Browse Source

PDFSamples(Android) - 1.Samples 示例

liuxiaolong 1 year ago
parent
commit
2cdbf455fe
67 changed files with 3619 additions and 0 deletions
  1. 1 0
      samples/.gitignore
  2. 43 0
      samples/build.gradle
  3. 21 0
      samples/proguard-rules.pro
  4. 26 0
      samples/src/androidTest/java/com/compdfkit/samples/ExampleInstrumentedTest.java
  5. 55 0
      samples/src/main/AndroidManifest.xml
  6. BIN
      samples/src/main/assets/Bird.wav
  7. BIN
      samples/src/main/assets/CommonFivePage.pdf
  8. BIN
      samples/src/main/assets/CreateAnnotationTest.pdf
  9. BIN
      samples/src/main/assets/ImageExtractTest.pdf
  10. BIN
      samples/src/main/assets/text.pdf
  11. 118 0
      samples/src/main/java/com/compdfkit/samples/PDFSamples.java
  12. 75 0
      samples/src/main/java/com/compdfkit/samples/SampleApplication.java
  13. 103 0
      samples/src/main/java/com/compdfkit/samples/SampleDetailActivity.java
  14. 34 0
      samples/src/main/java/com/compdfkit/samples/SampleListActivity.java
  15. 72 0
      samples/src/main/java/com/compdfkit/samples/SampleListAdapter.java
  16. 71 0
      samples/src/main/java/com/compdfkit/samples/samples/AnnotationImportExportTest.java
  17. 513 0
      samples/src/main/java/com/compdfkit/samples/samples/AnnotationTest.java
  18. 121 0
      samples/src/main/java/com/compdfkit/samples/samples/BackgroundTest.java
  19. 116 0
      samples/src/main/java/com/compdfkit/samples/samples/BatesTest.java
  20. 56 0
      samples/src/main/java/com/compdfkit/samples/samples/BookmarkTest.java
  21. 88 0
      samples/src/main/java/com/compdfkit/samples/samples/DocumentInfoTest.java
  22. 95 0
      samples/src/main/java/com/compdfkit/samples/samples/EncryptTest.java
  23. 48 0
      samples/src/main/java/com/compdfkit/samples/samples/FlattenTest.java
  24. 150 0
      samples/src/main/java/com/compdfkit/samples/samples/HeaderFooterTest.java
  25. 56 0
      samples/src/main/java/com/compdfkit/samples/samples/ImageExtractTest.java
  26. 316 0
      samples/src/main/java/com/compdfkit/samples/samples/InteractiveFormsTest.java
  27. 103 0
      samples/src/main/java/com/compdfkit/samples/samples/OutlineTest.java
  28. 76 0
      samples/src/main/java/com/compdfkit/samples/samples/PDFATest.java
  29. 204 0
      samples/src/main/java/com/compdfkit/samples/samples/PDFPageTest.java
  30. 63 0
      samples/src/main/java/com/compdfkit/samples/samples/PDFRedactTest.java
  31. 76 0
      samples/src/main/java/com/compdfkit/samples/samples/PDFToImageTest.java
  32. 111 0
      samples/src/main/java/com/compdfkit/samples/samples/TextExtractTest.java
  33. 129 0
      samples/src/main/java/com/compdfkit/samples/samples/TextSearchTest.java
  34. 173 0
      samples/src/main/java/com/compdfkit/samples/samples/WatermarkTest.java
  35. 20 0
      samples/src/main/java/com/compdfkit/samples/util/CPDFGlideModule.java
  36. 34 0
      samples/src/main/java/com/compdfkit/samples/util/DateUtil.java
  37. 114 0
      samples/src/main/java/com/compdfkit/samples/util/FileUtils.java
  38. 59 0
      samples/src/main/java/com/compdfkit/samples/util/LoggingOutputListener.java
  39. 24 0
      samples/src/main/java/com/compdfkit/samples/util/OutputListener.java
  40. 5 0
      samples/src/main/res/drawable/baseline_arrow_back_24.xml
  41. 19 0
      samples/src/main/res/layout/activity_sample_list.xml
  42. 65 0
      samples/src/main/res/layout/fragment_sample_detail.xml
  43. 22 0
      samples/src/main/res/layout/layout_sample_list_item.xml
  44. 5 0
      samples/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  45. 5 0
      samples/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  46. BIN
      samples/src/main/res/mipmap-hdpi/ic_launcher.png
  47. BIN
      samples/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
  48. BIN
      samples/src/main/res/mipmap-hdpi/ic_launcher_round.png
  49. BIN
      samples/src/main/res/mipmap-mdpi/ic_launcher.png
  50. BIN
      samples/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
  51. BIN
      samples/src/main/res/mipmap-mdpi/ic_launcher_round.png
  52. BIN
      samples/src/main/res/mipmap-xhdpi/ic_launcher.png
  53. BIN
      samples/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
  54. BIN
      samples/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  55. BIN
      samples/src/main/res/mipmap-xxhdpi/ic_launcher.png
  56. BIN
      samples/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
  57. BIN
      samples/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  58. BIN
      samples/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  59. BIN
      samples/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
  60. BIN
      samples/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  61. 7 0
      samples/src/main/res/values-night/themes.xml
  62. 5 0
      samples/src/main/res/values/colors.xml
  63. 70 0
      samples/src/main/res/values/strings.xml
  64. 9 0
      samples/src/main/res/values/themes.xml
  65. 25 0
      samples/src/main/res/xml/tools_file_paths.xml
  66. 17 0
      samples/src/test/java/com/compdfkit/samples/ExampleUnitTest.java
  67. 1 0
      settings.gradle

+ 1 - 0
samples/.gitignore

@@ -0,0 +1 @@
+/build

+ 43 - 0
samples/build.gradle

@@ -0,0 +1,43 @@
+plugins {
+    id 'com.android.application'
+}
+
+android {
+    namespace 'com.compdfkit.samples'
+    compileSdk rootProject.ext.android.COMPILESDK
+
+    defaultConfig {
+        applicationId "com.compdfkit.viewer"
+        minSdk rootProject.ext.android.MINSDK
+        targetSdk rootProject.ext.android.TARGETSDK
+        versionCode rootProject.ext.android.VERSIONCODE as int
+        versionName rootProject.ext.sdk.COMPDFKit_SDK_VERSION
+
+    }
+
+    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 'androidx.appcompat:appcompat:1.6.1'
+    implementation 'com.google.android.material:material:1.9.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+    testImplementation 'junit:junit:4.13.2'
+
+    api project(path:':compdfkit-repo:compdfkit')
+    api project(path:':compdfkit-repo:compdfkit-ui')
+    api 'com.github.bumptech.glide:glide:4.15.1'
+    annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'
+
+    api 'androidx.documentfile:documentfile:1.0.1'
+}

+ 21 - 0
samples/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
samples/src/androidTest/java/com/compdfkit/samples/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.compdfkit.samples;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.compdfkit.samples", appContext.getPackageName());
+    }
+}

File diff suppressed because it is too large
+ 55 - 0
samples/src/main/AndroidManifest.xml


BIN
samples/src/main/assets/Bird.wav


BIN
samples/src/main/assets/CommonFivePage.pdf


BIN
samples/src/main/assets/CreateAnnotationTest.pdf


BIN
samples/src/main/assets/ImageExtractTest.pdf


BIN
samples/src/main/assets/text.pdf


+ 118 - 0
samples/src/main/java/com/compdfkit/samples/PDFSamples.java

@@ -0,0 +1,118 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples;
+
+
+import androidx.annotation.StringRes;
+
+import com.compdfkit.core.common.CPDFDocumentException;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+public abstract class PDFSamples {
+
+    protected static final String INPUT_PATH = "TestFiles/";
+
+    protected OutputListener outputListener;
+
+    private ArrayList<String> outputFileList;
+
+    private String title;
+
+    private String description;
+
+    public PDFSamples() {
+        title = "{title}";
+        description = "{description}";
+        outputFileList = new ArrayList<>();
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public void setTitle(@StringRes int titleResId) {
+        this.title = SampleApplication.getInstance().getString(titleResId);
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public void setDescription(@StringRes int descriptionResId) {
+        this.description = SampleApplication.getInstance().getString(descriptionResId);
+    }
+
+    public List<String> getOutputFileList() {
+        return outputFileList;
+    }
+
+    public String[] getOutputFileNames() {
+        String[] names = new String[outputFileList.size()];
+        outputFileList.toArray(names);
+        for (int i = 0; i < names.length; i++) {
+            File file = new File(names[i]);
+            names[i] = file.getName();
+        }
+        return names;
+    }
+
+    public void addFileList(String file) {
+        this.outputFileList.add(file);
+    }
+
+    protected void printHead() {
+        String head = SampleApplication.getInstance().getString(R.string.sample_header, title);
+        if (outputListener != null) {
+            outputListener.println(head);
+        }
+    }
+
+    protected void printFooter() {
+        String footer = SampleApplication.getInstance().getString(R.string.sample_footer);
+        if (outputListener != null) {
+            outputListener.println("\n" + footer);
+            outputListener.println("--------------------------------------------");
+        }
+    }
+
+    protected void run(OutputListener outputListener) {
+        this.outputListener = outputListener;
+        this.outputFileList.clear();
+    }
+
+    protected void saveSamplePDF(CPDFDocument document, File file, boolean close){
+        try {
+            file.getParentFile().mkdirs();
+            document.saveAs(file.getAbsolutePath(), false);
+            if (file.exists()) {
+                getOutputFileList().add(file.getAbsolutePath());
+            }
+            if (close){
+                document.close();
+            }
+        } catch (CPDFDocumentException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 75 - 0
samples/src/main/java/com/compdfkit/samples/SampleApplication.java

@@ -0,0 +1,75 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples;
+
+
+import android.app.Application;
+import android.media.Image;
+
+import com.compdfkit.samples.samples.AnnotationImportExportTest;
+import com.compdfkit.samples.samples.AnnotationTest;
+import com.compdfkit.samples.samples.BackgroundTest;
+import com.compdfkit.samples.samples.BatesTest;
+import com.compdfkit.samples.samples.BookmarkTest;
+import com.compdfkit.samples.samples.DocumentInfoTest;
+import com.compdfkit.samples.samples.EncryptTest;
+import com.compdfkit.samples.samples.FlattenTest;
+import com.compdfkit.samples.samples.HeaderFooterTest;
+import com.compdfkit.samples.samples.ImageExtractTest;
+import com.compdfkit.samples.samples.InteractiveFormsTest;
+import com.compdfkit.samples.samples.OutlineTest;
+import com.compdfkit.samples.samples.PDFATest;
+import com.compdfkit.samples.samples.PDFPageTest;
+import com.compdfkit.samples.samples.PDFRedactTest;
+import com.compdfkit.samples.samples.PDFToImageTest;
+import com.compdfkit.samples.samples.TextExtractTest;
+import com.compdfkit.samples.samples.TextSearchTest;
+import com.compdfkit.samples.samples.WatermarkTest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SampleApplication extends Application {
+
+    private static SampleApplication application;
+
+    public List<PDFSamples> samplesList = new ArrayList<>();
+
+
+    public static SampleApplication getInstance(){
+        return application;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        application = this;
+        samplesList.clear();
+        samplesList.add(new AnnotationTest());
+        samplesList.add(new BookmarkTest());
+        samplesList.add(new OutlineTest());
+        samplesList.add(new PDFToImageTest());
+        samplesList.add(new TextSearchTest());
+        samplesList.add(new InteractiveFormsTest());
+        samplesList.add(new PDFPageTest());
+        samplesList.add(new ImageExtractTest());
+        samplesList.add(new TextExtractTest());
+        samplesList.add(new DocumentInfoTest());
+        samplesList.add(new WatermarkTest());
+        samplesList.add(new BackgroundTest());
+        samplesList.add(new HeaderFooterTest());
+        samplesList.add(new BatesTest());
+        samplesList.add(new PDFRedactTest());
+        samplesList.add(new EncryptTest());
+        samplesList.add(new PDFATest());
+        samplesList.add(new FlattenTest());
+        samplesList.add(new AnnotationImportExportTest());
+    }
+}

+ 103 - 0
samples/src/main/java/com/compdfkit/samples/SampleDetailActivity.java

@@ -0,0 +1,103 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples;
+
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.View;
+import android.widget.ScrollView;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.appcompat.widget.Toolbar;
+
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.LoggingOutputListener;
+import com.google.android.material.button.MaterialButton;
+
+import java.io.File;
+import java.util.function.IntFunction;
+
+public class SampleDetailActivity extends AppCompatActivity {
+
+    protected static final String EXTRA_SAMPLE_ID = "SAMPLE_ID";
+
+    PDFSamples pdfSamples = null;
+
+    public static void openDetail(Context context, int sampleId) {
+        Intent intent = new Intent(context, SampleDetailActivity.class);
+        intent.putExtra(EXTRA_SAMPLE_ID, sampleId);
+        context.startActivity(intent);
+    }
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_sample_detail);
+        MaterialButton btnRun = findViewById(R.id.btn_run);
+        MaterialButton btnOpenFiles = findViewById(R.id.btn_open_files);
+        AppCompatTextView logTextView = findViewById(R.id.tv_logging);
+        ScrollView scrollView = findViewById(R.id.scroll_view);
+        AppCompatTextView tvDescription = findViewById(R.id.tv_description);
+//        File file = getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
+//        FileUtils.deleteFile(file);
+        ActionBar actionBar = getSupportActionBar();
+        LoggingOutputListener outputListener = new LoggingOutputListener(logTextView, scrollView);
+        if (getIntent().hasExtra(EXTRA_SAMPLE_ID)) {
+            pdfSamples = SampleApplication.getInstance().samplesList.get(getIntent().getIntExtra(EXTRA_SAMPLE_ID, 0));
+            if (actionBar != null) {
+                actionBar.setIcon(R.drawable.baseline_arrow_back_24);
+                actionBar.setHomeButtonEnabled(true);
+                actionBar.setDisplayHomeAsUpEnabled(true);
+                actionBar.setTitle(pdfSamples.getTitle());
+                tvDescription.setText(pdfSamples.getDescription());
+            }
+        }
+        btnRun.setOnClickListener(v -> {
+            new Thread(() -> {
+                if (pdfSamples != null) {
+                    pdfSamples.run(outputListener);
+                }
+            }).start();
+        });
+        btnOpenFiles.setOnClickListener(v -> {
+            if (pdfSamples.getOutputFileList() != null) {
+                AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                builder.setTitle(R.string.choose_a_file_to_open);
+                builder.setItems(pdfSamples.getOutputFileNames(), (dialog, which) -> {
+                    String filePath = pdfSamples.getOutputFileList().get(which);
+                    String mimeType = "application/pdf";
+                    if (filePath.endsWith(".pdf")){
+                        mimeType = "application/pdf";
+                    } else if (filePath.endsWith("png") || filePath.endsWith("jpg")){
+                        mimeType = "image/*";
+                    }
+                    FileUtils.shareFile(this, "Open", mimeType, new File(filePath));
+                });
+                builder.create().show();
+            }
+        });
+    }
+
+
+
+    @Override
+    public boolean onSupportNavigateUp() {
+        onBackPressed();
+        return super.onSupportNavigateUp();
+    }
+}

+ 34 - 0
samples/src/main/java/com/compdfkit/samples/SampleListActivity.java

@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import android.os.Bundle;
+
+public class SampleListActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_sample_list);
+        RecyclerView recyclerView = findViewById(R.id.rv_sample_list);
+
+        SampleListAdapter listAdapter = new SampleListAdapter();
+        recyclerView.setLayoutManager(new LinearLayoutManager(this));
+        recyclerView.setAdapter(listAdapter);
+
+        listAdapter.setOnItemClickListener(position -> {
+            SampleDetailActivity.openDetail(this, position);
+        });
+    }
+}

