Tutorials

How to Build an Android PDF Viewer or Editor in Kotlin

By ComPDFKit | Fri. 21 Apr. 2023
AndroidKotlin

Quote: “How to show a PDF file and edit content in Android? I want to open a PDF file locally and then I show the PDF content if the user copies any text then I want to get the copied text. So please suggest to me any API or solution related to this problem” - from Reddit.

 

ComPDFKit for Android is such a solution for developers to build an Android PDF viewer and editor to open PDF files, edit PDF content, and control the PDF content. In this guide, we'll dive into the steps required to integrate ComPDFKit into your Android project. You will know how to build a fully functional PDF reader and editor using Kotlin, leveraging the robust features of ComPDFKit.

 

Windows   Web   Android   iOS   Mac   Server   React Native   Flutter   Electron
30-day Free

 

 

Requirements for Building Android PDF Viewer & Editor

 

ComPDFKit PDF SDK is supported on Android devices running API level 19 or newer and targeting the latest stable Android version 4.4 or higher. Furthermore, ComPDFKit PDF SDK requires apps to enable Java 8 language features to build.

 

 

Get License and Package of ComPDFKit for Android

 

Windows   Web   Android   iOS   Mac   Server   React Native   Flutter   Electron
30-day Free

 

Before you Apply the Steps below, get the package and license of ComPDFKit for Android first.

 

  • Get the free license

It’s easy to get the free license of ComPDFKit for Android. Without consulting sales, the license will be sent to your email inbox after choosing the platform and inputting your receiving email. 

 

Get the License of ComPDFKit for Android

 

  • Get the package

Download the package of ComPDFKit for Android.

 

 

Step 1: Create a New Android Project

 

  1. Use Android Studio to create a Phone & Tablet project, here we create a No Activity project.

 

Create a New Android Project

 

 

Step 2: Add the PDF Package of ComPDFKit Android Kotlin

 

  1. The first thing we need to do is to import ComPDFKit SDK. Copy ComPDFKit.aar and ComPDFKit-UI.aar to the libs directory of the app.

 

 

  1. Add the following code to the app dictionary’s build.gradle file:
...
dependencies {
    /*ComPDFKit SDK*/
    implementation(fileTree('libs'))
    ...
}
...
  1. Add ComPDFKit PDF SDK for Android as a dependency in the project. Inside the app dictionary’s build.gradle, add ComPDFKit.aar, ComPDFKit-UI.aar, and the related support libraries to the dependencies. For simplicity, update the dependencies as follows:
dependencies {
    ...
    // Add Kotlin coroutines dependencies
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'

    // glide
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'

    implementation 'androidx.documentfile:documentfile:1.0.1'
}
  1. Apply for read and write permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Note: On your apps that target Android 6.0 or higher, make sure to check for and request read and write permissions to external storage at runtime.

 

  1. If you use an online license, please add network access permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>



Step 3: Apply the License Key for Android PDF Viewer

 

Get the ComPDFKit license online directly from ComPDFKit pricing page and add this license in the AndroidManifest.xml of the main module. In version 1.13.0, we introduced a brand-new online authentication license scheme for ComPDFKit SDK. By default, the SDK performs online authentication. If you are using a version prior to 1.13.0, please refer to the following example to configure the SDK for offline authentication mode:

 

  • Online license
<!-- Each ComPDFKit license is bound to a specific applicationId -->
<!-- For example: com.compdfkit.pdfviewer -->
<meta-data
    android:name="compdfkit_key_online"
    android:value="Your ComPDFKit Key" />

You can also initialize ComPDFKit SDK in code using:

CPDFSdk.init(context, "your compdfkit license", false);

 

  • Offline license
<!-- Each ComPDFKit license is bound to a specific applicationId -->
<!-- For example: com.compdfkit.pdfviewer -->
<meta-data
    android:name="compdfkit_key"
    android:value="Your ComPDFKit Key" />

You can also initialize ComPDFKit SDK in code using:

CPDFSdk.init(context, "your compdfkit license");

 

 

Step 4: Add Proguard Rules

 

In the proguard-rules.pro file, please add the obfuscation configuration information for compdfkit as follows:

-keep class com.compdfkit.ui.** {*;}
-keep class com.compdfkit.core.** {*;}



Step 5: Display a PDF Document

 

When you finish the steps in this part, you will get an Android PDF viewer below:

 

 

  1. Copy a PDF document into the assets directory of your Android project. For example, import the file Quick Start Guide.pdf to the path src/main/assets.
  2. Create a new Empty Activity under your package, and set the activity name to MainActivity.

Android Studio will automatically generate a source file called MainActivity.kt and a layout file called activity_main.xml.

  • The source file:

The source file of ComPDFKit

 

  • The layout file:

The layout file of ComPDFKit

 

3. Create a CPDFReaderView in your activity_main.xml to display the contents of the PDF document:

<!-- Your activity_main.xml file -->

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!-- Create a CPDFReaderView -->
    <com.compdfkit.ui.reader.CPDFReaderView
        android:id="@+id/readerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Get the CPDFReaderView from the layout or create a CPDFReaderView directly in the code in the corresponding MainActivity.kt file:

