CÁCH TẠO VÀ THÊM NỘI DUNG VÀO TỆP PDF BẰNG APACHE PDFBOX TRONG ANDROID

Đăng bởi: Admin | Lượt xem: 1513 | Chuyên mục: Android

Trong hướng dẫn trước chúng ta đã tìm hiểu cách đọc tệp PDF trong. Hôm nay, chúng ta sẽ học cách tạo một tệp PDF mới và thêm nội dung vào tệp PDF.


Nếu bạn chưa đọc hướng dẫn trước , thì bạn nên đọc để làm được bài này.

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.

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'

    //loading
    implementation 'com.github.d-max:spots-dialog:1.1@aar'

    //RxAndroid
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
    implementation "io.reactivex.rxjava2:rxjava:2.2.10"

    //Pdf viewer
    implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'

    //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'
}

Ta đã thêm nhiều thư viện hơn như RxJava, RxAndroid, PDFViewer và ProgressView.

4.  TẠO ACTIVITY MỚI

Tạo activity mới và đặt tên là WritePdfActivity hoặc bất kỳ tên nào bạn chọn.

Mở tệp bố cục xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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"
    android:orientation="vertical"
    android:background="#f3f3f3"
    android:padding="12dp"
    tools:context=".WritePdfActivity">

    <androidx.appcompat.widget.AppCompatEditText
        android:id="@+id/content_box"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:inputType="text"
        android:hint="Enter PDF content"/>

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/create_pdf"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:textColor="@color/colorWhite"
        android:layout_marginTop="12dp"
        android:text="CREATE PDF"/>

    <com.github.barteksc.pdfviewer.PDFView
        android:id="@+id/pdf_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="12dp"/>

</androidx.appcompat.widget.LinearLayoutCompat>

Tệp layout chứa EditText, Button và PDFView.

Khi người dùng nhập văn bản và click vào nút tạo PDF, văn bản sẽ được trả về và được sử dụng để tạo tệp PDF mới.

5.  TẠO LỚP VIEWMODEL MỚI

Tiếp theo, chúng ta sẽ tạo một lớp Java mới sẽ kế thừa từ lớp ViewModel của Android.

Chúng ta sẽ tạo một phương thức chấp nhận văn bản và đường dẫn tệp làm tham số.

Mở lớp Java đã tạo.

@Setter
@Getter
public class PDFViewModel extends ViewModel {

    private static final String TAG = PDFViewModel.class.getSimpleName();

    private CompositeDisposable compositeDisposable;

    private MutableLiveData<Boolean> isLoading;

    public PDFViewModel() {
        compositeDisposable = new CompositeDisposable();
        isLoading = new MutableLiveData<>(false);
    }