+ 72 - 0
samples/src/main/java/com/compdfkit/samples/SampleListAdapter.java

@@ -0,0 +1,72 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples;
+
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SampleListAdapter extends RecyclerView.Adapter<SampleListAdapter.SampleListViewHolder> {
+
+    private List<PDFSamples> list = new ArrayList<>();
+
+    private OnItemClickListener onItemClickListener;
+
+    public SampleListAdapter(){
+        list.addAll(SampleApplication.getInstance().samplesList);
+    }
+
+    @NonNull
+    @Override
+    public SampleListAdapter.SampleListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        return new SampleListViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_sample_list_item, parent, false));
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull SampleListAdapter.SampleListViewHolder holder, int position) {
+        holder.tvSampleTitle.setText(list.get(holder.getAdapterPosition()).getTitle());
+        holder.itemView.setOnClickListener(v -> {
+            if (onItemClickListener != null) {
+                onItemClickListener.onClick(holder.getAdapterPosition());
+            }
+        });
+    }
+
+    @Override
+    public int getItemCount() {
+        return list.size();
+    }
+
+    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
+        this.onItemClickListener = onItemClickListener;
+    }
+
+    public static class SampleListViewHolder extends RecyclerView.ViewHolder{
+
+        private AppCompatTextView tvSampleTitle;
+
+        public SampleListViewHolder(@NonNull View itemView) {
+            super(itemView);
+            tvSampleTitle = itemView.findViewById(R.id.tv_sample_title);
+        }
+    }
+
+    public interface OnItemClickListener{
+        void onClick(int position);
+    }
+}

+ 71 - 0
samples/src/main/java/com/compdfkit/samples/samples/AnnotationImportExportTest.java

@@ -0,0 +1,71 @@
+package com.compdfkit.samples.samples;
+
+
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+public class AnnotationImportExportTest extends PDFSamples {
+
+    public AnnotationImportExportTest(){
+        setTitle(R.string.annotation_import_export_test_title);
+        setDescription(R.string.annotation_import_export_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        exportAnnotation();
+        importAnnotation();
+        printFooter();
+    }
+
+    /**
+     * Samples 1 : export pdf document annotations
+     */
+    private void exportAnnotation(){
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1: export pdf document annotations");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CreateAnnotationTest.pdf"));
+        File exportFile = new File(SampleApplication.getInstance().getExternalFilesDir(
+                Environment.DIRECTORY_DOCUMENTS), "AnnotationImportExportTest/ExportAnnotationTest.xfdf");
+        File cacheDir = new File(SampleApplication.getInstance().getCacheDir(), "AnnotationImportExportTest/");
+        exportFile.getParentFile().mkdirs();
+        cacheDir.mkdirs();
+        document.exportAnnotations(exportFile.getAbsolutePath(), cacheDir.getAbsolutePath());
+        document.close();
+
+        if (exportFile.exists()){
+            getOutputFileList().add(exportFile.getAbsolutePath());
+        }
+        outputListener.println("Done. Results saved in ExportAnnotationTest.xfdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void importAnnotation(){
+        outputListener.println("Samples 2: import pdf document annotation");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        File exportFile = new File(SampleApplication.getInstance().getExternalFilesDir(
+                Environment.DIRECTORY_DOCUMENTS), "AnnotationImportExportTest/ExportAnnotationTest.xfdf");
+        File cacheDir = new File(SampleApplication.getInstance().getCacheDir(), "AnnotationImportExportTest/");
+        exportFile.getParentFile().mkdirs();
+        cacheDir.mkdirs();
+        document.importAnnotations(exportFile.getAbsolutePath(), cacheDir.getAbsolutePath());
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "AnnotationImportExportTest/ImportAnnotationTest.pdf"
+                );
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Results saved in ImportAnnotationTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+}

+ 513 - 0
samples/src/main/java/com/compdfkit/samples/samples/AnnotationTest.java

