CÁCH ĐỌC TỆP PDF BẰNG APACHE PDFBOX TRONG ANDROID
Thư viện Apache PDFBox là một công cụ Java mã nguồn mở để làm việc với các tài liệu PDF. Dự án này cho phép tạo các tài liệu PDF mới, thao tác với các tài liệu hiện có và khả năng trích xuất nội dung từ tài liệu.
Nếu bạn đã làm việc với PDF trong Android, bạn sẽ hiểu rằng có một số tùy chọn hạn chế khi làm việc với PDF trong Android.
Hầu hết SDK có sẵn trong Android là SDK thương mại hoặc một phần giấy phép theo GPLV giới hạn nguồn đóng.
Chúng ta sẽ không tập trung vào SDK PDF có sẵn trên thị trường như PDFTRON , KdanMobile và Foxit .
Đúng hơn Java có một thư viện PDF mã nguồn mở được cung cấp bởi Apache - Apache PDFBox. Bạn có thể đọc thêm về PDFBox tại đây .
Không thể sử dụng tệp Java PDFBox .jar trong dự án Android vì nó chứa một số API Java (như Swing) không được hỗ trợ trong Android.
Thư viện Apache PDFBox là một công cụ Java mã nguồn mở để làm việc với các tài liệu PDF.
Dự án này cho phép tạo các tài liệu PDF mới, thao tác với các tài liệu hiện có và khả năng trích xuất nội dung từ tài liệu.
PDFBox Apache Android mà chúng ta sẽ sử dụng trong ứng dụng này là PDFBox-Android .
Dưới đây là ảnh chụp màn hình của ứng dụng chúng ta sẽ tạo.
1. TẠO DỰ ÁN ANDROID MỚI
- Mở Android Studio
- Chuyển đến file menu
- Chọn new option
- Nhập tên project
- Nhập tên activity
- Giữ các cài đặt mặc định khác
- Click vào nút finish để tạo một dự án Android mới
2. THÊM PERMISSION
Vì việc truy cập Android storage API cần có quyền, chúng ta sẽ thêm mã này vào tệp manifest.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3. THÊM THƯ VIỆN BÊN THỨ BA ANDROID
Chúng ta sẽ thêm một số thư viện android sẽ giúp chúng ta giải quyết một số vấn đề.
Mở dự án build.gradle của bạn và thêm các thư viện bên dưới.
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.0"
defaultConfig {
applicationId "com.inducesmile.apachepdfbox"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.3.0-alpha02'
//PDFBox android
implementation 'com.tom_roush:pdfbox-android:1.8.10.1'
//File picker
implementation 'com.github.jaiselrahman:FilePicker:1.3.2'
implementation 'com.jakewharton:butterknife:10.2.1'
annotationProcessor "com.jakewharton:butterknife-compiler:10.2.1"
implementation 'com.karumi:dexter:5.0.0'
//Lombok
compileOnly 'org.projectlombok:lombok:1.18.8'
annotationProcessor 'org.projectlombok:lombok:1.18.8'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
4. TRIỂN KHAI BỘ CHỌN TỆP PDF TỪ THIẾT BỊ
Trong tệp build.gradle, chúng ta đã thêm một thư viện com.github.jaiselrahman:FilePicker:1.3.2
sẽ được sử dụng để chọn bất kỳ tệp PDF nào trong thiết bị.
Tạo một lớp java mới và đặt tên cho nó PDFFilePicker.java
.
public class PdfFilePicker {
public static Intent openPdf(Context context, int numOfFile){
String[] suffix = {"pdf", "Pdf", "PDF"};
Intent intent = new Intent(context, FilePickerActivity.class);
return intent.putExtra(FilePickerActivity.CONFIGS, new Configurations.Builder()
.setCheckPermission(true)
.setShowImages(false)
.setShowAudios(false)
.setShowVideos(false)
.setShowFiles(true)
.enableImageCapture(false)
.setMaxSelection(numOfFile)
.setSkipZeroSizeFiles(true)
.setSuffixes(suffix)
.build());
}
}
5. TẠO ACTIVITY MỚI
Tạo activity mới và đặt tên là ReadPdfActivity.
Mở tệp xml layout của activity.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".ReadPDFActivity">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="12dp"
android:gravity="center"
android:visibility="gone"
android:layout_marginTop="40dp"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@drawable/pdf"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/file_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text=""/>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:backgroundTint="@color/colorAccent"
android:src="@drawable/ic_baseline_add_24" />
</FrameLayout>
Trong lớp activity, chúng ta sẽ lấy các tham chiếu View từ tệp layout của chúng ta.
Khi click vào bộ chọn tệp, nó sẽ mở hộp thoại với danh sách các tệp. Sau khi người dùng chọn một tệp và click vào done, ứng dụng sẽ nhận được chi tiết và đường dẫn tệp PDF.
Cuối cùng, chúng ta sẽ tạo một đối tượng PDF bằng cách sử dụng load()
của PDDocument class.
public class ReadPDFActivity extends AppCompatActivity {
private static final String TAG = ReadPDFActivity.class.getSimpleName();
private Document document;
private static final int PDF_REQUEST_CODE = 2121;
@BindView(R.id.wrapper)
LinearLayoutCompat wrapper;
@BindView(R.id.file_name)
AppCompatTextView filename;
private PDDocument pdDocument;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.setTitle("Read PDF File");
}
}
@OnClick(R.id.fab)
public void onOpenFilePicker(View view){
Log.d(TAG, "Working");
Intent intent = PdfFilePicker.openPdf(this, 1);
startActivityForResult(intent, PDF_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == PDF_REQUEST_CODE) {
getFileInStorage(data);
}
}
private void getFileInStorage(@Nullable Intent data) {
if (data != null) {
ArrayList<MediaFile> mediaFileArrayList = data.getParcelableArrayListExtra(FilePickerActivity.MEDIA_FILES);
if (mediaFileArrayList != null) {
MediaFile mediaFile = mediaFileArrayList.get(0);
String filePath = Helper.getPath(this, mediaFile.getUri());
if (!TextUtils.isEmpty(filePath) || filePath != null){
File file = new File(filePath);
document = new Document(file.getName(), Helper.formatSize(file.length()), Helper.formatDate(file.lastModified()), file.getAbsolutePath());
Log.d(TAG, "Selected Filename = " + document.getDocumentName());
//show or hide
showOrHidePDFIcon();
}
}
}
}
private void showOrHidePDFIcon(){
if (document != null){
wrapper.setVisibility(View.VISIBLE);
filename.setText(document.getDocumentName());
//Read and show text
runOnUiThread(new Runnable()
{
@Override
public void run(){
try {
readPDFContent();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
private void readPDFContent() throws IOException {
if (document != null){
File file = new File(document.getDocumentPath());
if (file.exists()){
pdDocument = PDDocument.load(file);
PDFTextStripper pdfTextStripper = new PDFTextStripper();
String textContent = pdfTextStripper.getText(pdDocument);
if (!TextUtils.isEmpty(textContent)){
//Log the text content of the PDF file
Log.d(TAG, textContent);
}
}
}
}
private void readPDFContentPageByPage() throws IOException {
if (document != null){
File file = new File(document.getDocumentPath());
if (file.exists()){
pdDocument = PDDocument.load(file);
PDFTextStripper pdfTextStripper = new PDFTextStripper();
for (int i = 0; i < pdDocument.getNumberOfPages(); i++){
pdfTextStripper.setStartPage(i);
pdfTextStripper.setEndPage(i);
String pageTextContent = pdfTextStripper.getText(pdDocument);
if (!TextUtils.isEmpty(pageTextContent)){
//Log the text content of the PDF file
Log.d(TAG, pageTextContent);
}
}
}
}
}
}
5. TẠO CLASS HELPER
Tạo một lớp Java mới và đặt tên cho nó Helper.Java
. Lớp này sẽ chứa một số phương thức quan trọng mà chúng ta cần.
Mở lớp java và thêm thông tin bên dưới vào nó.
public class Helper {
public static String formatDate(long milliseconds) {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+1"));
return dateFormat.format(new Date(milliseconds));
}
public static String formatSize(long bytes) {
DecimalFormat sizeFormat = new DecimalFormat("0.00");
return sizeFormat.format(bytes/1048576.0).concat(" MB");
}
public static String getPath(Activity activity, Uri uri) {
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = activity.getContentResolver().query(uri, projection, null, null, null);
if (cursor == null) return null;
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String s = cursor.getString(column_index);
cursor.close();
return s;
}
}
Trong bài tiếp theo, chúng ta sẽ tìm hiểu cách tạo tệp PDF mới trong Android bằng Apache PDFBox.
Theo dõi VnCoder trên Facebook, để cập nhật những bài viết, tin tức và khoá học mới nhất!