Skip to content
全新发布

PDF SDK 与 AI 文档处理

在 GitHub 获取完整的私有化部署SDK 包及 AI 智能文档处理能力,一键部署,快速构建您的文档处理工作流。

Guides

如何用Java开发一个Android PDF阅读器

本节将帮助您快速开始使用 ComPDF SDK,并通过分步说明使用 Java 制作 Android 应用程序。通过以下步骤,您将获得一个简单的应用程序,可以显示指定 PDF 文件的内容。

创建新项目

  1. 使用 Android Studio 创建一个 Phone and Table 项目。这里我们创建一个 No Activity 项目。

create_project.png

添加 ComPDF SDK 包

首先,我们需要导入 ComPDF SDK。您可以通过两种方式集成它:使用 Gradle 集成手动集成

Gradle 集成

  1. 打开位于项目根目录中的 "settings.gradle" 文件,然后添 加 mavenCentral 存储库:
diff
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
+       mavenCentral()
    }
}
  1. 在应用程序模块目录中打开 "build.gradle" 文件:
2.4.2.1-1

编辑它并添加完整的 ComPDF SDK 依赖项:

groovy
dependencies {
  implementation 'com.compdf:compdfkit:2.6.9'
  implementation 'com.compdf:compdfkit-ui:2.6.9'
}
  1. AndroidManifest.xml中申请读写权限:
xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

注: 对于面向 Android 6.0 或更高版本的应用程序,请确保在运行时检查并请求外部存储的读写权限。

  1. 如果您使用了在线认证的许可证,请在 AndroidManifest.xml中添加网络访问权限:
xml
<uses-permission android:name="android.permission.INTERNET"/>

手动集成

  1. "ComPDFKit.aar""ComPDFKit-UI.aar" 复制到 app"libs" 目录中。

libs.png

  1. 将以下代码添加到 app 目录下的 "build.gradle" 文件中:
groovy
...
dependencies {
    /*ComPDF SDK*/
    implementation(fileTree('libs'))
    ...
}
...
  1. 将 ComPDF SDK for Android 作为项目的依赖项添加进去。在 app 目录下的 "build.gradle" 文件中,将 "ComPDFKit.aar""ComPDFKit-UI.aar" 以及相关的支持库添加到 dependencies 中。为了简化操作,您可以按照以下方式更新依赖项:
groovy
dependencies {
    ...
    //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. AndroidManifest.xml中申请读写权限:
xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

注: 对于面向 Android 6.0 或更高版本的应用程序,请确保在运行时检查并请求外部存储的读写权限。

应用许可证密钥

具体步骤请参考应用许可证密钥

添加混淆

在 "proguard-rules.pro" 文件中,请添加 ComPDF 的混淆配置信息如下:

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

显示PDF文档

  1. 将 PDF 文档复制到 Android 项目的 assets 目录中。例如,将文件 "Quick Start Guide.pdf" 导入到路径 src/main/assets 中。

structure.png

  1. 在您的包下创建一个新的 Empty Activity,并将该 Activity 的名称设置为 MainActivity

new_activity.png

Android Studio将自动生成一个名为 "MainActivity.java" 的 source 文件和一个名为 "activity_main.xml" 的 layout 文件。

Source文件:

activity_java.png

Layout文件:

layout.png

  1. "activity_main.xml" 中创建一个 CPDFReaderView 来显示 PDF 文档的内容:
xml
<?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">

    <!-- 创建一个 CPDFReaderView -->
    <com.compdfkit.ui.reader.CPDFReaderView
        android:id="@+id/readerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

从布局中获取 CPDFReaderView 或者直接在对应的 MainActivity.java 文件中的代码中创建一个 CPDFReaderView

Java
// 你的 MainActivity.java 文件。

package com.compdfkit.pdfviewer;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 从xml中获取CPDFReaderView
        CPDFReaderView readerView = findViewById(R.id.readerview);
        // 创建CPDFReaderView的代码。
        // CPDFDocument readerView = new CPDFReaderView(content);
    }
}
kotlin
// 你的 MainActivity.kt 文件。
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)

        // 从xml中获取CPDFReaderView
        val readerView = findViewById<CPDFReaderView>(R.id.readerview)
        // 创建CPDFReaderView的代码。
        // CPDFDocument readerView = new CPDFReaderView(content);
    }
}
  1. 打开文档。这是一个耗时的过程,因此需要在子线程中执行。文档成功打开后,会初始化渲染 PDF 的 UI:
Java
// 你的 MainActivity.java 文件。

... //导入。

public class MainActivity extends AppCompatActivity {

    // 将PDF文件从资源文件夹复制到缓存文件夹。
    private void copyPdfFromAssetsToCache(String fileName) {
        try {
            InputStream inputStream = getAssets().open(fileName);
            File outputFile = new File(getCacheDir(), fileName);
            FileOutputStream outputStream = new FileOutputStream(outputFile);

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            inputStream.close();
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CPDFReaderView readerView = findViewById(R.id.readerview);
        // 创建CPDFReaderView的代码。
        // CPDFDocument readerView = new CPDFReaderView(content);

        // 创建文档对象。
        CPDFDocument document = new CPDFDocument(this);
      

        new Thread(() -> {
            String fileName = "Quick Start Guide.pdf";
            copyPdfFromAssetsToCache(fileName);

            File file = new File(getCacheDir(), fileName);
            String filePath = file.getAbsolutePath();

            // 打开文档。
            CPDFDocument.PDFDocumentError error = document.open(filePath);
            if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorPassword) {
                // 该文档已加密,需要密码才能打开。
                error = document.open(filePath, "password");
            }

            if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
                // 文档已成功打开,并且可以对数据进行解析和操作。
            } else {
                //无法打开PDF文件。具体错误可以参考API文件。
            }
        }).start();
    }
}
kotlin
// 你的 MainActivity.java 文件。