@@ -0,0 +1,513 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.os.Environment;
+import android.text.TextUtils;
+
+import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.CPDFBorderStyle;
+import com.compdfkit.core.annotation.CPDFCircleAnnotation;
+import com.compdfkit.core.annotation.CPDFFreetextAnnotation;
+import com.compdfkit.core.annotation.CPDFHighlightAnnotation;
+import com.compdfkit.core.annotation.CPDFInkAnnotation;
+import com.compdfkit.core.annotation.CPDFLineAnnotation;
+import com.compdfkit.core.annotation.CPDFLinkAnnotation;
+import com.compdfkit.core.annotation.CPDFSoundAnnotation;
+import com.compdfkit.core.annotation.CPDFSquareAnnotation;
+import com.compdfkit.core.annotation.CPDFStampAnnotation;
+import com.compdfkit.core.annotation.CPDFTextAnnotation;
+import com.compdfkit.core.annotation.CPDFTextAttribute;
+import com.compdfkit.core.document.CPDFDestination;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.action.CPDFGoToAction;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.core.page.CPDFTextPage;
+import com.compdfkit.core.page.CPDFTextRange;
+import com.compdfkit.core.page.CPDFTextSearcher;
+import com.compdfkit.core.page.CPDFTextSelection;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+import com.compdfkit.ui.attribute.CPDFFreetextAttr;
+import com.compdfkit.ui.reader.CPDFReaderView;
+import com.compdfkit.ui.textsearch.ITextSearcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class AnnotationTest extends PDFSamples {
+
+    public AnnotationTest() {
+        setTitle(R.string.annotation_test_title);
+        setDescription(R.string.annotation_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        //------------------------------------------
+        //Samples 1 : add freetext annotation
+        addFreeText(document);
+
+        //------------------------------------------
+        //Samples 2 : add ink annotation
+        addInk(document);
+
+        //------------------------------------------
+        //Samples 3 : add line annotation
+        addLine(document);
+
+        //------------------------------------------
+        //Samples 4 : add circle annotation
+        addCircleShape(document);
+
+        //------------------------------------------
+        //Samples 5 : add square annotation
+        addSquareShape(document);
+
+        //------------------------------------------
+        //Samples 6 : add highlight(markup) annotation
+//        addHighlight(document);
+
+        //------------------------------------------
+        //Samples 7 : add link annotation
+        addLink(document);
+
+        //------------------------------------------
+        //Samples 8 : add note annotation
+        addNote(document);
+
+        //------------------------------------------
+        //Samples 8 : add sound annotation
+        addSound(document);
+
+        //------------------------------------------
+        //Samples 9 : add stamp annotation
+        addStamp(document);
+
+        //------------------------------------------
+        //Samples 10 : print annotation list info
+        printAnnotationList(document);
+
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "AnnotationTest/CreateAnnotationTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in CreateAnnotationTest.pdf");
+
+        //------------------------------------------
+        //Samples 11 : delete annotation
+        deleteAnnotation();
+
+        printFooter();
+    }
+
+    private void addFreeText(CPDFDocument document) {
+        CPDFPage page1 = document.pageAtIndex(0);
+        CPDFFreetextAnnotation freetextAnnotation = (CPDFFreetextAnnotation) page1.addAnnot(CPDFAnnotation.Type.FREETEXT);
+        RectF freeText1Rect = getConvertRect(page1, new RectF(10, 200, 160, 570));
+        freetextAnnotation.setRect(freeText1Rect);
+        freetextAnnotation.setFreetextAlignment(CPDFFreetextAnnotation.Alignment.ALIGNMENT_LEFT);
+        CPDFBorderStyle borderStyle = new CPDFBorderStyle();
+        borderStyle.setBorderWidth(2);
+        borderStyle.setStyle(CPDFBorderStyle.Style.Border_Dashed);
+        freetextAnnotation.setBorderStyle(borderStyle);
+        CPDFTextAttribute textAttribute = new CPDFTextAttribute(CPDFTextAttribute.FontNameHelper.obtainFontName(
+                CPDFTextAttribute.FontNameHelper.FontType.Courier, false, false
+        ), 12, Color.RED);
+        freetextAnnotation.setFreetextDa(textAttribute);
+        freetextAnnotation.setAlpha(255);
+        freetextAnnotation.setBorderRGBColor(255, 0, 0);
+        freetextAnnotation.setContent("Some swift brown fox snatched a gray hare out of the air by freezing it with an angry glare.\n" +
+                "\n" +
+                "Aha!\n" +
+                "\n" +
+                "And there was much rejoicing!");
+        freetextAnnotation.updateAp();
+    }
+
+    private void addInk(CPDFDocument document) {
+        CPDFPage page1 = document.pageAtIndex(0);
+        ArrayList<ArrayList<PointF>> mDrawing = new ArrayList<>();
+        ArrayList<PointF> arc1 = new ArrayList<>();
+        arc1.add(new PointF(100, 100));
+        arc1.add(new PointF(110, 110));
+        arc1.add(new PointF(120, 120));
+        mDrawing.add(arc1);
+        ArrayList<PointF> arc2 = new ArrayList<>();
+        arc2.add(new PointF(115, 115));
+        arc2.add(new PointF(130, 130));
+        arc2.add(new PointF(160, 160));
+        mDrawing.add(arc2);
+        float scaleValue = 1F;
+        float borderWidth = 5F;
+        CPDFInkAnnotation inkAnnotation = (CPDFInkAnnotation) page1.addAnnot(CPDFInkAnnotation.Type.INK);
+        inkAnnotation.setColor(Color.RED);
+        inkAnnotation.setAlpha(255);
+        inkAnnotation.setBorderWidth(borderWidth);
+        RectF rect = null;
+        RectF size = document.getPageSize(0);
+        if (size.isEmpty()) {
+            return;
+        }
+        int lineCount = mDrawing.size();
+        PointF[][] path = new PointF[lineCount][];
+        for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) {
+            ArrayList<PointF> line = mDrawing.get(lineIndex);
+            int pointCount = line.size();
+            PointF[] linePath = new PointF[pointCount];
+            for (int pointIndex = 0; pointIndex < pointCount; pointIndex++) {
+                PointF point = line.get(pointIndex);
+                /****** Calculate the smallest Rect that the Path is surrounded by ******/
+                if (rect == null) {
+                    rect = new RectF(point.x, point.y, point.x, point.y);
+                } else {
+                    rect.union(point.x, point.y);
+                }
+                /****** Calculate the coordinate points that are converted to the Page and stored in the linePath collection ******/
+                linePath[pointIndex] = (page1.convertPointToPage(false, size.width(), size.height(), point));
+            }
+            path[lineIndex] = linePath;
+        }
+        float dx = borderWidth / scaleValue / 2;
+        rect.inset(-dx, -dx);
+        rect.set(page1.convertRectToPage(false, size.width(), size.height(), rect));
+        inkAnnotation.setInkPath(path);
+        inkAnnotation.setRect(rect);
+        inkAnnotation.updateAp();
+        mDrawing.clear();
+    }
+
+    private void addLine(CPDFDocument document) {
+        // Add a green dotted line annotation
+        CPDFPage page2 = document.pageAtIndex(1);
+        CPDFLineAnnotation lineAnnotation = (CPDFLineAnnotation) page2.addAnnot(CPDFAnnotation.Type.LINE);
+        PointF startPoint = new PointF(200, 100);
+        PointF endPoint = new PointF(50, 300);
+        RectF area = new RectF();
+
+        convertLinePoint(page2, startPoint, endPoint, area);
+        lineAnnotation.setRect(area);
+        lineAnnotation.setLinePoints(startPoint, endPoint);
+        lineAnnotation.setLineType(CPDFLineAnnotation.LineType.LINETYPE_NONE, CPDFLineAnnotation.LineType.LINETYPE_NONE);
+        CPDFBorderStyle borderStyle = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Dashed, 10, new float[]{8, 4F});
+        lineAnnotation.setBorderStyle(borderStyle);
+        lineAnnotation.setBorderWidth(3);
+        lineAnnotation.setBorderAlpha(255);
+        lineAnnotation.setBorderColor(Color.GREEN);
+        lineAnnotation.updateAp();
+
+        //Add a solid red line annotation with an arrow type
+        CPDFLineAnnotation lineAnnotation2 = (CPDFLineAnnotation) page2.addAnnot(CPDFAnnotation.Type.LINE);
+        PointF startPoint2 = new PointF(200, 350);
+        PointF endPoint2 = new PointF(50, 550);
+        RectF area2 = new RectF();
+
+        convertLinePoint(page2, startPoint2, endPoint2, area2);
+        lineAnnotation2.setRect(area2);
+        lineAnnotation2.setLinePoints(startPoint2, endPoint2);
+        lineAnnotation2.setLineType(CPDFLineAnnotation.LineType.LINETYPE_CIRCLE, CPDFLineAnnotation.LineType.LINETYPE_ARROW);
+        CPDFBorderStyle borderStyle2 = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10, new float[]{8, 0});
+        lineAnnotation2.setBorderStyle(borderStyle2);
+        lineAnnotation2.setBorderWidth(5);
+        lineAnnotation2.setBorderAlpha(255);
+        lineAnnotation2.setBorderColor(Color.RED);
+        lineAnnotation2.updateAp();
+
+        // Add a solid red line annotation
+        CPDFLineAnnotation lineAnnotation3 = (CPDFLineAnnotation) page2.addAnnot(CPDFAnnotation.Type.LINE);
+        PointF startPoint3 = new PointF(400, 100);
+        PointF endPoint3 = new PointF(250, 300);
+        RectF area3 = new RectF();
+
+        convertLinePoint(page2, startPoint3, endPoint3, area3);
+        lineAnnotation3.setRect(area3);
+        lineAnnotation3.setLinePoints(startPoint3, endPoint3);
+        lineAnnotation3.setLineType(CPDFLineAnnotation.LineType.LINETYPE_NONE, CPDFLineAnnotation.LineType.LINETYPE_NONE);
+        CPDFBorderStyle borderStyle3 = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10, new float[]{8, 0});
+        lineAnnotation3.setBorderStyle(borderStyle3);
+        lineAnnotation3.setBorderWidth(5);
+        lineAnnotation3.setBorderAlpha(255);
+        lineAnnotation3.setBorderColor(Color.BLUE);
+        lineAnnotation3.updateAp();
+    }
+
+    private void convertLinePoint(CPDFPage page, PointF startPoint, PointF endPoint, RectF area) {
+        RectF pageSize = page.getSize();
+        float lineWidth = 10f;
+        area.left = Math.min(startPoint.x, endPoint.x);
+        area.right = Math.max(startPoint.x, endPoint.x);
+        area.top = Math.min(startPoint.y, endPoint.y);
+        area.bottom = Math.max(startPoint.y, endPoint.y);
+        area.left -= lineWidth * 2;
+        area.top -= lineWidth * 2;
+        area.right += lineWidth * 2;
+        area.bottom += lineWidth * 2;
+        area.set(page.convertRectToPage(false, pageSize.width(), pageSize.height(), area));
+        startPoint.set(page.convertPointToPage(false, pageSize.width(), pageSize.height(), startPoint));
+        endPoint.set(page.convertPointToPage(false, pageSize.width(), pageSize.height(), endPoint));
+    }
+
+    private void addCircleShape(CPDFDocument document) {
+        // Add a circular annotation with a green border and blue fill
+        CPDFPage page3 = document.pageAtIndex(2);
+        CPDFCircleAnnotation circleAnnotation = (CPDFCircleAnnotation) page3.addAnnot(CPDFAnnotation.Type.CIRCLE);
+        RectF pageSize = page3.getSize();
+        RectF insertRect = new RectF(50, 50, 150, 150);
+        insertRect = page3.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect);
+        circleAnnotation.setRect(insertRect);
+        circleAnnotation.setBorderColor(Color.parseColor("#3863F1"));
+        CPDFBorderStyle borderStyle = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10, new float[]{8.0F, 0F});
+        borderStyle.setBorderWidth(5F);
+        circleAnnotation.setBorderStyle(borderStyle);
+        circleAnnotation.setBorderAlpha(255);
+        circleAnnotation.setFillColor(Color.parseColor("#31BC98"));
+        circleAnnotation.setFillAlpha(255);
+        circleAnnotation.updateAp();
+
+        //Add a dotted border circular annotation
+        CPDFCircleAnnotation circleAnnotation2 = (CPDFCircleAnnotation) page3.addAnnot(CPDFAnnotation.Type.CIRCLE);
+        RectF insertRect2 = new RectF(50, 200, 150, 300);
+        insertRect2 = page3.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect2);
+        circleAnnotation2.setRect(insertRect2);
+        circleAnnotation2.setBorderColor(Color.parseColor("#3863F1"));
+        CPDFBorderStyle borderStyle2 = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Dashed, 10, new float[]{8.0F, 4F});
+        borderStyle2.setBorderWidth(5F);
+        circleAnnotation2.setBorderStyle(borderStyle2);
+        circleAnnotation2.setBorderAlpha(127);
+        circleAnnotation2.setFillColor(Color.parseColor("#31BC98"));
+        circleAnnotation2.setFillAlpha(127);
+        circleAnnotation2.updateAp();
+    }
+
+    private void addSquareShape(CPDFDocument document) {
+        CPDFPage page3 = document.pageAtIndex(2);
+        CPDFSquareAnnotation squareAnnotation = (CPDFSquareAnnotation) page3.addAnnot(CPDFAnnotation.Type.SQUARE);
+        RectF pageSize = page3.getSize();
+        RectF insertRect = new RectF(50, 350, 300, 450);
+        insertRect = page3.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect);
+        squareAnnotation.setRect(insertRect);
+        squareAnnotation.setBorderColor(Color.parseColor("#3863F1"));
+        CPDFBorderStyle borderStyle = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Solid, 10, new float[]{8.0F, 0F});
+        borderStyle.setBorderWidth(10F);
+        squareAnnotation.setBorderStyle(borderStyle);
+        squareAnnotation.setBorderAlpha(255);
+        squareAnnotation.setFillColor(Color.parseColor("#31BC98"));
+        squareAnnotation.setFillAlpha(255);
+        squareAnnotation.updateAp();
+
+        CPDFSquareAnnotation squareAnnotation2 = (CPDFSquareAnnotation) page3.addAnnot(CPDFAnnotation.Type.SQUARE);
+        RectF insertRect2 = new RectF(50, 500, 300, 600);
+        insertRect2 = page3.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect2);
+        squareAnnotation2.setRect(insertRect2);
+        squareAnnotation2.setBorderColor(Color.parseColor("#3863F1"));
+        CPDFBorderStyle borderStyle2 = new CPDFBorderStyle(CPDFBorderStyle.Style.Border_Dashed, 10, new float[]{8.0F, 4F});
+        borderStyle2.setBorderWidth(10F);
+        squareAnnotation2.setBorderStyle(borderStyle2);
+        squareAnnotation2.setBorderAlpha(127);
+        squareAnnotation2.setFillColor(Color.parseColor("#31BC98"));
+        squareAnnotation2.setFillAlpha(127);
+        squareAnnotation2.updateAp();
+    }
+
+    private void addHighlight(CPDFDocument document) {
+        CPDFReaderView readerView = new CPDFReaderView(SampleApplication.getInstance());
+        readerView.setPDFDocument(document);
+        readerView.reloadPages();
+        //Also search for the `Page` keyword in the 3rd of the document
+        List<CPDFTextRange> list = startSearch(readerView, "Page");
+        if (list != null && list.size() > 0) {
+            CPDFTextRange textRange = list.get(0);
+            CPDFPage pdfPage = document.pageAtIndex(3);
+            CPDFTextPage pdfTextPage = pdfPage.getTextPage();
+            CPDFTextSelection[] textSelectionArr = pdfTextPage.getSelectionsByTextForRange(textRange);
+            //Then, add a highlight annotation for the specific area.
+            RectF annotRect = new RectF();
+            CPDFHighlightAnnotation highlightAnnotation = (CPDFHighlightAnnotation) pdfPage.addAnnot(CPDFAnnotation.Type.HIGHLIGHT);
+            highlightAnnotation.setColor(Color.YELLOW);
+            highlightAnnotation.setAlpha((255 / 2));
+            RectF[] quadRects = new RectF[textSelectionArr.length];
+            StringBuilder markedTextSb = new StringBuilder();
+            int len = textSelectionArr.length;
+            for (int i = 0; i < len; i++) {
+                CPDFTextSelection textSelection = textSelectionArr[i];
+                if (textSelection == null) {
+                    continue;
+                }
+                //Get the position of the keyword `Page` in the page
+                RectF rect = new RectF(textSelection.getRectF());
+                if (annotRect.isEmpty()) {
+                    annotRect.set(rect);
+                } else {
+                    annotRect.union(rect);
+                }
+                quadRects[i] = new RectF(textSelection.getRectF());
+                String text = pdfTextPage.getText(textSelection.getTextRange());
+                if (!TextUtils.isEmpty(text)) {
+                    markedTextSb.append(text);
+                }
+            }
+            highlightAnnotation.setQuadRects(quadRects);
+            highlightAnnotation.setMarkedText(markedTextSb.toString());
+            highlightAnnotation.setRect(annotRect);
+            highlightAnnotation.updateAp();
+            outputListener.println(annotRect.toString());
+        }
+    }
+
+    public static List<CPDFTextRange> startSearch(CPDFReaderView readerView, String keywords) {
+        ITextSearcher textSearcher = readerView.getTextSearcher();
+        if (null == textSearcher) {
+            return null;
+        }
+        CPDFDocument document = readerView.getPDFDocument();
+        if (null == document) {
+            return null;
+        }
+        textSearcher.setSearchConfig(keywords, CPDFTextSearcher.PDFSearchOptions.PDFSearchCaseInsensitive);
+        List<CPDFTextRange> searchTextInfoList = new ArrayList<>();
+
+        CPDFPage page = document.pageAtIndex(3);
+        CPDFTextPage textPage = page.getTextPage();
+        if ((null == textPage) || !textPage.isValid()) {
+            return null;
+        }
+        final List<CPDFTextRange> searchPageContent = textSearcher.searchKeyword(3);
+        if (searchPageContent.size() > 0) {
+            searchTextInfoList.addAll(searchPageContent);
+        }
+        page.close();
+        return searchTextInfoList;
+    }
+
+    private void addLink(CPDFDocument document) {
+        CPDFPage page = document.pageAtIndex(3);
+        CPDFLinkAnnotation linkAnnotation = (CPDFLinkAnnotation) page.addAnnot(CPDFAnnotation.Type.LINK);
+        RectF pageSize = page.getSize();
+        RectF insertRect = getConvertRect(page, new RectF(50, 50, 150, 150));
+        linkAnnotation.setRect(insertRect);
+
+        float firstPageHeight = document.getPageSize(0).height();
+        CPDFGoToAction goToAction = new CPDFGoToAction();
+        CPDFDestination destination = new CPDFDestination(1, 0, firstPageHeight, 1f);
+        goToAction.setDestination(document, destination);
+        linkAnnotation.setLinkAction(goToAction);
+        linkAnnotation.updateAp();
+    }
+
+    private void addNote(CPDFDocument document) {
+        CPDFPage page = document.pageAtIndex(3);
+        CPDFTextAnnotation textAnnotation = (CPDFTextAnnotation) page.addAnnot(CPDFAnnotation.Type.TEXT);
+        //get the actual size of the page you want to insert
+        RectF insertRect = getConvertRect(page, new RectF(50, 200, 100, 250));
+        textAnnotation.setRect(insertRect);
+        textAnnotation.setContent("ComPDFKit");
+        textAnnotation.updateAp();
+    }
+
+    private void addSound(CPDFDocument document) {
+        CPDFPage page = document.pageAtIndex(3);
+        CPDFSoundAnnotation soundAnnotation = (CPDFSoundAnnotation) page.addAnnot(CPDFAnnotation.Type.SOUND);
+        RectF insertRect = getConvertRect(page, new RectF(50, 300, 100, 350));
+        soundAnnotation.setRect(insertRect);
+        soundAnnotation.setSoundPath(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "Bird.wav"));
+        soundAnnotation.updateAp();
+    }
+
+    private void addStamp(CPDFDocument document) {
+        int yOffset = 50;
+        float lastOffset = 0;
+        for (int i = 0; i < CPDFStampAnnotation.StandardStamp.values().length; i++) {
+            CPDFPage page = document.pageAtIndex(4);
+            CPDFStampAnnotation.StandardStamp standardStamp = CPDFStampAnnotation.StandardStamp.values()[i];
+            if (standardStamp == null || standardStamp == CPDFStampAnnotation.StandardStamp.UNKNOWN) {
+                continue;
+            }
+            // add Standard stamp
+            CPDFStampAnnotation standard = (CPDFStampAnnotation) page.addAnnot(CPDFAnnotation.Type.STAMP);
+            if (standard == null) {
+                continue;
+            }
+            standard.setStandardStamp(standardStamp);
+            RectF pageSize = page.getSize();
+            RectF insertRect = standard.getRect();
+            insertRect.set(page.convertRectFromPage(false, pageSize.width(), pageSize.height(), insertRect));
+            float defaultWidth = 100F;
+            int x = 50;
+            if (i == 10){
+                lastOffset = 50;
+            }
+            if (i >= 10){
+                x = 150;
+            }
+            yOffset = (int) lastOffset + 10;
+            PointF vertex = new PointF(x, yOffset);
+            insertRect.set(vertex.x, vertex.y, vertex.x + defaultWidth, vertex.y + defaultWidth * Math.abs(insertRect.height() / insertRect.width()));
+            lastOffset = insertRect.bottom;
+            standard.setRect(page.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect));
+            standard.updateAp();
+        }
+    }
+
+    private RectF getConvertRect(CPDFPage page, RectF rectF) {
+        RectF size = page.getSize();
+        return page.convertRectToPage(false, size.width(), size.height(), rectF);
+    }
+
+    private void printAnnotationList(CPDFDocument document){
+        for (int i = 0; i < document.getPageCount(); i++) {
+            CPDFPage page = document.pageAtIndex(i);
+            for (CPDFAnnotation annotation : page.getAnnotations()) {
+                outputListener.println("--------------------------------------------");
+                outputListener.println("Page: " + (i + 1));
+                outputListener.println("Annot Type: " + annotation.getType().name());
+                RectF widgetRect = annotation.getRect();
+                RectF position = page.convertRectFromPage(false, document.getPageSize(i).width(),
+                        document.getPageSize(i).height(),widgetRect);
+                outputListener.println(String.format("Position: %d, %d, %d, %d",(int) position.left, (int) position.top,
+                        (int) position.right, (int) position.bottom));
+            }
+        }
+        outputListener.println("--------------------------------------------");
+    }
+
+
+    private void deleteAnnotation(){
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples : delete annotation");
+        File sampleFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "AnnotationTest/CreateAnnotationTest.pdf");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(sampleFile.getAbsolutePath());
+        for (int i = 0; i < document.getPageCount(); i++) {
+            CPDFPage page = document.pageAtIndex(i);
+            List<CPDFAnnotation> annotations = page.getAnnotations();
+            if (annotations != null && annotations.size() >0){
+                page.deleteAnnotation(annotations.get(0));
+                break;
+            }
+        }
+
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "AnnotationTest/DeleteAnnotationTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Results saved in DeleteAnnotationTest.pdf");
+    }
+}

+ 121 - 0
samples/src/main/java/com/compdfkit/samples/samples/BackgroundTest.java