    public void writeToPDFFile(String pdfFilePath, String pdfContent){
        Completable.create(new CompletableOnSubscribe() {
            @Override
            public void subscribe(CompletableEmitter emitter) throws Exception {
                openAndWriteToPDFFile(pdfFilePath, pdfContent);
                emitter.onComplete();
            }
        }).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new CompletableObserver() {
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onComplete() {
                isLoading.setValue(true);
                Log.d(TAG, "Completed");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "Error message " + e.getLocalizedMessage());
            }
        });
    }

    private void openAndWriteToPDFFile(String pdfFilePath, String pdfContent){
        PDDocument pdDocument = new PDDocument();
        PDPage page = new PDPage();
        pdDocument.addPage(page);

        try {
            PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page);
            contentStream.beginText();
            contentStream.setFont(PDType1Font.COURIER_BOLD, 18);
            contentStream.setLeading(16f);
            contentStream.newLineAtOffset(30, 600);
            contentStream.showText(pdfContent);
            contentStream.endText();
            contentStream.close();

            Log.d(TAG, "File Path Log " + pdfFilePath);
            pdDocument.save(new File(pdfFilePath));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

6.  MỞ LỚP ACTIVITY

Trong lớp activity, chúng ta nhận được tất cả các tham chiếu đến các view trong tệp layout

Chúng ta sẽ đính kèm sự kiện onclick vào button. Sau khi người dùng nhập văn bản và click vào nút, phương thức writeToPDFFile(String pdfFilePath, String pdfContent) được gọi.

Mã hoàn chỉnh cho activity được hiển thị bên dưới

public class WritePdfActivity extends AppCompatActivity {

    private static final String TAG = WritePdfActivity.class.getSimpleName();

    private File fileStorage;

    private static String FILE_PATH_NAME;

    private PDFViewModel viewModel;

    @BindView(R.id.content_box)
    AppCompatEditText contentBox;

    @BindView(R.id.pdf_view)
    PDFView pdfView;

    private AlertDialog progressView;

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

        ButterKnife.bind(this);
        permissionRequest();

        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null){
            actionBar.setTitle("Create New PDF File");
        }
        PDFBoxResourceLoader.init(this);

        viewModel = ViewModelProviders.of(this).get(PDFViewModel.class);
        progressView = new SpotsDialog.Builder().setContext(this).setCancelable(false).setMessage("Processing...").build();

        fileStorage = getExternalFilesDir("PDF");
        if (fileStorage != null){
            if(!fileStorage.exists()){
                fileStorage.mkdir();
            }
            FILE_PATH_NAME = fileStorage.getAbsolutePath() + File.separator + "text.pdf";
        }
    }

    private void permissionRequest() {
        Dexter.withActivity(this).withPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .withListener(new MultiplePermissionsListener() {
                    @Override
                    public void onPermissionsChecked(MultiplePermissionsReport report) {
                        if (report.areAllPermissionsGranted()) {
                            //do work when permission is granted
                        }else if (report.isAnyPermissionPermanentlyDenied()) {
                            Log.d(TAG, "Permission has been granted");
                        }
                    }
                    public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                        token.continuePermissionRequest();
                    }
                })
                .withErrorListener(new PermissionRequestErrorListener() {
                    @Override
                    public void onError(DexterError error) {
                        Log.e(TAG, error.toString());
                    }
                })
                .onSameThread()
                .check();
    }

    @OnClick(R.id.create_pdf)
    public void createNewPDF(View view){
        String content = Objects.requireNonNull(contentBox.getText()).toString();
        if (TextUtils.isEmpty(content)){
            Toast.makeText(this, "Content box must be filled", Toast.LENGTH_SHORT).show();
        }else{
            writeNewPDFContent(pdfView, content);
        }
    }

    private void writeNewPDFContent(PDFView pdfView, String pdfContent){
        progressView.show();
        viewModel.writeToPDFFile(FILE_PATH_NAME, pdfContent);
        viewModel.getIsLoading().observe(this, new Observer<Boolean>() {
            @Override
            public void onChanged(Boolean aBoolean) {
                if (aBoolean){
                    // View the new PDF file
                    progressView.dismiss();
                    getPdfConfigurator(pdfView, FILE_PATH_NAME);
                }else{
                    progressView.dismiss();
                    Log.d(TAG, "Something has gone wrong");
                }
            }
        });
    }

    public void getPdfConfigurator(PDFView pdfView, String filePath) {
        PDFView.Configurator configurator = null;
        File file = new File(filePath);
        if (file.exists()){
            configurator = pdfView.fromFile(new File(filePath))
                    .enableDoubletap(true)
                    .enableSwipe(true)
                    .swipeHorizontal(true)
                    .enableAnnotationRendering(true)
                    .pageFitPolicy(FitPolicy.BOTH)
                    .fitEachPage(true)
                    .spacing(2);
        }
        if (configurator != null){
            configurator.load();
        }
    }
}

Trong các hướng dẫn tiếp theo, chúng ta sẽ trình bày cách thao tác với PDF trong Android như hợp nhất nhiều tệp PDF, nén PDF, v.v.

vncoder logo

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!



Khóa học liên quan

Khóa học: Android

Học Kotlin cơ bản
Số bài học:
Lượt xem: 17033
Đăng bởi: Admin
Chuyên mục: Android

Học lập trình Flutter cơ bản
Số bài học:
Lượt xem: 54934
Đăng bởi: Admin
Chuyên mục: Android

Lập trình Android cơ bản
Số bài học:
Lượt xem: 22134
Đăng bởi: Admin
Chuyên mục: Android