... //导入。

class MainActivity : AppCompatActivity() {

  // 将PDF文件从资源文件夹复制到缓存文件夹。
  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)
    // 创建CPDFReaderView的代码。
    // CPDFDocument readerView = new CPDFReaderView(content);

    // 创建文档对象。
    val document = CPDFDocument(this)

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

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

      // 打开文档。
      var error = document.open(filePath)
      if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorPassword) {
        // 该文档已加密,需要密码才能打开。
        error = document.open(filePath, "password")
      }
      if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
        // 文档已成功打开,并且可以对数据进行解析和操作。
      } else {
        // 无法打开PDF文件。具体错误可以参考API文件。
      }
    }.start()
  }
}
  1. 设置 CPDFReaderView的基本属性:
Java
// 你的 MainActivity.java 文件。

... // 导入。

public class MainActivity extends AppCompatActivity {
    // 创建一个处理程序以在主线程上运行代码。
    private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
...
    if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
        // 文档已成功打开,并且可以对数据进行解析和操作。
        mainThreadHandler.post(() -> {
            // 设置UI的文档内容。
            readerView.setPDFDocument(document);
        });
    } else {
        // 无法打开PDF文件。具体错误可以参考API文件。
    }
...
}
kotlin
// 你的 MainActivity.java 文件。

... // 导入。

public class MainActivity : AppCompatActivity() {
    // 创建一个处理程序以在主线程上运行代码。
    private var mainThreadHandler =  Handler(Looper.getMainLooper());
    ...
    if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
         // 文档已成功打开,并且可以对数据进行解析和操作。
        mainThreadHandler.post {
            // 设置UI的文档内容。
            readerView.setPDFDocument(document);
        }
    } else {
        // 无法打开PDF文件。具体错误可以参考API文件。
    }
    ...
}
  1. 在这个阶段,您的代码会像下面展示的这样:
Java
// 你的 MainActivity.java 文件。

... // 导入。

public class MainActivity extends AppCompatActivity {
    // 创建一个处理程序,在主线程上运行代码。

    private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
    // 将PDF文件从资源文件夹复制到缓存文件夹。
    private void copyPdfFromAssetsToCache(String fileName) {
        try {
            InputStream inputStream = getAssets().open(fileName);
            File outputFile = new File(getCacheDir(), fileName);
            FileOutputStream outputStream = new FileOutputStream(outputFile);

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            inputStream.close();
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CPDFReaderView readerView = findViewById(R.id.readerview);

        // 创建文档对象。
        CPDFDocument document = new CPDFDocument(this);

        new Thread(() -> {
            String fileName = "Quick Start Guide.pdf";
            copyPdfFromAssetsToCache(fileName);

            File file = new File(getCacheDir(), fileName);
            String filePath = file.getAbsolutePath();

            // 打开文档。
            CPDFDocument.PDFDocumentError error = document.open(filePath);
            if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorPassword) {
                // 该文档已加密,需要密码才能打开。
                error = document.open(filePath, "password");
            }

            if (error == CPDFDocument.PDFDocumentError.PDFDocumentErrorSuccess) {
                // 文档已成功打开,并且可以对数据进行解析和操作。
                mainThreadHandler.post(() -> {
                    // 将文档设置为阅读器视图。
                    readerView.setPDFDocument(document);
                });
            } else {
                // 无法打开PDF文件。具体错误可以参考API文件。
            }
        }).start();
    }
}
kotlin
// 你的 MainActivity.java 文件。

... // 导入。

class MainActivity : AppCompatActivity() {
    // 创建一个处理程序,在主线程上运行代码。
    private val mainThreadHandler = Handler(Looper.getMainLooper())

    // 将PDF文件从资源文件夹复制到缓存文件夹。
    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)

        // 创建文档对象。
        val document = CPDFDocument(this)
        Thread {
            val fileName = "Quick Start Guide.pdf"
            copyPdfFromAssetsToCache(fileName)
            val file = File(cacheDir, fileName)
            val filePath = file.absolutePath

            // 打开文档。
            var error = document.open(filePath)
            if (error == PDFDocumentError.PDFDocumentErrorPassword) {
                // 该文档已加密,需要密码才能打开。
                error = document.open(filePath, "password")
            }
            if (error == PDFDocumentError.PDFDocumentErrorSuccess) {
                // 文档已成功打开,并且可以对数据进行解析和操作。
                mainThreadHandler.post {
                    // 将文档设置为阅读器视图。
                    readerView.pdfDocument = document
                }
            } else {
                // 无法打开PDF文件。具体错误可以参考API文件。
            }
        }.start()
    }
}
xml
<!-- 你的 activity_main.xml 文件 -->
<?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>
  1. 运行应用程序。
2.4.2.1-1

现在,借助ComPDF的帮助,您获得了一个简单的应用程序来显示PDF文件。

问题排除

  1. 无法打开 PDF 文件

    我们向您提供的许可证是与您的应用程序 ID 绑定的,因此请确保所获取的许可证与您的应用程序 ID 匹配。

  2. 其它问题

    如果您在集成 ComPDF SDK for Android 时遇到其他问题,请随时联系 ComPDF 团队。