@@ -0,0 +1,121 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.os.Environment;
+
+import com.compdfkit.core.annotation.CPDFImageScaleType;
+import com.compdfkit.core.document.CPDFBackground;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+public class BackgroundTest extends PDFSamples {
+
+    public BackgroundTest(){
+        setTitle(R.string.background_test_title);
+        setDescription(R.string.background_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        addColorBackground();
+        addImageBackground();
+        deleteBackground();
+        printFooter();
+    }
+
+
+    private void addColorBackground(){
+        outputListener.println("Samples 1 : Set the document background color");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFBackground background = document.getBackground();
+        background.setType(CPDFBackground.Type.Color);
+        background.setColor(Color.RED);
+        background.setOpacity(0.5F);
+        background.setPages("0,1,2,3");
+        printBackgroundInfo(background);
+        background.update();
+        background.release();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "backgroundTest/Add_Color_Background.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nAdd_Color_Background.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void addImageBackground(){
+        outputListener.println("Samples 1 : Set the document background image");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFBackground background = document.getBackground();
+        background.setType(CPDFBackground.Type.Image);
+        Bitmap backgroundImage = BitmapFactory.decodeResource(SampleApplication.getInstance().getResources(), R.mipmap.ic_launcher_foreground);
+        background.setImage(backgroundImage, CPDFImageScaleType.SCALETYPE_center);
+        background.setOpacity(0.5F);
+        background.setPages("0,1,2,3");
+        printBackgroundInfo(background);
+        background.update();
+        background.release();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "backgroundTest/Add_Image_Background.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nAdd_Image_Background.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Sample 3 : Delete document background
+     */
+    private void deleteBackground(){
+        outputListener.println("Samples 3 : Delete document background");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File sampleFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "backgroundTest/Add_Color_Background.pdf");
+        document.open(sampleFile.getAbsolutePath());
+        CPDFBackground background = document.getBackground();
+        //remove all pages background
+        background.clear();
+        //update pages
+//        background.setPages("0,2,3,4");
+//        background.update();
+//        background.release();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "backgroundTest/Delete_Background.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nDelete_Background.pdf");
+    }
+
+    private void printBackgroundInfo(CPDFBackground background){
+        outputListener.println("Type : " + background.getType().name());
+        if (background.getType() == CPDFBackground.Type.Color){
+            outputListener.println(String.format("Color : red:%d, green:%d, blue:%d, alpha:%d",
+                    Color.red(background.getColor()),
+                    Color.green(background.getColor()),
+                    Color.blue(background.getColor()),
+                    Color.alpha(background.getColor())));
+        }
+        outputListener.println("Opacity : " + background.getOpacity());
+        outputListener.println("Rotation : " + background.getRotation());
+        outputListener.println("Vertalign : " + background.getVertalign().name());
+        outputListener.println("Horizalign : " + background.getHorizalign().name());
+        outputListener.println("VertOffset : " + background.getXOffset());
+        outputListener.println("HorizOffset : " + background.getYOffset());
+        outputListener.println("Pages : " + background.getPages());
+    }
+}

+ 116 - 0
samples/src/main/java/com/compdfkit/samples/samples/BatesTest.java

@@ -0,0 +1,116 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Color;
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFBates;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.CPDFHeaderFooter;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class BatesTest extends PDFSamples {
+
+    public BatesTest(){
+        setTitle(R.string.bates_test_title);
+        setDescription(R.string.bates_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        addCommonBates();
+        editDateBates();
+        clearBates();
+        printFooter();
+    }
+
+    /**
+     * Samples 1 : Add bates
+     */
+    private void addCommonBates(){
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1 : Add Bates");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFBates bates = document.getBates();
+        int num = 6;
+        for (int i = 0; i < num; i++) {
+            outputListener.println("\nText : <<#3#5#Prefix-#-Suffix>>");
+            bates.setText(i, "<<#3#5#Prefix-#-Suffix>>");
+            bates.setTextColor(i, Color.RED);
+            bates.setFontSize(i, 14);
+            if (i == 0) {
+                outputListener.println("Location: Top Left");
+            } else if (i == 1) {
+                outputListener.println("Location: Top Middle");
+            } else if (i == 2) {
+                outputListener.println("Location: Top Right");
+            } else if (i == 3) {
+                outputListener.println("Location: Botton Left");
+            } else if (i == 4) {
+                outputListener.println("Location: Botton Middle");
+            } else {
+                outputListener.println("Location: Botton Right");
+            }
+        }
+        bates.setPages("0,1,2,3,4");
+        bates.update();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "BatesTest/AddBatesTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Results saved in 1 AddBatesTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples 2: edit bates
+     */
+    private void editDateBates(){
+        outputListener.println("Samples 2 : edit bates");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "BatesTest/AddBatesTest.pdf");
+        document.open(file.getAbsolutePath());
+        CPDFBates bates = document.getBates();
+        outputListener.println("Get old bates 0 succeeded, text is " + bates.getText(0));
+        outputListener.println("Change bates 0 succeeded, new text is <<#3#1#ComPDFKit-#-ComPDFKit>>");
+        bates.setText(0, "<<#3#1#ComPDFKit-#-ComPDFKit>>");
+        bates.update();
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "BatesTest/EditBatesTest.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in EditBatesTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * samples 3 : clear bates
+     */
+    private void clearBates(){
+        outputListener.println("Samples 3 : clear bates");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "BatesTest/AddBatesTest.pdf");
+        document.open(file.getAbsolutePath());
+        CPDFBates bates = document.getBates();
+        bates.clear();
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "BatesTest/ClearBatesTest.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in ClearBatesTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+}

+ 56 - 0
samples/src/main/java/com/compdfkit/samples/samples/BookmarkTest.java

@@ -0,0 +1,56 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.Environment;
+
+import com.compdfkit.core.common.CPDFDate;
+import com.compdfkit.core.document.CPDFBookmark;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.utils.TTimeUtil;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+import java.util.List;
+
+
+public class BookmarkTest extends PDFSamples {
+
+    public BookmarkTest() {
+        setTitle(R.string.bookmark_test_title);
+        setDescription(R.string.bookmark_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.addBookmark(new CPDFBookmark(
+                1, "my bookmark", CPDFDate.toStandardDate(TTimeUtil.getCurrentDate())
+        ));
+        List<CPDFBookmark> list = document.getBookmarks();
+        if (list != null && list.size() > 0) {
+            for (CPDFBookmark cpdfBookmark : list) {
+                outputListener.println("Go to page " + (cpdfBookmark.getPageIndex() + 1));
+            }
+        }
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "bookmark/CreateBookmarkTest.pdf");
+        outputListener.println("Done. Result saved in\nCreateBookmarkTest.pdf");
+        saveSamplePDF(document, file, true);
+        printFooter();
+    }
+}

+ 88 - 0
samples/src/main/java/com/compdfkit/samples/samples/DocumentInfoTest.java

@@ -0,0 +1,88 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.ParcelFileDescriptor;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.CPDFDocumentPermissionInfo;
+import com.compdfkit.core.document.CPDFInfo;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.DateUtil;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+
+public class DocumentInfoTest extends PDFSamples {
+
+    public DocumentInfoTest(){
+        setTitle(R.string.document_test_title);
+        setDescription(R.string.document_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        outputListener.println("");
+        CPDFInfo cpdfInfo = document.getInfo();
+        CPDFDocumentPermissionInfo permissionInfo = document.getPermissionsInfo();
+        outputListener.println("FileName : " + document.getFileName());
+        outputListener.println("FileSize : " + getDocumentSize(document));
+        outputListener.println("Title : " + cpdfInfo.getTitle());
+        outputListener.println("Author : " + cpdfInfo.getAuthor());
+        outputListener.println("Subject : " + cpdfInfo.getSubject());
+        outputListener.println("Keywords : " + cpdfInfo.getKeywords());
+
+        outputListener.println("Version : " + document.getMajorVersion());
+        outputListener.println("PageCount : " + document.getPageCount());
+        outputListener.println("Creator : " + cpdfInfo.getCreator());
+        outputListener.println("CreationDate : " + DateUtil.transformPDFDate(cpdfInfo.getCreationDate()));
+        outputListener.println("ModificationDate : "+ DateUtil.transformPDFDate(cpdfInfo.getModificationDate()));
+
+        outputListener.println("Printing : " + permissionInfo.isAllowsPrinting());
+        outputListener.println("Content Copying : " + permissionInfo.isAllowsCopying());
+        outputListener.println("Document Change : " + permissionInfo.isAllowsDocumentChanges());
+        outputListener.println("Document Assembly : " + permissionInfo.isAllowsDocumentAssembly());
+        outputListener.println("Document Commenting : " + permissionInfo.isAllowsCommenting());
+        outputListener.println("Document Filling of form field : " + permissionInfo.isAllowsFormFieldEntry());
+        printFooter();
+    }
+
+
+    private String getDocumentSize(CPDFDocument document) {
+        final long MB = 1024 * 1024;
+        final int KB = 1024;
+        long fileSize = 0L;
+        try {
+            ParcelFileDescriptor p = document.getContext().getContentResolver().openFileDescriptor(document.getUri(), "r");
+            fileSize = p.getStatSize();
+            p.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        float size;
+        String unit = " M";
+        if (fileSize > MB) {
+            size = ((float) fileSize / (1024 * 1024));
+        } else if (fileSize > KB) {
+            size = ((float) fileSize / 1024);
+            unit = " KB";
+        } else {
+            size = fileSize;
+            unit = " B";
+        }
+        return String.format("%.2f", size) + unit;
+    }
+}

+ 95 - 0
samples/src/main/java/com/compdfkit/samples/samples/EncryptTest.java

@@ -0,0 +1,95 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.Environment;
+
+import com.compdfkit.core.common.CPDFDocumentException;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.CPDFDocumentPermissionInfo;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class EncryptTest extends PDFSamples {
+
+    public EncryptTest() {
+        setTitle(R.string.encrypt_test_title);
+        setDescription(R.string.encrypt_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        encryptDocument();
+        decryptDocument();
+        printFooter();
+    }
+
+    /**
+     * samples 1 : Encrypt document
+     */
+    private void encryptDocument() {
+        outputListener.println("Samples 1 : encrypt document");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.setUserPassword("123456");
+        document.setEncryptAlgorithm(CPDFDocument.PDFDocumentEncryptAlgo.PDFDocumentAES256);
+        document.setOwnerPassword("123456");
+        CPDFDocumentPermissionInfo info = document.getPermissionsInfo();
+        info.setAllowsPrinting(true);
+        info.setAllowsHighQualityPrinting(false);
+        info.setAllowsCopying(false);
+        info.setAllowsDocumentChanges(false);
+        info.setAllowsDocumentAssembly(false);
+        info.setAllowsCommenting(false);
+        info.setAllowsFormFieldEntry(false);
+        document.setPermissionsInfo(info);
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "EncryptTest/EncryptTest.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in EncryptTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * samples 2 : decrypt document
+     */
+    private void decryptDocument() {
+        outputListener.println("Samples 2 : encrypt document");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "EncryptTest/EncryptTest.pdf");
+        document.open(file.getAbsolutePath(), "123456");
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "EncryptTest/DecryptTest.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in DecryptTest.pdf");
+    }
+
+    @Override
+    protected void saveSamplePDF(CPDFDocument document, File file, boolean close) {
+        try {
+            file.getParentFile().mkdirs();
+            document.saveAs(file.getAbsolutePath(), true);
+            if (file.exists()) {
+                getOutputFileList().add(file.getAbsolutePath());
+            }
+            if (close) {
+                document.close();
+            }
+        } catch (CPDFDocumentException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 48 - 0
samples/src/main/java/com/compdfkit/samples/samples/FlattenTest.java

@@ -0,0 +1,48 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class FlattenTest extends PDFSamples {
+
+    public FlattenTest(){
+        setTitle(R.string.flatten_test_title);
+        setDescription(R.string.flatten_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        outputListener.println("Samples 1 : convert to flatten");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.convertType(CPDFDocument.PDFDocumentType.PDFTypeA1a);
+        document.flattenAllPages(CPDFPage.PDFFlattenOption.FLAT_NORMALDISPLAY);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "Flatten/FlattenTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in FlattenTest.pdf");
+        outputListener.println("--------------------------------------------");
+        printFooter();
+    }
+}

+ 150 - 0
samples/src/main/java/com/compdfkit/samples/samples/HeaderFooterTest.java

@@ -0,0 +1,150 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Color;
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.CPDFHeaderFooter;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+public class HeaderFooterTest extends PDFSamples {
+
+    public HeaderFooterTest() {
+        setTitle(R.string.header_footer_test_title);
+        setDescription(R.string.header_footer_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        addCommonHeaderFooter();
+        addPageHeaderFooter();
+        editHeaderFooter();
+        clearHeaderFooterTest();
+        printFooter();
+    }
+
+    /**
+     * samples 1 : add header
+     */
+    private void addCommonHeaderFooter() {
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1 : Add header");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFHeaderFooter headerFooter = document.getHeaderFooter();
+        String headerStr = "ComPDFKit";
+        int index = 3;
+        for (int i = 0; i < index; i++) {
+            outputListener.println("Text: " + headerStr);
+            headerFooter.setText(i, headerStr);
+            headerFooter.setTextColor(i, Color.RED);
+            headerFooter.setFontSize(i, 14);
+            if (i == 0) {
+                outputListener.println("Location: Top Left");
+            } else if (i == 1) {
+                outputListener.println("Location: Top Middle");
+            } else {
+                outputListener.println("Location: Top Right");
+            }
+        }
+        headerFooter.setPages("0,1,2,3,4");
+        headerFooter.update();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "HeaderFooterTest/AddCommonHeaderFooter.pdf");
+        saveSamplePDF(document, file, false);
+        outputListener.println("Done. Results saved in AddCommonHeaderFooter.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void addPageHeaderFooter() {
+        outputListener.println("Samples 2 : Add header and footer");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFHeaderFooter headerFooter = document.getHeaderFooter();
+        String headerStr = "ComPDFKit";
+        for (int i = 0; i < document.getPageCount(); i++) {
+            int pageNumber = i + 1;
+            int index = 6;
+            for (int i1 = 0; i1 < index; i1++) {
+                if (i1 < 3) {
+                    outputListener.println("Text: " + headerStr);
+                    headerFooter.setText(i1, headerStr);
+                    headerFooter.setTextColor(i1, Color.BLACK);
+                } else {
+                    outputListener.println("Text: 0" + pageNumber);
+                    headerFooter.setText(i1, "0" + pageNumber);
+                    headerFooter.setTextColor(i1, Color.RED);
+                }
+                if (i1 == 0) {
+                    outputListener.println("Location: Top Left");
+                } else if (i1 == 1) {
+                    outputListener.println("Location: Top Middle");
+                } else if (i1 == 2) {
+                    outputListener.println("Location: Top Right");
+                } else if (i1 == 3) {
+                    outputListener.println("Location: Botton Left");
+                } else if (i1 == 4) {
+                    outputListener.println("Location: Botton Middle");
+                } else {
+                    outputListener.println("Location: Botton Right");
+                }
+                headerFooter.setFontSize(i, 14);
+            }
+            headerFooter.setPages("" + i);
+            headerFooter.update();
+        }
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "HeaderFooterTest/AddPageHeaderFooter.pdf");
+        saveSamplePDF(document, file, false);
+        outputListener.println("Done. Results saved in AddPageHeaderFooter.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * samples 3 : edit top left header
+     */
+    private void editHeaderFooter() {
+        outputListener.println("Samples 3 : Edit top left header");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "HeaderFooterTest/AddCommonHeaderFooter.pdf");
+        document.open(file.getAbsolutePath());
+        CPDFHeaderFooter headerFooter = document.getHeaderFooter();
+        outputListener.println("Get old head and footer 0 succeeded, text is " + headerFooter.getText(0));
+        outputListener.println("Change head and footer 0 succeeded, new text is ComPDFKit Samples");
+        headerFooter.setText(0, "ComPDFKit Samples");
+        headerFooter.update();
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "HeaderFooterTest/EditHeaderFooterTest.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in EditHeaderFooterTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void clearHeaderFooterTest(){
+        outputListener.println("Samples 4 : Clean all header and footer");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "HeaderFooterTest/AddCommonHeaderFooter.pdf");
+        document.open(file.getAbsolutePath());
+        CPDFHeaderFooter headerFooter = document.getHeaderFooter();
+        outputListener.println("");
+        headerFooter.clear();
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "HeaderFooterTest/ClearHeaderFooter.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in ClearHeaderFooter.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+}

+ 56 - 0
samples/src/main/java/com/compdfkit/samples/samples/ImageExtractTest.java

@@ -0,0 +1,56 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+import java.io.FileFilter;
+
+
+public class ImageExtractTest extends PDFSamples {
+
+    public ImageExtractTest(){
+        setTitle(R.string.image_extract_test_title);
+        setDescription(R.string.image_extract_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1: Extract all images in the document");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "ImageExtractTest.pdf"));
+        for (int i = 0; i < document.getPageCount(); i++) {
+            File extractDir = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "imageExtract/ImageExtractTest_"+i+"/");
+            extractDir.delete();
+            document.pageAtIndex(i).extractImages(extractDir.getAbsolutePath());
+            File[] images = extractDir.listFiles();
+            if (images != null && images.length>0) {
+                for (File image : images) {
+                    getOutputFileList().add(image.getAbsolutePath());
+                    outputListener.println(image.getName());
+                }
+            }
+        }
+        document.close();
+        printFooter();
+    }
+}

+ 316 - 0
samples/src/main/java/com/compdfkit/samples/samples/InteractiveFormsTest.java

@@ -0,0 +1,316 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.os.Environment;
+
+import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.form.CPDFCheckboxWidget;
+import com.compdfkit.core.annotation.form.CPDFComboboxWidget;
+import com.compdfkit.core.annotation.form.CPDFListboxWidget;
+import com.compdfkit.core.annotation.form.CPDFPushbuttonWidget;
+import com.compdfkit.core.annotation.form.CPDFRadiobuttonWidget;
+import com.compdfkit.core.annotation.form.CPDFSignatureWidget;
+import com.compdfkit.core.annotation.form.CPDFTextWidget;
+import com.compdfkit.core.annotation.form.CPDFWidget;
+import com.compdfkit.core.annotation.form.CPDFWidgetItem;
+import com.compdfkit.core.document.CPDFDestination;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.action.CPDFAction;
+import com.compdfkit.core.document.action.CPDFGoToAction;
+import com.compdfkit.core.document.action.CPDFUriAction;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.OutputListener;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+
+import java.io.File;
+
+
+public class InteractiveFormsTest extends PDFSamples {
+
+    public InteractiveFormsTest() {
+        setTitle(R.string.interactive_forms_test_title);
+        setDescription(R.string.interactive_forms_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+
+        printHead();
+        CPDFDocument document = CPDFDocument.createDocument(SampleApplication.getInstance());
+        // Create a blank new page and add some form fields.
+        document.insertBlankPage(0, 595, 842);
+        document.insertBlankPage(1, 595, 842);
+
+        createTestForms(document);
+        printFormsMessage(document);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "forms/Create_From_Test.pdf");
+        saveSamplePDF(document, file, true);
+        deleteForm();
+        printFooter();
+    }
+
+    private void createTestForms(CPDFDocument document) {
+        outputListener.println("Samples 1 : Create test forms");
+        // create new Form Fields and Widget Annotations.
+        int pageNumber = 0;
+        RectF pageSize = document.getPageSize(pageNumber);
+        CPDFPage cpdfPage = document.pageAtIndex(pageNumber);
+
+        //Insert a single-line TextField.
+        RectF singleLineTextRect = new RectF(28, 32, 237, 75);
+        singleLineTextRect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), singleLineTextRect);
+        CPDFTextWidget singleLineTextWidget = (CPDFTextWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_TextField);
+        singleLineTextWidget.setRect(singleLineTextRect);
+        singleLineTextWidget.setFieldName("TextField1");
+        singleLineTextWidget.setText("Basic Text Field");
+        singleLineTextWidget.setFontColor(Color.BLACK);
+        singleLineTextWidget.setFontSize(15);
+        singleLineTextWidget.updateAp();
+
+        //Insert a multiline TextField.
+        RectF multilineTextRect = new RectF(28, 97, 237, 189);
+        multilineTextRect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), multilineTextRect);
+        CPDFTextWidget multiLineTextWidget = (CPDFTextWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_TextField);
+        multiLineTextWidget.setRect(multilineTextRect);
+        multiLineTextWidget.setFieldName("TextField2");
+        multiLineTextWidget.setText("Basic Text Field\nBasic Text Field\nBasic Text Field");
+        multiLineTextWidget.setMultiLine(true);
+        multiLineTextWidget.setFontColor(Color.BLACK);
+        multiLineTextWidget.setFontSize(15);
+        multiLineTextWidget.updateAp();
+
+        //Insert a ListBox widget.
+        RectF listBoxRect = new RectF(267, 32, 567, 138);
+        listBoxRect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), listBoxRect);
+        CPDFListboxWidget listBoxWidget = (CPDFListboxWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_ListBox);
+        listBoxWidget.setRect(listBoxRect);
+        listBoxWidget.setFieldName("ListBox1");
+        CPDFWidgetItem[] listBoxItems = new CPDFWidgetItem[]{
+                new CPDFWidgetItem("List Box No.1", "List Box No.1"),
+                new CPDFWidgetItem("List Box No.2", "List Box No.2"),
+                new CPDFWidgetItem("List Box No.3", "List Box No.3"),
+        };
+        listBoxWidget.setOptionItems(listBoxItems);
+        listBoxWidget.setSelectedIndexes(new int[]{1});
+        listBoxWidget.updateAp();
+
+        //Insert a ComboBox Widget.
+        RectF comboBoxRect = new RectF(267, 143, 567, 189);
+        comboBoxRect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), comboBoxRect);
+        CPDFComboboxWidget comboBoxWidget = (CPDFComboboxWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_ComboBox);
+        comboBoxWidget.setRect(comboBoxRect);
+        comboBoxWidget.setFieldName("ComboBox1");
+        CPDFWidgetItem[] comboBoxItems = new CPDFWidgetItem[]{
+                new CPDFWidgetItem("Combo Box No.1", "Combo Box No.1"),
+                new CPDFWidgetItem("Combo Box No.2", "Combo Box No.2"),
+                new CPDFWidgetItem("Combo Box No.3", "Combo Box No.3"),
+        };
+        comboBoxWidget.setOptionItems(comboBoxItems, new int[]{1});
+        comboBoxWidget.updateAp();
+
+        //Insert a Form Signature Widget (unsigned)
+        RectF signatureRect = new RectF(28, 206, 237, 301);
+        signatureRect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), signatureRect);
+        CPDFSignatureWidget signatureWidget = (CPDFSignatureWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_SignatureFields);
+        signatureWidget.setFieldName("Signature1");
+        signatureWidget.setRect(signatureRect);
+        signatureWidget.updateAp();
+
+        //Insert a PushButton to jump to a page.
+        RectF pushButton1Rect = new RectF(267, 203, 401, 235);
+        pushButton1Rect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), pushButton1Rect);
+        CPDFPushbuttonWidget pushButtonWidget1 = (CPDFPushbuttonWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_PushButton);
+        pushButtonWidget1.setRect(pushButton1Rect);
+        pushButtonWidget1.setFieldName("PushButton1");
+        pushButtonWidget1.setFontColor(Color.BLACK);
+        pushButtonWidget1.setFontSize(15);
+        pushButtonWidget1.setButtonTitle("PushButton");
+        //set PushButton jump to a page action
+        CPDFGoToAction goToAction = new CPDFGoToAction();
+        CPDFDestination destination = new CPDFDestination(1, 0, 842, 0F);
+        goToAction.setDestination(document, destination);
+        pushButtonWidget1.setButtonAction(goToAction);
+        pushButtonWidget1.updateAp();
+
+        //Insert a PushButton to jump to a website.
+        RectF pushButton2Rect = new RectF(433, 203, 567, 235);
+        pushButton2Rect = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), pushButton2Rect);
+        CPDFPushbuttonWidget pushButtonWidget2 = (CPDFPushbuttonWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_PushButton);
+        pushButtonWidget2.setRect(pushButton2Rect);
+        pushButtonWidget2.setFieldName("PushButton2");
+        pushButtonWidget2.setFontColor(Color.BLACK);
+        pushButtonWidget2.setFontSize(15);
+        pushButtonWidget2.setButtonTitle("PushButton");
+        //set PushButton jump to a website
+        CPDFUriAction uriAction = new CPDFUriAction();
+        uriAction.setUri("https://www.compdf.com/");
+        pushButtonWidget2.setButtonAction(uriAction);
+        pushButtonWidget2.updateAp();
+
+        //Insert CheckBox Widget
+        RectF checkBox1 = new RectF(267, 251, 299, 283);
+        checkBox1 = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), checkBox1);
+        CPDFCheckboxWidget checkboxWidget = (CPDFCheckboxWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_CheckBox);
+        checkboxWidget.setRect(checkBox1);
+        checkboxWidget.setFieldName("CheckBox1");
+        checkboxWidget.setFillColor(Color.parseColor("#CCE5E5FF"));
+        checkboxWidget.setBorderColor(Color.BLACK);
+        checkboxWidget.setBorderWidth(2F);
+        checkboxWidget.setChecked(false);
+        checkboxWidget.updateAp();
+
+        RectF checkBox2 = new RectF(326, 251, 358, 283);
+        checkBox2 = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), checkBox2);
+        CPDFCheckboxWidget checkboxWidget2 = (CPDFCheckboxWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_CheckBox);
+        checkboxWidget2.setRect(checkBox2);
+        checkboxWidget2.setFieldName("CheckBox1");
+        checkboxWidget2.setFillColor(Color.parseColor("#CCE5E5FF"));
+        checkboxWidget2.setBorderColor(Color.BLACK);
+        checkboxWidget2.setBorderWidth(2F);
+        checkboxWidget2.setChecked(true);
+        checkboxWidget2.updateAp();
+
+        RectF radioButton1 = new RectF(385, 251, 424, 290);
+        radioButton1 = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), radioButton1);
+        CPDFRadiobuttonWidget radiobuttonWidget1 = (CPDFRadiobuttonWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_RadioButton);
+        radiobuttonWidget1.setRect(radioButton1);
+        radiobuttonWidget1.setFieldName("RadioButton");
+        radiobuttonWidget1.setCheckStyle(CPDFWidget.CheckStyle.CK_Circle);
+        radiobuttonWidget1.setFillColor(Color.parseColor("#CCE5E5FF"));
+        radiobuttonWidget1.setBorderColor(Color.BLACK);
+        radiobuttonWidget1.setBorderWidth(2F);
+        radiobuttonWidget1.setChecked(false);
+        radiobuttonWidget1.setFieldName("RadioButton1");
+        radiobuttonWidget1.updateAp();
+
+        RectF radioButton2 = new RectF(450, 251, 489, 290);
+        radioButton2 = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), radioButton2);
+        CPDFRadiobuttonWidget radiobuttonWidget2 = (CPDFRadiobuttonWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_RadioButton);
+        radiobuttonWidget2.setRect(radioButton2);
+        radiobuttonWidget2.setFieldName("RadioButton");
+        radiobuttonWidget2.setCheckStyle(CPDFWidget.CheckStyle.CK_Circle);
+        radiobuttonWidget2.setFillColor(Color.parseColor("#CCE5E5FF"));
+        radiobuttonWidget2.setBorderColor(Color.BLACK);
+        radiobuttonWidget2.setBorderWidth(2F);
+        // Check the widget (by default it is unchecked).
+        radiobuttonWidget2.setChecked(true);
+        radiobuttonWidget2.setFieldName("RadioButton1");
+        radiobuttonWidget2.updateAp();
+
+        RectF radioButton3 = new RectF(515, 251, 554, 290);
+        radioButton3 = cpdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), radioButton3);
+        CPDFRadiobuttonWidget radiobuttonWidget3 = (CPDFRadiobuttonWidget) cpdfPage.addFormWidget(CPDFWidget.WidgetType.Widget_RadioButton);
+        radiobuttonWidget3.setRect(radioButton3);
+        radiobuttonWidget3.setFieldName("RadioButton");
+        radiobuttonWidget3.setCheckStyle(CPDFWidget.CheckStyle.CK_Circle);
+        radiobuttonWidget3.setFillColor(Color.parseColor("#CCE5E5FF"));
+        radiobuttonWidget3.setBorderColor(Color.BLACK);
+        radiobuttonWidget3.setBorderWidth(2F);
+        radiobuttonWidget3.setChecked(false);
+        radiobuttonWidget3.setFieldName("RadioButton1");
+        radiobuttonWidget3.updateAp();
+        outputListener.println("Done. Result saved in Create_Form_Test.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+
+    private void deleteForm(){
+        outputListener.println("Samples 3 : delete first form");
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "forms/Create_From_Test.pdf");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(file.getAbsolutePath());
+        CPDFPage page = document.pageAtIndex(0);
+        for (CPDFAnnotation annotation : page.getAnnotations()) {
+            if (annotation.getType() == CPDFAnnotation.Type.WIDGET){
+                page.deleteAnnotation(annotation);
+                break;
+            }
+        }
+        File resultsForms = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "forms/Delete_Form_Test.pdf");
+        saveSamplePDF(document, resultsForms,true);
+        outputListener.println("Done. Result saved in Delete_Form_Test.pdf");
+    }
+
+    private void printFormsMessage(CPDFDocument document) {
+        outputListener.println("Samples 2 : print forms message");
+        for (int i = 0; i < document.getPageCount(); i++) {
+            CPDFPage page = document.pageAtIndex(i);
+            for (CPDFAnnotation annotation : page.getAnnotations()) {
+                switch (annotation.getType()) {
+                    case WIDGET:
+                        CPDFWidget cpdfWidget = (CPDFWidget) annotation;
+                        outputListener.println("Field name : " + cpdfWidget.getFieldName());
+                        switch (cpdfWidget.getWidgetType()) {
+                            case Widget_TextField:
+                                outputListener.println("Field partial name : " + ((CPDFTextWidget) cpdfWidget).getText());
+                                break;
+                            case Widget_ListBox:
+                                CPDFListboxWidget listBoxWidget = (CPDFListboxWidget) cpdfWidget;
+                                CPDFWidgetItem[] options = listBoxWidget.getOptions();
+                                int[] selectedIndexs = listBoxWidget.getSelectedIndexes();
+                                if (options != null && selectedIndexs != null) {
+                                    CPDFWidgetItem selectItem = options[selectedIndexs[0]];
+                                    outputListener.println("Field Select Item : " + selectItem.text);
+                                }
+                                break;
+                            case Widget_ComboBox:
+                                CPDFComboboxWidget comboBoxWidget = (CPDFComboboxWidget) cpdfWidget;
+                                CPDFWidgetItem[] comboBoxOptions = comboBoxWidget.getOptions();
+                                int[] selectedIndexs1 = comboBoxWidget.getSelectedIndexes();
+                                if (comboBoxOptions != null && selectedIndexs1 != null) {
+                                    CPDFWidgetItem selectItem = comboBoxOptions[selectedIndexs1[0]];
+                                    outputListener.println("Field Select Item : " + selectItem.text);
+                                }
+                                break;
+                            case Widget_SignatureFields:
+                                CPDFSignatureWidget signatureWidget = (CPDFSignatureWidget) cpdfWidget;
+                                outputListener.println("Field isSigned : " + signatureWidget.isSigned());
+                                break;
+                            case Widget_CheckBox:
+                                outputListener.println("Field isChecked : " + ((CPDFCheckboxWidget) cpdfWidget).isChecked());
+                                break;
+                            case Widget_RadioButton:
+                                outputListener.println("Field isChecked : " + ((CPDFRadiobuttonWidget) cpdfWidget).isChecked());
+                                break;
+                            case Widget_PushButton:
+                                CPDFPushbuttonWidget pushButtonWidget = (CPDFPushbuttonWidget) cpdfWidget;
+                                outputListener.println("Field PushButton Title : " + pushButtonWidget.getButtonTitle());
+                                CPDFAction cpdfAction = pushButtonWidget.getButtonAction();
+                                if (cpdfAction != null) {
+                                    if (cpdfAction instanceof CPDFUriAction) {
+                                        outputListener.println("Field PushButton Action : " + ((CPDFUriAction) cpdfAction).getUri());
+                                    } else if (cpdfAction instanceof CPDFGoToAction) {
+                                        outputListener.println("Field PushButton Action : Jump to page " + (((CPDFGoToAction) cpdfAction).getDestination(document).getPageIndex() + 1) + " of the document");
+                                    }
+                                }
+                                break;
+                            default:
+                                break;
+                        }
+                        RectF widgetRect = cpdfWidget.getRect();
+                        RectF position = page.convertRectFromPage(false, document.getPageSize(i).width(),
+                                document.getPageSize(i).height(),widgetRect);
+                        outputListener.println(String.format("Field Position : %d, %d, %d, %d", (int)position.left, (int)position.top, (int)position.right, (int)position.bottom));
+                        outputListener.println("Widget type : " + cpdfWidget.getWidgetType().name());
+                        outputListener.println("--------------------------------------------");
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+    }
+}

+ 103 - 0
samples/src/main/java/com/compdfkit/samples/samples/OutlineTest.java

@@ -0,0 +1,103 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDestination;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.CPDFOutline;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+public class OutlineTest extends PDFSamples {
+
+    public OutlineTest(){
+        setTitle(R.string.outline_test_title);
+        setDescription(R.string.outline_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        createOutline();
+        printOutline();
+        printFooter();
+    }
+
+    /**
+     * Sample 1 : create outline test
+     */
+    private void createOutline(){
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1 : Crate Outline Test");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFOutline rootOutline = null;
+        if (document.getOutlineRoot() == null) {
+            rootOutline = document.newOutlineRoot();
+        }else {
+            rootOutline = document.getOutlineRoot();
+        }
+        CPDFOutline child = insertOutline(rootOutline, "Outline 1", 0);
+        insertOutline(child, "Outline 1 child", 0);
+        insertOutline(rootOutline, "Outline 2", 1);
+        insertOutline(rootOutline, "Outline 3", 2);
+        insertOutline(rootOutline, "Outline 4", 3);
+        insertOutline(rootOutline, "Outline 5", 4);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "outline/CreateOutlineTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Results saved in\nCreateOutlineTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private CPDFOutline insertOutline(CPDFOutline rootOutline, String title, int pageIndex){
+        CPDFOutline child = rootOutline.insertChildAtIndex(pageIndex);
+        child.setTitle(title);
+        CPDFDestination destination = new CPDFDestination(pageIndex, 0,0, 1F);
+        child.setDestination(destination);
+        return child;
+    }
+
+    private void printOutline(){
+        outputListener.println("Samples 2 : Print outline Info");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File sampleFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "outline/CreateOutlineTest.pdf");
+        document.open(sampleFile.getAbsolutePath());
+        CPDFOutline outlineRoot = document.getOutlineRoot();
+        if (outlineRoot != null) {
+            printChildOutline(outlineRoot.getChildList());
+        }
+    }
+
+    private void printChildOutline(CPDFOutline[] outlines){
+        for (CPDFOutline outline : outlines) {
+            StringBuilder tab = new StringBuilder();
+            if (outline.getLevel() > 1) {
+                for (int i = 0; i < outline.getLevel(); i++) {
+                    tab.append("\t");
+                }
+            }
+            outputListener.println(tab.toString() + "->" + outline.getTitle());
+            if (outline.getChildList() != null && outline.getChildList().length > 0){
+                printChildOutline(outline.getChildList());
+            }
+        }
+    }
+}

+ 76 - 0
samples/src/main/java/com/compdfkit/samples/samples/PDFATest.java

@@ -0,0 +1,76 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.Environment;
+
+import com.compdfkit.core.common.CPDFDate;
+import com.compdfkit.core.document.CPDFBookmark;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.utils.TTimeUtil;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+import java.util.List;
+
+
+public class PDFATest extends PDFSamples {
+
+    public PDFATest(){
+        setTitle(R.string.pdf_a_test_title);
+        setDescription(R.string.pdf_a_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        convertToPDFA1a();
+        convertToPDFA1b();
+        printFooter();
+    }
+
+    /**
+     * Samples 1 : convert pdf document to pdfA1a
+     */
+    private void convertToPDFA1a(){
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1 : convert to pdf A1a");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.convertType(CPDFDocument.PDFDocumentType.PDFTypeA1a);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "PDFATest/PDFA1aTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in PDFA1aTest.pdf");
+        outputListener.println("--------------------------------------------");
+
+    }
+
+
+    /**
+     * Samples 2 : convert pdf document to pdfA1b
+     */
+    private void convertToPDFA1b(){
+        outputListener.println("Samples 1 : convert to pdf A1b");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.convertType(CPDFDocument.PDFDocumentType.PDFTypeA1b);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "PDFATest/PDFA1bTest.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in PDFA1bTest.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+}

+ 204 - 0
samples/src/main/java/com/compdfkit/samples/samples/PDFPageTest.java

@@ -0,0 +1,204 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class PDFPageTest extends PDFSamples {
+
+
+    public PDFPageTest() {
+        setTitle(R.string.pdf_page_test_title);
+        setDescription(R.string.pdf_page_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        insertBlankPage();
+        insertPdfPage();
+        splitPages();
+        mergePages();
+        deletePages();
+        rotatePage();
+        replacePages();
+        extractPages();
+        printFooter();
+    }
+
+    /**
+     * Samples - 1: Insert a blank A4-sized page into the sample document
+     */
+    private void insertBlankPage() {
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Samples 1: Insert a blank A4-sized page into the sample document");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.insertBlankPage(1, 595, 842);
+        outputListener.println("Insert PageIndex : 1");
+        outputListener.println("Size : 595*842");
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/Insert_Blank_Page.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nInsert_Blank_Page.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples - 2: Import pages from another document into the example document
+     */
+    private void insertPdfPage() {
+        outputListener.println("Samples 2: Import pages from another document into the example document");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        outputListener.println("Open the document to be imported");
+        CPDFDocument document2 = new CPDFDocument(SampleApplication.getInstance());
+        document2.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+        document.importPages(document2, new int[]{0}, 1);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/Import_Document_Page.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nImport_Document_Page.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples - 3: Split a PDF document into multiple pages
+     */
+    private void splitPages() {
+        outputListener.println("Samples 3: Split a PDF document into multiple pages");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        for (int i = 0; i < document.getPageCount(); i++) {
+            CPDFDocument newDocument = CPDFDocument.createDocument(SampleApplication.getInstance());
+            newDocument.importPages(document, new int[]{i}, 0);
+            File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/CommonFivePage_Split_Page_" + (i + 1) + ".pdf");
+            outputListener.println("Done. Result saved in \nCommonFivePage_Split_Page_" + (i + 1) + ".pdf");
+            saveSamplePDF(newDocument, file, true);
+        }
+        document.close();
+        outputListener.println("Done!");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples - 4: Merge split documents
+     */
+    private void mergePages() {
+        outputListener.println("Samples 4: Merge split documents");
+        int pageNum = 5;
+        CPDFDocument document = CPDFDocument.createDocument(SampleApplication.getInstance());
+        for (int i = 0; i < pageNum; i++) {
+            File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/CommonFivePage_Split_Page_" + (i + 1) + ".pdf");
+            if (file.exists()) {
+                outputListener.println("Opening " + file.getName());
+                CPDFDocument newDocument = new CPDFDocument(SampleApplication.getInstance());
+                newDocument.open(file.getAbsolutePath());
+                document.importPages(newDocument, new int[]{0}, i);
+            }
+        }
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/Merge_Pages.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nMerge_Pages.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples - 5: Delete the specified page of the document
+     */
+    private void deletePages() {
+        outputListener.println("Samples 5: Delete the specified page of the document");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        int[] evenNumbers = getEvenNumbers(0, document.getPageCount() - 1);
+        document.removePages(evenNumbers);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/Remove_Page.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nRemove_Page.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    public static int[] getEvenNumbers(int start, int end) {
+        int size = (end - start) / 2 + 1;
+        int[] evenNumbers = new int[size];
+        int index = 0;
+        for (int i = start; i <= end; i++) {
+            if (i % 2 != 0) {
+                evenNumbers[index] = i;
+                index++;
+            }
+        }
+        return evenNumbers;
+    }
+
+    /**
+     * Samples - 6: Rotate document pages
+     */
+    private void rotatePage() {
+        outputListener.println("Samples 6: Rotate document pages");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.pageAtIndex(0).setRotation(90);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/Rotate_Pages.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nRotate_Pages.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples - 7: Replace specified pages of example documentation with other documentation specified pages
+     */
+    private void replacePages() {
+        outputListener.println("Samples 7: Replace specified pages of example documentation with other documentation specified pages");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        document.removePages(new int[]{1});
+        //open second pdf Document
+        CPDFDocument document2 = new CPDFDocument(SampleApplication.getInstance());
+        document2.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+        document.importPages(document2, new int[]{0}, 1);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/Replace_Pages.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nReplace_Pages.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples - 8: Extract specific pages of a document
+     */
+    private void extractPages() {
+        outputListener.println("Samples 8: Extract specific pages of a document");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFDocument newDocument = CPDFDocument.createDocument(SampleApplication.getInstance());
+        newDocument.importPages(document, new int[]{1}, 0);
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "pdfPage/CommonFivePage_Extract_Page_1.pdf");
+        outputListener.println("Done. Result saved in \nCommonFivePage_Extract_Page_1.pdf");
+        saveSamplePDF(newDocument, file, true);
+        document.close();
+        outputListener.println("--------------------------------------------");
+    }
+}

+ 63 - 0
samples/src/main/java/com/compdfkit/samples/samples/PDFRedactTest.java

@@ -0,0 +1,63 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.os.Environment;
+
+import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.CPDFRedactAnnotation;
+import com.compdfkit.core.annotation.CPDFTextAttribute;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class PDFRedactTest extends PDFSamples {
+
+    public PDFRedactTest() {
+        setTitle(R.string.redact_test_title);
+        setDescription(R.string.redact_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        outputListener.println("Samples 1 : add redact");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+        CPDFPage pdfPage = document.pageAtIndex(0);
+        CPDFRedactAnnotation redactAnnotation = (CPDFRedactAnnotation) pdfPage.addAnnot(CPDFAnnotation.Type.REDACT);
+        RectF pageSize = pdfPage.getSize();
+        RectF insertRect = new RectF(100, 220, 200, 320);
+        //coordinate conversion
+        insertRect = pdfPage.convertRectToPage(false, pageSize.width(), pageSize.height(), insertRect);
+
+        redactAnnotation.setRect(insertRect);
+        CPDFTextAttribute textAttribute = new CPDFTextAttribute(
+                CPDFTextAttribute.FontNameHelper.obtainFontName(CPDFTextAttribute.FontNameHelper.FontType.Helvetica, false, false), 14, Color.YELLOW);
+        redactAnnotation.setTextDa(textAttribute);
+        redactAnnotation.setOverLayText("REDACT");
+        redactAnnotation.setFillColor(Color.BLACK);
+        redactAnnotation.applyRedaction();
+        File resultsFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "RedactTest/AddRedactTest.pdf");
+        saveSamplePDF(document, resultsFile, false);
+        outputListener.println("Done. Results saved in AddRedactTest.pdf");
+        printFooter();
+    }
+}

+ 76 - 0
samples/src/main/java/com/compdfkit/samples/samples/PDFToImageTest.java

@@ -0,0 +1,76 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFBackground;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+import com.compdfkit.ui.utils.CPDFBitmapUtils;
+
+import java.io.File;
+
+public class PDFToImageTest extends PDFSamples {
+
+    public PDFToImageTest(){
+        setTitle(R.string.pdf_to_image_test_title);
+        setDescription(R.string.pdf_to_image_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        for (int i = 0; i < document.getPageCount(); i++) {
+            RectF size = document.getPageSize(i);
+            Bitmap bitmap = Bitmap.createBitmap((int) size.width(), (int)size.height(), Bitmap.Config.RGB_565);
+            boolean success = document.renderPageAtIndex(
+                    bitmap,
+                    i,
+                    (int) size.width(),
+                    (int) size.height(),
+                    0,
+                    0,
+                    (int) size.width(),
+                    (int) size.height(),
+                    Color.WHITE,
+                    255,
+                    0,
+                    true,
+                    true
+            );
+            if (success){
+                File file = new File(SampleApplication.getInstance().getExternalFilesDir(
+                        Environment.DIRECTORY_DOCUMENTS
+                ), "PDFToImageTest/CommonFivePage/PDFToImageTest"+i+".png");
+                file.getParentFile().mkdirs();
+                CPDFBitmapUtils.saveBitmap(bitmap,file.getAbsolutePath());
+                if (file.exists()){
+                    outputListener.println("Done. Results saved in "+file.getName());
+                    addFileList(file.getAbsolutePath());
+                }
+            }
+        }
+        document.close();
+        printFooter();
+    }
+}

+ 111 - 0
samples/src/main/java/com/compdfkit/samples/samples/TextExtractTest.java

@@ -0,0 +1,111 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.RectF;
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.core.page.CPDFTextPage;
+import com.compdfkit.core.page.CPDFTextRange;
+import com.compdfkit.core.page.CPDFTextSelection;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class TextExtractTest extends PDFSamples {
+
+    public TextExtractTest(){
+        setTitle(R.string.text_extract_test_title);
+        setDescription(R.string.text_extract_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        extractPageText();
+        extractAllPageText();
+        extractRectRangeText();
+        printFooter();
+    }
+
+    /**
+     * Samples 1: Extract all text content in the specified page
+     */
+    private void extractPageText(){
+        outputListener.println("Samples 1: Extract all text content in the specified page");
+        outputListener.println("Opening the Samples PDF File");
+        outputListener.println("The text content of the first page of the document:");
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Text : ");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+        CPDFPage page = document.pageAtIndex(0);
+        CPDFTextPage textPage = page.getTextPage();
+        String pageText = textPage.getText(new CPDFTextRange(0, textPage.getCountChars() - 1) );
+        outputListener.print(pageText);
+        outputListener.println("\nDone!");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples 2: Extract all text content of the document
+     */
+    private void extractAllPageText(){
+        outputListener.println("Samples 2: Extract all text content of the document");
+        outputListener.println("Opening the Samples PDF File");
+        outputListener.println("--------------------------------------------");
+        outputListener.println("Text : ");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+        for (int i = 0; i < document.getPageCount(); i++) {
+            CPDFPage page = document.pageAtIndex(i);
+            CPDFTextPage textPage = page.getTextPage();
+            String pageText = textPage.getText(new CPDFTextRange(0, textPage.getCountChars() - 1) );
+            outputListener.print(pageText);
+        }
+        outputListener.println("Done!");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void extractRectRangeText(){
+        outputListener.println("Samples 3: Extract Select Rect Range Text");
+        outputListener.println("Opening the Samples PDF File");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+        CPDFPage page = document.pageAtIndex(0);
+        CPDFTextPage textPage = page.getTextPage();
+        // Extract the text within the range of (0, 0, 500, 500) on the first page
+        RectF selectRect = new RectF(0f, 0f, 300f, 300f);
+        RectF size = page.getSize();
+        selectRect = page.convertRectFromPage(false, size.width(), size.height(), selectRect);
+        CPDFTextSelection[] selections = textPage.getSelectionsByLineForRect(selectRect);
+        outputListener.println("Range : (0, 0, 300, 300)");
+        outputListener.println("Text : ");
+        for (int i = 0; i < selections.length; i++) {
+            CPDFTextSelection textSelection = selections[i];
+            if (textSelection == null) {
+                continue;
+            }
+            String text = textPage.getText(textSelection.getTextRange());
+            outputListener.print(text);
+        }
+        outputListener.println("\nDone!");
+        outputListener.println("--------------------------------------------");
+    }
+}

+ 129 - 0
samples/src/main/java/com/compdfkit/samples/samples/TextSearchTest.java

@@ -0,0 +1,129 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+
+import android.graphics.Color;
+import android.graphics.RectF;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.TextUtils;
+
+import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.CPDFHighlightAnnotation;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.page.CPDFPage;
+import com.compdfkit.core.page.CPDFTextPage;
+import com.compdfkit.core.page.CPDFTextRange;
+import com.compdfkit.core.page.CPDFTextSearcher;
+import com.compdfkit.core.page.CPDFTextSelection;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+import com.compdfkit.ui.reader.CPDFReaderView;
+import com.compdfkit.ui.textsearch.ITextSearcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TextSearchTest extends PDFSamples {
+
+    public TextSearchTest() {
+        setTitle(R.string.text_search_test_title);
+        setDescription(R.string.text_search_test_desc);
+    }
+
+    private Handler handler = new Handler(Looper.getMainLooper());
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        handler.post(() -> {
+            printHead();
+            CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+            document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "text.pdf"));
+            CPDFReaderView readerView = new CPDFReaderView(SampleApplication.getInstance());
+            readerView.setPDFDocument(document);
+            readerView.reloadPages();
+            List<CPDFTextRange> list = startSearch(readerView, "PDF");
+            if (list != null && list.size() > 0) {
+                CPDFTextRange textRange = list.get(0);
+                CPDFPage pdfPage = document.pageAtIndex(0);
+                CPDFTextPage pdfTextPage = pdfPage.getTextPage();
+
+                CPDFTextSelection[] textSelectionArr = pdfTextPage.getSelectionsByTextForRange(textRange);
+                //Then, add a highlight annotation for the specific area.
+                RectF annotRect = new RectF();
+                CPDFHighlightAnnotation highlightAnnotation = (CPDFHighlightAnnotation) pdfPage.addAnnot(CPDFAnnotation.Type.HIGHLIGHT);
+                highlightAnnotation.setColor(Color.YELLOW);
+                highlightAnnotation.setAlpha((255 / 2));
+                RectF[] quadRects = new RectF[textSelectionArr.length];
+                StringBuilder markedTextSb = new StringBuilder();
+                int len = textSelectionArr.length;
+                for (int i = 0; i < len; i++) {
+                    CPDFTextSelection textSelection = textSelectionArr[i];
+                    if (textSelection == null) {
+                        continue;
+                    }
+                    RectF rect = new RectF(textSelection.getRectF());
+                    if (annotRect.isEmpty()) {
+                        annotRect.set(rect);
+                    } else {
+                        annotRect.union(rect);
+                    }
+                    quadRects[i] = new RectF(textSelection.getRectF());
+                    String text = pdfTextPage.getText(textSelection.getTextRange());
+                    if (!TextUtils.isEmpty(text)) {
+                        markedTextSb.append(text);
+                    }
+                }
+                highlightAnnotation.setQuadRects(quadRects);
+                highlightAnnotation.setMarkedText(markedTextSb.toString());
+                highlightAnnotation.setRect(annotRect);
+                highlightAnnotation.updateAp();
+                outputListener.println(annotRect.toString());
+            }
+            outputListener.println("the key `PDF` have " + list.size() + " results");
+            File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "TextSearchTest/Text_Search_Resluts.pdf");
+            saveSamplePDF(document, file, false);
+            printFooter();
+        });
+    }
+
+    public static List<CPDFTextRange> startSearch(CPDFReaderView readerView, String keywords) {
+        ITextSearcher textSearcher = readerView.getTextSearcher();
+        if (null == textSearcher) {
+            return null;
+        }
+        CPDFDocument document = readerView.getPDFDocument();
+        if (null == document) {
+            return null;
+        }
+        textSearcher.setSearchConfig(keywords, CPDFTextSearcher.PDFSearchOptions.PDFSearchCaseInsensitive);
+        List<CPDFTextRange> searchTextInfoList = new ArrayList<>();
+        for (int i = 0; i < document.getPageCount(); i++) {
+            CPDFPage page = document.pageAtIndex(i);
+            CPDFTextPage textPage = page.getTextPage();
+            if ((null == textPage) || !textPage.isValid()) {
+                continue;
+            }
+            final List<CPDFTextRange> searchPageContent = textSearcher.searchKeyword(i);
+            if (searchPageContent.size() > 0) {
+                searchTextInfoList.addAll(searchPageContent);
+            }
+            page.close();
+        }
+        return searchTextInfoList;
+    }
+}

+ 173 - 0
samples/src/main/java/com/compdfkit/samples/samples/WatermarkTest.java

@@ -0,0 +1,173 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.samples;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.os.Environment;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.watermark.CPDFWatermark;
+import com.compdfkit.samples.PDFSamples;
+import com.compdfkit.samples.R;
+import com.compdfkit.samples.SampleApplication;
+import com.compdfkit.samples.util.FileUtils;
+import com.compdfkit.samples.util.OutputListener;
+
+import java.io.File;
+
+
+public class WatermarkTest extends PDFSamples {
+
+    public WatermarkTest() {
+        setTitle(R.string.watermark_test_title);
+        setDescription(R.string.watermark_test_desc);
+    }
+
+    @Override
+    protected void run(OutputListener outputListener) {
+        super.run(outputListener);
+        printHead();
+        addTextWatermark();
+        addImageWatermark();
+        addTilesWatermark();
+        deleteWatermark();
+        printFooter();
+    }
+
+    /**
+     * Samples 1 : Insert a text watermark in the center of all pages of the document
+     */
+    private void addTextWatermark() {
+        outputListener.println("Sample 1 : Insert Text Watermark");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFWatermark watermark = document.createWatermark(CPDFWatermark.Type.WATERMARK_TYPE_TEXT);
+        watermark.setText("ComPDFKit");
+        watermark.setTextRGBColor(Color.RED);
+        watermark.setFontSize(30);
+        watermark.setOpacity(0.5F);
+        watermark.setRotation(45);
+        watermark.setVertalign(CPDFWatermark.Vertalign.WATERMARK_VERTALIGN_CENTER);
+        watermark.setHorizalign(CPDFWatermark.Horizalign.WATERMARK_HORIZALIGN_CENTER);
+        watermark.setVertOffset(0);
+        watermark.setHorizOffset(0);
+        watermark.setPages("0,1,2,3,4");
+        printWatermarkInfo(watermark);
+        watermark.update();
+        watermark.release();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "watermarkTest/Text_Watermark_Test.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nText_Watermark_Test.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples 2 : Insert a picture watermark in the center of all pages of the document
+     */
+    private void addImageWatermark() {
+        outputListener.println("Sample 2 : Insert Image Watermark");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFWatermark watermark = document.createWatermark(CPDFWatermark.Type.WATERMARK_TYPE_IMG);
+        Bitmap watermarkImage = BitmapFactory.decodeResource(SampleApplication.getInstance().getResources(), R.mipmap.ic_launcher_foreground);
+        watermark.setImage(watermarkImage, 100, 100);
+        watermark.setOpacity(1F);
+        watermark.setRotation(20);
+        watermark.setVertalign(CPDFWatermark.Vertalign.WATERMARK_VERTALIGN_CENTER);
+        watermark.setHorizalign(CPDFWatermark.Horizalign.WATERMARK_HORIZALIGN_CENTER);
+        watermark.setVertOffset(0);
+        watermark.setHorizOffset(0);
+        watermark.setPages("0,1,2,3,4");
+        printWatermarkInfo(watermark);
+        watermark.update();
+        watermark.release();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "watermarkTest/Image_Watermark_Test.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nImage_Watermark_Test.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    /**
+     * Samples 3 : Insert a tiled text watermark on all pages of the document
+     */
+    private void addTilesWatermark() {
+        outputListener.println("Sample 3 : Insert Text Tiles Watermark");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        document.open(FileUtils.getAssetsTempFile(SampleApplication.getInstance(), "CommonFivePage.pdf"));
+        CPDFWatermark watermark = document.createWatermark(CPDFWatermark.Type.WATERMARK_TYPE_TEXT);
+        watermark.setText("ComPDFKit");
+        watermark.setTextRGBColor(Color.RED);
+        watermark.setFontSize(30);
+        watermark.setOpacity(0.5F);
+        watermark.setRotation(45);
+        watermark.setVertalign(CPDFWatermark.Vertalign.WATERMARK_VERTALIGN_CENTER);
+        watermark.setHorizalign(CPDFWatermark.Horizalign.WATERMARK_HORIZALIGN_CENTER);
+        watermark.setVertOffset(0);
+        watermark.setHorizOffset(0);
+        watermark.setPages("0,1,2,3,4");
+        watermark.setFullScreen(true);
+        watermark.setHorizontalSpacing(100);
+        watermark.setVerticalSpacing(100);
+        printWatermarkInfo(watermark);
+        watermark.update();
+        watermark.release();
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "watermarkTest/Text_Tiles_Watermark_Test.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nText_Tiles_Watermark_Test.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void deleteWatermark() {
+        outputListener.println("Sample 4 : Delete Watermark");
+        CPDFDocument document = new CPDFDocument(SampleApplication.getInstance());
+        File sampleFile = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS),
+                "watermarkTest/Text_Watermark_Test.pdf");
+        document.open(sampleFile.getAbsolutePath());
+        CPDFWatermark watermark = document.getWatermark(0);
+        if (watermark != null) {
+            //remove all page watermarks
+            watermark.clear();
+
+            // Remove the watermark on the second page
+//            watermark.setPages("0,2,3,4");
+//            watermark.update();
+//            watermark.release();
+        }
+        File file = new File(SampleApplication.getInstance().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "watermarkTest/Delete_Watermark_Test.pdf");
+        saveSamplePDF(document, file, true);
+        outputListener.println("Done. Result saved in\nDelete_Watermark_Test.pdf");
+        outputListener.println("--------------------------------------------");
+    }
+
+    private void printWatermarkInfo(CPDFWatermark watermark){
+        if (watermark.getType() == CPDFWatermark.Type.WATERMARK_TYPE_TEXT){
+            outputListener.println("Text : "+ watermark.getText());
+            outputListener.println(String.format("Color : red:%d, green:%d, blue:%d, alpha:%d",
+                    Color.red(watermark.getTextRGBColor()),
+                    Color.green(watermark.getTextRGBColor()),
+                    Color.blue(watermark.getTextRGBColor()),
+                    Color.alpha(watermark.getTextRGBColor())));
+
+            outputListener.println("FontSize : " + watermark.getFontSize());
+        }
+        outputListener.println("Opacity : " + watermark.getOpacity());
+        outputListener.println("Rotation : " + watermark.getRotation());
+        outputListener.println("Vertalign : " + watermark.getVertalign().name());
+        outputListener.println("Horizalign : " + watermark.getHorizalign().name());
+        outputListener.println("VertOffset : " + watermark.getVertOffset());
+        outputListener.println("HorizOffset : " + watermark.getHorizOffset());
+        outputListener.println("Pages : " + watermark.getPages());
+        outputListener.println("VerticalSpacing : " + watermark.getVerticalSpacing());
+        outputListener.println("HorizontalSpacing : " + watermark.getHorizontalSpacing());
+
+    }
+}

+ 20 - 0
samples/src/main/java/com/compdfkit/samples/util/CPDFGlideModule.java

@@ -0,0 +1,20 @@
+package com.compdfkit.samples.util;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.Registry;
+import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.module.AppGlideModule;
+
+@GlideModule
+public class CPDFGlideModule extends AppGlideModule {
+    @Override
+    public boolean isManifestParsingEnabled() {
+        return false;
+    }
+
+}

+ 34 - 0
samples/src/main/java/com/compdfkit/samples/util/DateUtil.java

@@ -0,0 +1,34 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.util;
+
+import android.text.TextUtils;
+
+
+public class DateUtil {
+
+
+    public static String transformPDFDate(String inputDate) {
+        try{
+            if (TextUtils.isEmpty(inputDate) || inputDate.length() < 16) {
+                return "";
+            }
+            String year = inputDate.substring(2, 6);
+            String month = inputDate.substring(6, 8);
+            String day = inputDate.substring(8, 10);
+            String hour = inputDate.substring(10, 12);
+            String minute = inputDate.substring(12, 14);
+            String second = inputDate.substring(14, 16);
+            return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
+        }catch (Exception e){
+            return inputDate;
+        }
+    }
+}

+ 114 - 0
samples/src/main/java/com/compdfkit/samples/util/FileUtils.java

@@ -0,0 +1,114 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.util;
+
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.util.Log;
+
+import androidx.core.content.FileProvider;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+public class FileUtils {
+
+    public static void shareFile(Context context, String title, String type, File file) {
+        try {
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.putExtra(Intent.EXTRA_SUBJECT, title);
+            Uri uri = getUriBySystem(context, file);
+            intent.putExtra(Intent.EXTRA_STREAM, uri);
+            intent.setDataAndType(uri, type);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            context.startActivity(Intent.createChooser(intent, title));
+        } catch (ActivityNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static Uri getUriBySystem(Context context, File file) {
+        try {
+            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
+                return Uri.fromFile(file);
+            } else {
+                return FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
+            }
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static String getAssetsTempFile(Context context, String assetsName) {
+        return copyFileFromAssets(context, assetsName, context.getCacheDir().getAbsolutePath(), assetsName, true);
+    }
+
+    public static String copyFileFromAssets(Context context,
+                                            String assetName,
+                                            String savePath,
+                                            String saveName,
+                                            final boolean overwriteExisting) {
+        //if save path folder not exists, create directory
+        File dir = new File(savePath);
+        if (!dir.exists()) {
+            if (!dir.mkdirs()) {
+                Log.d("FileUtils", "mkdir error: " + savePath);
+                return null;
+            }
+        }
+
+        // 拷贝文件
+        String filename = savePath + "/" + saveName;
+        File file = new File(filename);
+        if (file.exists()) {
+            file.delete();
+        }
+        if (!file.exists() || overwriteExisting) {
+            try {
+                InputStream inStream = context.getAssets().open(assetName);
+                FileOutputStream fileOutputStream = new FileOutputStream(filename);
+                int byteread;
+                byte[] buffer = new byte[1024];
+                while ((byteread = inStream.read(buffer)) != -1) {
+                    fileOutputStream.write(buffer, 0, byteread);
+                }
+                fileOutputStream.flush();
+                inStream.close();
+                fileOutputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            Log.d("FileUtils", "[copyFileFromAssets] copy asset file: " + assetName + " to : " + filename);
+            return file.getAbsolutePath();
+        } else {
+            Log.d("FileUtils", "[copyFileFromAssets] file is exist: " + filename);
+            return file.getAbsolutePath();
+        }
+    }
+
+    public static void deleteFile(File file) {
+        if (file.isDirectory()) {
+            File[] files = file.listFiles();
+            for (int i = 0; i < files.length; i++) {
+                File f = files[i];
+                deleteFile(f);
+            }
+            file.delete();//如要保留文件夹,只删除文件,请注释这行
+        } else if (file.exists()) {
+            file.delete();
+        }
+    }
+}

+ 59 - 0
samples/src/main/java/com/compdfkit/samples/util/LoggingOutputListener.java

@@ -0,0 +1,59 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.util;
+
+
+import android.view.View;
+import android.widget.ScrollView;
+
+import androidx.appcompat.widget.AppCompatTextView;
+
+public class LoggingOutputListener implements OutputListener{
+
+    private AppCompatTextView logTextview;
+
+    private ScrollView scrollView;
+
+    public LoggingOutputListener(AppCompatTextView logTextview, ScrollView scrollView){
+        this.logTextview = logTextview;
+        this.scrollView = scrollView;
+    }
+
+    @Override
+    public void print(String output) {
+        scrollView.post(()->{
+            logTextview.append(output);
+            scrollView.fullScroll(View.FOCUS_DOWN);
+        });
+    }
+
+    @Override
+    public void print() {
+        logTextview.append("");
+    }
+
+    @Override
+    public void println(String output) {
+        scrollView.post(()->{
+            logTextview.append(output+"\n");
+            scrollView.fullScroll(View.FOCUS_DOWN);
+        });
+    }
+
+    @Override
+    public void println() {
+        logTextview.append("");
+    }
+
+    @Override
+    public void printError(String errorMessage) {
+        println(errorMessage);
+    }
+}

+ 24 - 0
samples/src/main/java/com/compdfkit/samples/util/OutputListener.java

@@ -0,0 +1,24 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.samples.util;
+
+
+public interface OutputListener {
+
+    void print(String output);
+
+    void print();
+
+    void println(String output);
+
+    void println();
+
+    void printError(String errorMessage);
+}

+ 5 - 0
samples/src/main/res/drawable/baseline_arrow_back_24.xml

@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:tint="#000000" android:viewportHeight="24"
+    android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
+</vector>

+ 19 - 0
samples/src/main/res/layout/activity_sample_list.xml

@@ -0,0 +1,19 @@
+<?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=".SampleListActivity">
+
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/rv_sample_list"
+        tools:listitem="@layout/layout_sample_list_item"
+        />
+
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 65 - 0
samples/src/main/res/layout/fragment_sample_detail.xml

@@ -0,0 +1,65 @@
+<?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"
+    android:padding="8dp">
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Sample Description" />
+
+    <com.google.android.material.button.MaterialButton
+        android:id="@+id/btn_run"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:text="@string/run"
+        app:cornerRadius="4dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_description"
+
+        />
+
+    <com.google.android.material.button.MaterialButton
+        android:id="@+id/btn_open_files"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:text="@string/open_files"
+        app:cornerRadius="4dp"
+        app:layout_constraintStart_toEndOf="@id/btn_run"
+        app:layout_constraintTop_toTopOf="@id/btn_run" />
+
+
+    <ScrollView
+        android:id="@+id/scroll_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginTop="8dp"
+        android:fillViewport="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/btn_run">
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_logging"
+            style="?android:attr/textAppearanceSmall"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textIsSelectable="true"
+            android:background="#80E4E0E0"
+            android:padding="4dp"
+            tools:text="Done!" />
+
+
+    </ScrollView>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 22 - 0
samples/src/main/res/layout/layout_sample_list_item.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginHorizontal="8dp"
+    android:background="?attr/selectableItemBackground"
+    android:orientation="vertical">
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sample_title"
+        android:layout_width="match_parent"
+        android:layout_height="55dp"
+        android:gravity="center_vertical"
+        android:textSize="16sp"
+        tools:text="FormsTest" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0.5dp"
+        android:background="?attr/colorControlHighlight" />
+</LinearLayout>

+ 5 - 0
samples/src/main/res/mipmap-anydpi-v26/ic_launcher.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@android:color/white"/>
+    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
+</adaptive-icon>

+ 5 - 0
samples/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@color/white"/>
+    <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
+</adaptive-icon>

BIN
samples/src/main/res/mipmap-hdpi/ic_launcher.png


BIN
samples/src/main/res/mipmap-hdpi/ic_launcher_foreground.png


BIN
samples/src/main/res/mipmap-hdpi/ic_launcher_round.png


BIN
samples/src/main/res/mipmap-mdpi/ic_launcher.png


BIN
samples/src/main/res/mipmap-mdpi/ic_launcher_foreground.png


BIN
samples/src/main/res/mipmap-mdpi/ic_launcher_round.png


BIN
samples/src/main/res/mipmap-xhdpi/ic_launcher.png


BIN
samples/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png


BIN
samples/src/main/res/mipmap-xhdpi/ic_launcher_round.png


BIN
samples/src/main/res/mipmap-xxhdpi/ic_launcher.png


BIN
samples/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png


BIN
samples/src/main/res/mipmap-xxhdpi/ic_launcher_round.png


BIN
samples/src/main/res/mipmap-xxxhdpi/ic_launcher.png


BIN
samples/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png


BIN
samples/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png


+ 7 - 0
samples/src/main/res/values-night/themes.xml

@@ -0,0 +1,7 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Base.Theme.Compdfkit_android_demo" parent="Theme.Material3.DayNight">
+        <!-- Customize your dark theme here. -->
+        <!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
+    </style>
+</resources>

+ 5 - 0
samples/src/main/res/values/colors.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+</resources>

+ 70 - 0
samples/src/main/res/values/strings.xml

@@ -0,0 +1,70 @@
+<resources>
+    <string name="app_name">Samples_ComPDFKit</string>
+    
+    <string name="sample_header">Running %s sample&#8230;</string>
+    <string name="sample_footer">Done!</string>
+
+    <string name="interactive_forms_test_title">InteractiveFormsTest</string>
+    <string name="interactive_forms_test_desc">InteractiveFormsTest Desc</string>
+
+    <string name="pdf_page_test_title">PDFPageTest</string>
+    <string name="pdf_page_test_desc">PDFPageTest Desc</string>
+
+    <string name="image_extract_test_title">ImageExtractTest</string>
+    <string name="image_extract_test_desc">ImageExtractTest Desc</string>
+
+    <string name="text_extract_test_title">TextExtractTest</string>
+    <string name="text_extract_test_desc">TextExtractTest Desc</string>
+
+    <string name="watermark_test_title">WatermarkTest</string>
+    <string name="watermark_test_desc">WatermarkTest Desc</string>
+
+    <string name="background_test_title">BackgroundTest</string>
+    <string name="background_test_desc">BackgroundTest Desc</string>
+
+    <string name="bookmark_test_title">BookmarkTest</string>
+    <string name="bookmark_test_desc">BookmarkTest Desc</string>
+
+    <string name="outline_test_title">OutlineTest</string>
+    <string name="outline_test_desc">OutlineTest Desc</string>
+
+    <string name="pdf_to_image_test_title">PDFToImageTest</string>
+    <string name="pdf_to_image_test_desc">PDFToImageTest Desc</string>
+
+    <string name="text_search_test_title">TextSearchTest</string>
+    <string name="text_search_test_desc">TextSearchTest Desc</string>
+
+    <string name="annotation_test_title">AnnotationTest</string>
+    <string name="annotation_test_desc">AnnotationTest Desc</string>
+
+    <string name="header_footer_test_title">HeaderFooterTest</string>
+    <string name="header_footer_test_desc">HeaderFooterTest Desc</string>
+
+    <string name="document_test_title">DocumentTest</string>
+    <string name="document_test_desc">documentTest Desc</string>
+
+    <string name="bates_test_title">BatesTest</string>
+    <string name="bates_test_desc">BatesTest Desc</string>
+
+    <string name="redact_test_title">RedactTest</string>
+    <string name="redact_test_desc">RedactTest Desc</string>
+
+    <string name="encrypt_test_title">EncryptTest</string>
+    <string name="encrypt_test_desc">EncryptTest Desc</string>
+
+    <string name="pdf_a_test_title">PDFATest</string>
+    <string name="pdf_a_test_desc">PDFATest Desc</string>
+
+    <string name="flatten_test_title">FlattenTest</string>
+    <string name="flatten_test_desc">FlattenTest Desc</string>
+
+    <string name="annotation_import_export_test_title">AnnotationImportExportTest</string>
+    <string name="annotation_import_export_test_desc">AnnotationImportExportTest Desc</string>
+
+    <string name="tools_allowed">Allowed</string>
+    <string name="tools_not_allowed">Not Allowed</string>
+
+    <string name="run">Run</string>
+    <string name="open_files">Open Files</string>
+    <string name="choose_a_file_to_open">Choose a file to open</string>
+</resources>

+ 9 - 0
samples/src/main/res/values/themes.xml

@@ -0,0 +1,9 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Base.Theme.Compdfkit_android_demo" parent="Theme.Material3.DayNight">
+        <!-- Customize your light theme here. -->
+        <!-- <item name="colorPrimary">@color/my_light_primary</item> -->
+    </style>
+
+    <style name="Theme.Compdfkit_android_demo" parent="Base.Theme.Compdfkit_android_demo" />
+</resources>

+ 25 - 0
samples/src/main/res/xml/tools_file_paths.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths>
+
+    <cache-path name="compdfkit/"
+        path="." />
+
+    <cache-path name="media/"
+        path="compdfkit/temp/" />
+
+    <files-path
+        name="media/"
+        path="."/>
+
+    <files-path name="media/"
+        path="compdfkit/temp/" />
+
+    <files-path
+        name="file/"
+        path="."/>
+
+    <external-path
+        name="compdf/"
+        path="."/>
+
+</paths>

+ 17 - 0
samples/src/test/java/com/compdfkit/samples/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.compdfkit.samples;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 0
settings.gradle

@@ -22,3 +22,4 @@ include ':DocsEditor'
 include ':ComPDFKit_Tools'
 include ':compdfkit-repo:compdfkit'
 include ':compdfkit-repo:compdfkit-ui'
+include ':samples'