// Your MainActivity.kt file
package com.compdfkit.pdfviewer

import androidx.appcompat.app.AppCompatActivity

import android.os.Bundle
import com.compdfkit.ui.reader.CPDFReaderView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Get CPDFReaderView from xml.
        val readerView = findViewById<CPDFReaderView>(R.id.readerview)
        // Code to create CPDFReaderView.
        // CPDFDocument readerView = new CPDFReaderView(content);
    }
}

 

4. Open the document. This is a time-consuming process, so it needs to be executed in a sub-thread. After the document is opened successfully, the UI that renders the PDF is initiated:

// Your MainActivity.kt file

... //imports

class MainActivity : AppCompatActivity() {

  // Copy the PDF file from the assets folder to the cache folder.
  private fun copyPdfFromAssetsToCache(fileName: String) {
    try {
      val inputStream = assets.open(fileName)
      val outputFile = File(cacheDir, fileName)
      val outputStream = FileOutputStream(outputFile)

      val buffer = ByteArray(1024)
      var bytesRead: Int
      while (inputStream.read(buffer).also { bytesRead = it } != -1) {
        outputStream.write(buffer, 0, bytesRead)
      }
      inputStream.close()
      outputStream.flush()
      outputStream.close()
    } catch (e: IOException) {
      e.printStackTrace()
    }
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val readerView = findViewById<CPDFReaderView>(R.id.readerview)
    // Code to create CPDFReaderView.
    // CPDFDocument readerView = new CPDFReaderView(content);

    //Create a document object.
    val document = CPDFDocument(this)

    Thread {
      val fileName = "Quick Start Guide.pdf"
      copyPdfFromAssetsToCache(fileName)

      val file = File(cacheDir, fileName)
      val filePath = file.absolutePath

      //Open document.
      var error = document.open(filePath)
      if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorPassword) {
        //The document is encrypted and requires a password to open.
        error = document.open(filePath, "password")
      }
      if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
        //The document is opened successfully and data can be parsed and manipulated.
      } else {
        //The PDF file failed to open. You can refer to the API file for specific error
      }
    }.start()
  }
}

 

5. Set the basic properties of CPDFReaderView:

// Your MainActivity.kt file

... // imports

public class MainActivity : AppCompatActivity() {
    // Create a handler to run the code on the main thread.
    private var mainThreadHandler =  Handler(Looper.getMainLooper());
    ...
    if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
        // The document is opened successfully and data can be parsed and manipulated.
        mainThreadHandler.post {
            // Set the document content for UI.
            readerView.setPDFDocument(document);
        }
    } else {
        // The PDF file failed to open. You can refer to the API file for specific error
    }
    ...
}

 

6. Your code may resemble the following at this stage:

// Your MainActivity.kt file

... // imports

class MainActivity : AppCompatActivity() {
    // Create a handler to run the code on the main thread.
    private val mainThreadHandler = Handler(Looper.getMainLooper())

    // Copy the PDF file from the assets folder to the cache folder.
    private fun copyPdfFromAssetsToCache(fileName: String) {
        try {
            val inputStream = assets.open(fileName)
            val outputFile = File(cacheDir, fileName)
            val outputStream = FileOutputStream(outputFile)
            val buffer = ByteArray(1024)
            var bytesRead: Int
            while (inputStream.read(buffer).also { bytesRead = it } != -1) {
                outputStream.write(buffer, 0, bytesRead)
            }
            inputStream.close()
            outputStream.flush()
            outputStream.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val readerView = findViewById<CPDFReaderView>(R.id.readerview)

        //Create a document object.
        val document = CPDFDocument(this)
        Thread {
            val fileName = "Quick Start Guide.pdf"
            copyPdfFromAssetsToCache(fileName)
            val file = File(cacheDir, fileName)
            val filePath = file.absolutePath

            //Open document.
            var error = document.open(filePath)
            if (error == PDFDocumentError.PDFDocumentErrorPassword) {
                //The document is encrypted and requires a password to open.
                error = document.open(filePath, "password")
            }
            if (error == PDFDocumentError.PDFDocumentErrorSuccess) {
                //The document is opened successfully and data can be parsed and manipulated.
                mainThreadHandler.post {
                    //Set the document to the reader view.
                    readerView.pdfDocument = document
                }
            } else {
                //The PDF file failed to open. You can refer to the API file for specific error
            }
        }.start()
    }
}
<!-- Your activity_main.xml file -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.compdfkit.ui.reader.CPDFReaderView
        android:id="@+id/readerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

7. If you want to get a PDF editor, you can change the mode with the instructions on ComPDFKit android developer guides.



Troubleshooting

 

  1. Unable to Open the PDF Files
    The license we provide to you is tied to your application ID, so ensure that the license acquired matches your application ID.
  2. Other Problems

If you encounter some other problems when integrating our ComPDFKit PDF SDK for Android, please visit our FAQ page first. If your problem can’t be solved, please feel free to contact our technical support team or open an issue on GitHub. Our R&D team will answer your question and respond as soon as possible.

 

Windows   Web   Android   iOS   Mac   Server   React Native   Flutter   Electron
30-day Free