Browse Source

Merge branch 'compdfkit_demo_android' of git.kdan.cc:others/kmpdfkit_demo into compdfkit_demo_android

* 'compdfkit_demo_android' of git.kdan.cc:others/kmpdfkit_demo:
  PDFTool(Android) - 数字签名功能
  PDFTool(Android) - 1.数字签名功能代码合并
  PDFTool(Android) - 1.数字签名列表、详情等界面
  PDFTool(Android) - 1.导入、创建数字签名证书交互界面
libai 1 year ago
parent
commit
45decaab3a
100 changed files with 5241 additions and 117 deletions
  1. 0 3
      Annotations/build.gradle
  2. 33 44
      Annotations/src/main/java/com/compdfkit/annotations/PDFAnnotationSampleActivity.java
  3. BIN
      ComPDFKit_Repo/compdfkit/ComPDFKit.aar
  4. 3 5
      ComPDFKit_Tools/build.gradle
  5. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfpic/CImageStyleFragment.java
  6. 28 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfsignature/CAddSignatureActivity.java
  7. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfsignature/data/CSignatureDatas.java
  8. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfstamp/data/CStampDatas.java
  9. 12 31
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/activity/CBasicActivity.java
  10. 44 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/activity/CPermissionActivity.java
  11. 89 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/fragment/CBasicBottomSheetDialogFragment.java
  12. 51 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/fragment/CPermissionFragment.java
  13. 0 2
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/contextmenu/impl/CEditImageContextMenuView.java
  14. 86 2
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CFileUtils.java
  15. 78 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CPermissionUtil.java
  16. 43 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CUriUtil.java
  17. 33 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/BaseActivityResultLauncher.java
  18. 0 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CImageResultContracts.java
  19. 14 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CMultiplePermissionResultLauncher.java
  20. 18 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CPermissionResultLauncher.java
  21. 25 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CSelectPDFDocumentResultContract.java
  22. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/animation/CFillScreenManager.java
  23. 9 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/animation/ConstraintSetUtils.java
  24. 17 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/date/CDateUtil.java
  25. 0 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/image/CBitmapUtil.java
  26. 130 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/view/CEditText.java
  27. 5 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/viewutils/CDimensUtils.java
  28. 13 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/window/CModeSwitchDialogFragment.java
  29. 8 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/CToolBar.java
  30. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/font/CExternFontSpinnerAdapter.java
  31. 1 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/font/CFontSpinnerAdapter.java
  32. 0 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CAnnotStyle.java
  33. 0 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/stamp/CPDFStampTextView.java
  34. 0 4
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPDFViewCtrl.java
  35. 5 1
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPreviewMode.java
  36. 0 4
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/contenteditor/pdfproperties/CEditImagePropertiesFragment.java
  37. 0 3
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/forms/pdfformbar/CFormToolbar.java
  38. 0 4
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/forms/pdfproperties/pdfsign/CustomSignatureWidgetImpl.java
  39. 78 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/CSignatureToolBar.java
  40. 298 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/CertificateDigitalDatas.java
  41. 20 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/SignatureStatus.java
  42. 64 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/bean/CPDFCertAttrDataItem.java
  43. 93 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/bean/CPDFOwnerItemData.java
  44. 35 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/bean/CPDFSignatureItemData.java
  45. 209 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CImportCertificateDigitalDialog.java
  46. 159 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CPDFSelectDigitalSignatureDialog.java
  47. 93 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CountryReginSpinnerAdapter.java
  48. 339 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CreateCertificateDigitalDialog.java
  49. 129 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertAttrDatas.java
  50. 57 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertAttrListAdapter.java
  51. 127 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDetailsDialog.java
  52. 102 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDetailsListAdapter.java
  53. 111 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDigitalSignAttributesDialog.java
  54. 141 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDigitalSignInfoDialog.java
  55. 152 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/signlist/CPDFCertDigitalSignListDialog.java
  56. 61 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/signlist/adapter/CertDigitalSignListAdapter.java
  57. 8 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/interfaces/COnSelectCertFileListener.java
  58. 129 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/pdfproperties/pdfsign/CDigitalSignStyleData.java
  59. 244 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/pdfproperties/pdfsign/CDigitalSignStylePreviewView.java
  60. 89 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/pdfproperties/pdfsign/CDigitalSignatureWidgetImpl.java
  61. 295 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/preview/CDigitalSignStylePreviewDialog.java
  62. 89 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/preview/view/CSignStylePositionView.java
  63. 103 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/preview/view/CSignStyleReasonView.java
  64. 117 0
      ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/verify/view/CVerifySignStatusView.java
  65. 7 0
      ComPDFKit_Tools/src/main/res/anim/tools_slide_in_left.xml
  66. 7 0
      ComPDFKit_Tools/src/main/res/anim/tools_slide_out_right.xml
  67. 10 0
      ComPDFKit_Tools/src/main/res/drawable-night/tools_ic_digital_signature.xml
  68. 9 0
      ComPDFKit_Tools/src/main/res/drawable/tools_bg_import_certificate_digital_id_error_item.xml
  69. 15 0
      ComPDFKit_Tools/src/main/res/drawable/tools_bg_import_certificate_digital_id_item.xml
  70. 23 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_compdfkit_logo.xml
  71. 13 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_dark_oval_close.xml
  72. 7 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_checkbox.xml
  73. 15 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_checkbox_normal.xml
  74. 15 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_checkbox_select.xml
  75. 27 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_is_failures.xml
  76. 18 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_is_valid.xml
  77. 17 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_is_wrong.xml
  78. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_signature.xml
  79. 27 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_import_digital_signature.xml
  80. 10 0
      ComPDFKit_Tools/src/main/res/drawable/tools_ic_sign_none.xml
  81. 5 0
      ComPDFKit_Tools/src/main/res/drawable/tools_import_certificate_digital_id_btn.xml
  82. 6 0
      ComPDFKit_Tools/src/main/res/drawable/tools_sign_cert_info_btn_bg.xml
  83. 19 0
      ComPDFKit_Tools/src/main/res/drawable/tools_signature_toolbar_btn_corner_status_bg.xml
  84. 16 0
      ComPDFKit_Tools/src/main/res/layout-land/tools_properties_signature_style_add_activity.xml
  85. 71 0
      ComPDFKit_Tools/src/main/res/layout-land/tools_sign_style_preview_dialog.xml
  86. 243 0
      ComPDFKit_Tools/src/main/res/layout-land/tools_sign_style_preview_main.xml
  87. 0 1
      ComPDFKit_Tools/src/main/res/layout/tools_dialog_tool_bar.xml
  88. 40 0
      ComPDFKit_Tools/src/main/res/layout/tools_layout_c_edit_text.xml
  89. 9 0
      ComPDFKit_Tools/src/main/res/layout/tools_pdf_mode_switch_dialog_fragment.xml
  90. 17 0
      ComPDFKit_Tools/src/main/res/layout/tools_properties_signature_style_add_activity.xml
  91. 36 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_cert_digital_sign_list_fragment.xml
  92. 98 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_cert_digital_sign_list_item.xml
  93. 28 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_attributes_fragment.xml
  94. 25 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_attributes_list_head_item.xml
  95. 47 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_attributes_list_item.xml
  96. 29 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_details_dialog.xml
  97. 45 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_details_list_item.xml
  98. 144 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_digital_sign_info_fragment.xml
  99. 41 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_create_cert_digital_id_fragment.xml
  100. 0 0
      ComPDFKit_Tools/src/main/res/layout/tools_sign_create_cert_digital_id_info_layout.xml

+ 0 - 3
Annotations/build.gradle

@@ -52,7 +52,4 @@ dependencies {
     implementation 'com.google.android.material:material:1.8.0'
     implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
     implementation project(':ComPDFKit_Tools')
-
-    implementation 'pub.devrel:easypermissions:3.0.0'
-
 }

+ 33 - 44
Annotations/src/main/java/com/compdfkit/annotations/PDFAnnotationSampleActivity.java

@@ -5,17 +5,17 @@ import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.view.View;
 
 import androidx.activity.result.ActivityResultLauncher;
 import androidx.activity.result.contract.ActivityResultContracts;
-import androidx.annotation.NonNull;
 
 import com.compdfkit.annotations.databinding.AnnotationPdfSampleActivityBinding;
 import com.compdfkit.core.annotation.CPDFAnnotation;
-import com.compdfkit.tools.common.activity.CBasicActivity;
+import com.compdfkit.tools.common.basic.activity.CBasicPDFActivity;
 import com.compdfkit.tools.common.utils.CFileUtils;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
+import com.compdfkit.tools.common.utils.activitycontracts.CSelectPDFDocumentResultContract;
 import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
 import com.compdfkit.tools.common.utils.task.CExtractAssetFileTask;
 import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
@@ -23,18 +23,14 @@ import com.compdfkit.tools.common.views.pdfbota.CPDFBOTA;
 import com.compdfkit.tools.common.views.pdfbota.CPDFBotaDialogFragment;
 import com.compdfkit.tools.common.views.pdfbota.CPDFBotaFragmentTabs;
 import com.compdfkit.tools.common.views.pdfproperties.CAnnotationType;
-import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
 import com.compdfkit.tools.common.views.pdfview.CPreviewMode;
 import com.compdfkit.tools.viewer.pdfsearch.CSearchResultDialogFragment;
 import com.compdfkit.ui.reader.CPDFReaderView;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 
-import pub.devrel.easypermissions.AppSettingsDialog;
-import pub.devrel.easypermissions.EasyPermissions;
 
-public class PDFAnnotationSampleActivity extends CBasicActivity {
+public class PDFAnnotationSampleActivity extends CBasicPDFActivity {
 
     /**
      * assets folder pdf file
@@ -45,9 +41,8 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
 
     CAnnotSampleScreenManager screenManager = new CAnnotSampleScreenManager();
 
-    private ActivityResultLauncher<Intent> selectDocumentLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
-        if (result.getData() != null && result.getData().getData() != null) {
-            Uri uri = result.getData().getData();
+    private ActivityResultLauncher<Void> selectDocumentLauncher = registerForActivityResult(new CSelectPDFDocumentResultContract(), uri -> {
+        if (uri != null) {
             CFileUtils.takeUriPermission(this, uri);
             binding.pdfView.resetAnnotationType();
             binding.pdfView.openPDF(uri);
@@ -155,7 +150,7 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
                 sharePDF(binding.pdfView);
             });
             menuWindow.addItem(R.drawable.tools_ic_new_file, R.string.tools_open_document, v1 -> {
-                if (hasPermissions(STORAGE_PERMISSIONS)) {
+                if (CPermissionUtil.hasStoragePermissions(this)) {
                     selectDocument();
                 } else {
                     requestStoragePermissions();
@@ -168,9 +163,17 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
 
     private void requestStoragePermissions() {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-            startActivity(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION));
+            CPermissionUtil.openManageAllFileAppSettings(this);
         } else {
-            EasyPermissions.requestPermissions(this, "request permission", REQUEST_EXTERNAL_PERMISSION, STORAGE_PERMISSIONS);
+            multiplePermissionResultLauncher.launch(STORAGE_PERMISSIONS, result -> {
+                if (CPermissionUtil.hasStoragePermissions(this)) {
+                    selectDocument();
+                }else {
+                    if (!CPermissionUtil.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
+                        showPermissionsRequiredDialog();
+                    }
+                }
+            });
         }
     }
 
@@ -181,8 +184,15 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
             screenManager.changeWindowStatus(type);
             //You are required to grant recording permission when selecting voice notes
             if (type == CAnnotationType.SOUND) {
-                if (!EasyPermissions.hasPermissions(this, Manifest.permission.RECORD_AUDIO)) {
-                    EasyPermissions.requestPermissions(this, getString(R.string.tools_use_sound_annot), 111, Manifest.permission.RECORD_AUDIO);
+                if (!hasPermission(Manifest.permission.RECORD_AUDIO)) {
+                    permissionResultLauncher.launch(Manifest.permission.RECORD_AUDIO, hasRecordAudioPermission -> {
+                        if (!hasRecordAudioPermission){
+                            binding.pdfView.resetAnnotationType();
+                            if (!CPermissionUtil.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)){
+                                showPermissionsRequiredDialog();
+                            }
+                        }
+                    });
                 }
             }
         });
@@ -190,6 +200,8 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
         binding.inkCtrlView.setFragmentManager(getSupportFragmentManager());
     }
 
+
+
     private void initSearchBar() {
         binding.pdfSearchToolBar.initWithPDFView(binding.pdfView);
         binding.pdfSearchToolBar.onSearchQueryResults(list -> {
@@ -210,11 +222,11 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
 
     private void selectDocument() {
         if (binding.pdfView.getCPdfReaderView().getPDFDocument() == null){
-            selectDocumentLauncher.launch(CFileUtils.getContentIntent());
+            selectDocumentLauncher.launch(null);
             return;
         }
         if (!binding.pdfView.getCPdfReaderView().getPDFDocument().hasChanges()) {
-            selectDocumentLauncher.launch(CFileUtils.getContentIntent());
+            selectDocumentLauncher.launch(null);
             return;
         }
         CAlertDialog alertDialog = CAlertDialog.newInstance(getString(com.compdfkit.tools.R.string.tools_save_title), getString(com.compdfkit.tools.R.string.tools_save_message));
@@ -222,42 +234,19 @@ public class PDFAnnotationSampleActivity extends CBasicActivity {
             //save pdf document
             binding.pdfView.savePDF((filePath, pdfUri) -> {
                 alertDialog.dismiss();
-                selectDocumentLauncher.launch(CFileUtils.getContentIntent());
+                selectDocumentLauncher.launch(null);
             }, e -> {
                 alertDialog.dismiss();
-                selectDocumentLauncher.launch(CFileUtils.getContentIntent());
+                selectDocumentLauncher.launch(null);
             });
         });
         alertDialog.setCancelClickListener(v -> {
             alertDialog.dismiss();
-            selectDocumentLauncher.launch(CFileUtils.getContentIntent());
+            selectDocumentLauncher.launch(null);
         });
         alertDialog.show(getSupportFragmentManager(), "alertDialog");
     }
 
-    @Override
-    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
-        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
-        if (requestCode == REQUEST_EXTERNAL_PERMISSION) {
-            if (EasyPermissions.hasPermissions(this, STORAGE_PERMISSIONS)) {
-                selectDocument();
-            }
-        } else if (requestCode == 111) {
-            if (!EasyPermissions.hasPermissions(this, permissions)) {
-                if (EasyPermissions.somePermissionPermanentlyDenied(this, Arrays.asList(permissions))) {
-                    new AppSettingsDialog.Builder(this)
-                            .build().show();
-                } else {
-                    binding.pdfView.resetAnnotationType();
-                }
-            }
-        } else if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE) {
-            if (EasyPermissions.hasPermissions(this, permissions)) {
-
-            }
-        }
-    }
-
     @Override
     public void onBackPressed() {
         if (binding.pdfView != null) {

BIN
ComPDFKit_Repo/compdfkit/ComPDFKit.aar


+ 3 - 5
ComPDFKit_Tools/build.gradle

@@ -47,9 +47,7 @@ dependencies {
     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'
-
-    implementation 'androidx.appcompat:appcompat:1.6.1'
-    implementation 'com.google.android.material:material:1.8.0'
-    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-    implementation 'com.google.android.flexbox:flexbox:3.0.0'
+    api 'androidx.appcompat:appcompat:1.6.1'
+    api 'com.google.android.material:material:1.8.0'
+    api 'androidx.constraintlayout:constraintlayout:2.1.4'
 }

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfpic/CImageStyleFragment.java

@@ -33,7 +33,7 @@ public class CImageStyleFragment extends CBasicPropertiesFragment {
     private ActivityResultLauncher<CImageResultContracts.RequestType> imageLauncher = registerForActivityResult(new CImageResultContracts(), result -> {
         if (result != null && viewModel != null) {
             File file = new File(getContext().getFilesDir(), CFileUtils.CACHE_FOLDER);
-            String path = CFileUtils.copyImageToInternalDirectory(getContext(), result, file.getAbsolutePath(), "pic_" + CDateUtil.getDataTime(CDateUtil.NORMAL_DATE_FORMAT) + ".png");
+            String path = CFileUtils.copyFileToInternalDirectory(getContext(), result, file.getAbsolutePath(), "pic_" + CDateUtil.getDataTime(CDateUtil.NORMAL_DATE_FORMAT) + ".png");
             viewModel.getStyle().setImagePath(path);
             dismissStyleDialog();
         }

+ 28 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfsignature/CAddSignatureActivity.java

@@ -11,6 +11,7 @@ package com.compdfkit.tools.annotation.pdfproperties.pdfsignature;
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.net.Uri;
@@ -45,12 +46,22 @@ import com.google.android.material.floatingactionbutton.FloatingActionButton;
 
 public class CAddSignatureActivity extends AppCompatActivity implements View.OnClickListener {
 
+    public static final String EXTRA_TITLE = "extra_title";
+
+    public static final String EXTRA_SHOW_NONE_TYPE = "extra_show_none_type";
+
+    public static final String EXTRA_SCREEN_ORIENTATION = "extra_screen_orientation";
+
+    public static final String RESULT_NONE = "result_none";
+
     private AppCompatImageView ivAddDrawSignature;
 
     private AppCompatImageView ivAddTextSignature;
 
     private AppCompatImageView ivAddPicSignature;
 
+    private AppCompatImageView ivNone;
+
     private CToolBar cToolBar;
 
     private CPDFSignatureEditView writingView;
@@ -89,6 +100,8 @@ public class CAddSignatureActivity extends AppCompatActivity implements View.OnC
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        int screenOrientation = getIntent().getIntExtra(EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        setRequestedOrientation(screenOrientation);
         setContentView(R.layout.tools_properties_signature_style_add_activity);
         writingView = findViewById(R.id.writing_view);
         editText = findViewById(R.id.et_text);
@@ -98,6 +111,7 @@ public class CAddSignatureActivity extends AppCompatActivity implements View.OnC
         ivAddDrawSignature = findViewById(R.id.iv_add_draw_signature);
         ivAddTextSignature = findViewById(R.id.iv_add_text_signature);
         ivAddPicSignature = findViewById(R.id.iv_add_pic_signature);
+        ivNone = findViewById(R.id.iv_none);
         cToolBar = findViewById(R.id.tool_bar);
         colorListView = findViewById(R.id.color_list_view);
         btnSave = findViewById(R.id.btn_save);
@@ -133,6 +147,11 @@ public class CAddSignatureActivity extends AppCompatActivity implements View.OnC
             saveBitmap();
         } else if (v.getId() == R.id.btn_clean) {
             cleanSignature();
+        } else if (v.getId() == R.id.iv_none){
+            Intent intent = new Intent();
+            intent.putExtra(RESULT_NONE, true);
+            setResult(Activity.RESULT_OK, intent);
+            onBackPressed();
         }
     }
 
@@ -142,6 +161,7 @@ public class CAddSignatureActivity extends AppCompatActivity implements View.OnC
         ivAddDrawSignature.setOnClickListener(this);
         ivAddTextSignature.setOnClickListener(this);
         ivAddPicSignature.setOnClickListener(this);
+        ivNone.setOnClickListener(this);
         btnClean.setOnClickListener(this);
         btnSave.setOnClickListener(this);
         colorListView.setOnColorSelectListener(this::setSignatureColor);
@@ -170,6 +190,14 @@ public class CAddSignatureActivity extends AppCompatActivity implements View.OnC
 
     private void initView() {
         writingView.setAttribute(20,  Color.BLACK, 255);
+        if (getIntent().hasExtra(EXTRA_TITLE)) {
+            String title = getIntent().getStringExtra(EXTRA_TITLE);
+            cToolBar.setTitle(title);
+        }
+        if (getIntent().hasExtra(EXTRA_SHOW_NONE_TYPE)){
+            boolean showNoneType = getIntent().getBooleanExtra(EXTRA_SHOW_NONE_TYPE, false);
+            ivNone.setVisibility(showNoneType ? View.VISIBLE : View.GONE);
+        }
     }
 
     private void switchTab(int selectPosition) {

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfsignature/data/CSignatureDatas.java

@@ -71,7 +71,7 @@ public class CSignatureDatas {
 
     public static String saveSignatureImage(Context context, Uri imageUri){
         File file = new File(context.getFilesDir(), CFileUtils.SIGNATURE_FOLDER);
-        return CFileUtils.copyImageToInternalDirectory(context, imageUri, file.getAbsolutePath(),
+        return CFileUtils.copyFileToInternalDirectory(context, imageUri, file.getAbsolutePath(),
                 "signature_"+ CDateUtil.getDataTime(CDateUtil.NORMAL_DATE_FORMAT)+".png");
     }
 }

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/annotation/pdfproperties/pdfstamp/data/CStampDatas.java

@@ -141,7 +141,7 @@ public class CStampDatas {
 
     public static String saveStampImage(Context context, Uri imageUri) {
         File file = new File(context.getFilesDir(), CFileUtils.IMAGE_STAMP_FOLDER);
-        return CFileUtils.copyImageToInternalDirectory(context, imageUri, file.getAbsolutePath(),
+        return CFileUtils.copyFileToInternalDirectory(context, imageUri, file.getAbsolutePath(),
                 "stamp_" + CDateUtil.getDataTime(CDateUtil.NORMAL_DATE_FORMAT) + ".png");
     }
 }

+ 12 - 31
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/activity/CBasicActivity.java

@@ -7,19 +7,14 @@
  * This notice may not be removed from this file.
  */
 
-package com.compdfkit.tools.common.activity;
+package com.compdfkit.tools.common.basic.activity;
 
 
-import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.graphics.Color;
-import android.net.Uri;
 import android.os.Build;
 import android.os.Environment;
-import android.provider.Settings;
 import android.text.TextUtils;
 
-import androidx.appcompat.app.AppCompatActivity;
 import androidx.core.content.ContextCompat;
 
 import com.compdfkit.core.annotation.CPDFLineAnnotation;
@@ -38,7 +33,9 @@ import com.compdfkit.tools.annotation.pdfproperties.pdfnote.CPDFtextAnnotImpl;
 import com.compdfkit.tools.common.contextmenu.CPDFContextMenuHelper;
 import com.compdfkit.tools.common.contextmenu.impl.CEditImageContextMenuView;
 import com.compdfkit.tools.common.contextmenu.impl.CEditTextContextMenuView;
+import com.compdfkit.tools.common.contextmenu.impl.CSignatureContextMenuView;
 import com.compdfkit.tools.common.utils.CFileUtils;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleType;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.manager.CStyleManager;
 import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
@@ -54,30 +51,11 @@ import com.compdfkit.tools.viewer.pdfinfo.CPDFDocumentInfoDialogFragment;
 
 import java.io.File;
 
-public class CBasicActivity extends AppCompatActivity {
+public class CBasicPDFActivity extends CPermissionActivity {
 
     protected static final int REQUEST_EXTERNAL_PERMISSION = 1233;
 
-    protected final static String[] STORAGE_PERMISSIONS = new String[]{
-            android.Manifest.permission.READ_EXTERNAL_STORAGE,
-            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-    };
-
-    protected boolean hasPermissions(String... perms) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
-            return true;
-        }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-            return true;
-        }
-        for (String perm : perms) {
-            if (ContextCompat.checkSelfPermission(this, perm)
-                    != PackageManager.PERMISSION_GRANTED) {
-                return false;
-            }
-        }
-        return true;
-    }
+    protected int curEditMode = CPDFEditPage.LoadUnknown;
 
     protected void resetContextMenu(CPDFViewCtrl pdfView, CPreviewMode mode) {
         switch (mode) {
@@ -105,6 +83,12 @@ public class CBasicActivity extends AppCompatActivity {
                                 .defaultFormHelper()
                                 .create(pdfView));
                 break;
+            case Signature:
+                pdfView.getCPdfReaderView().setContextMenuShowListener(
+                        new CPDFContextMenuHelper.Builder()
+                                .setSignatureContextMenu(new CSignatureContextMenuView())
+                                .create(pdfView));
+                break;
             default:
                 break;
         }
@@ -180,7 +164,7 @@ public class CBasicActivity extends AppCompatActivity {
                 document.getAbsolutePath().startsWith("/storage/emulated/0");
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && isExternalFile) {
             if (!Environment.isExternalStorageManager()) {
-                startActivity(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION));
+                CPermissionUtil.openManageAllFileAppSettings(this);
                 return;
             }
         }
@@ -199,9 +183,6 @@ public class CBasicActivity extends AppCompatActivity {
         });
     }
 
-    protected int curEditMode = CPDFEditPage.LoadUnknown;
-
-
     protected void showPageEdit(CPDFViewCtrl pdfView, boolean enterEdit, CPDFPageEditDialogFragment.OnBackLisener backListener) {
         curEditMode = pdfView.getCPdfReaderView().getLoadType();
         pdfView.exitEditMode();

+ 44 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/activity/CPermissionActivity.java

@@ -0,0 +1,44 @@
+package com.compdfkit.tools.common.basic.activity;
+
+
+import android.content.pm.PackageManager;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
+import com.compdfkit.tools.common.utils.activitycontracts.CMultiplePermissionResultLauncher;
+import com.compdfkit.tools.common.utils.activitycontracts.CPermissionResultLauncher;
+import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
+
+
+public class CPermissionActivity extends AppCompatActivity {
+
+    protected final static String[] STORAGE_PERMISSIONS = CPermissionUtil.STORAGE_PERMISSIONS;
+
+    protected CPermissionResultLauncher permissionResultLauncher = new CPermissionResultLauncher(this);
+
+    protected CMultiplePermissionResultLauncher multiplePermissionResultLauncher = new CMultiplePermissionResultLauncher(this);
+
+    public boolean hasPermission(String permission){
+        return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    protected void showPermissionsRequiredDialog(){
+        CAlertDialog alertDialog = CAlertDialog.newInstance(getString(R.string.tools_permission_tips_title), getString(R.string.tools_permission_tips_msg));
+        alertDialog.setCancelable(false);
+        alertDialog.setConfirmClickListener(v -> {
+            toSelfSetting();
+            alertDialog.dismiss();
+        });
+        alertDialog.setCancelClickListener(v -> alertDialog.dismiss());
+        alertDialog.show(getSupportFragmentManager(), "permissionRequiredDialog");
+    }
+
+    protected void toSelfSetting(){
+        CPermissionUtil.toSelfSetting(this);
+    }
+}
+
+

+ 89 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/fragment/CBasicBottomSheetDialogFragment.java

@@ -0,0 +1,89 @@
+/**
+ * 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.tools.common.basic.fragment;
+
+
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.LayoutRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+public abstract class CBasicBottomSheetDialogFragment extends BottomSheetDialogFragment {
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setStyle(STYLE_NORMAL, getStyle());
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        BottomSheetBehavior<View> behavior = BottomSheetBehavior.from((View) getView().getParent());
+        if (fullScreen()) {
+            CDialogFragmentUtil.setBottomSheetDialogFragmentFullScreen(getDialog(), behavior);
+        }
+        CDialogFragmentUtil.setDimAmount(getDialog(), dimAmount());
+        behavior.setDraggable(draggable());
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(layoutId(), container, false);
+        onCreateView(view);
+        return view;
+    }
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        onViewCreate();
+    }
+
+    protected abstract @LayoutRes int layoutId();
+
+    protected int getStyle(){
+        return R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle;
+    }
+
+    protected boolean fullScreen(){
+        return false;
+    }
+
+    protected float dimAmount(){
+        return 0.2F;
+    }
+
+    protected boolean draggable(){
+        return true;
+    }
+
+    protected abstract void onCreateView(View rootView);
+
+    protected abstract void onViewCreate();
+
+    @Override
+    public void onConfigurationChanged(@NonNull Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        CDialogFragmentUtil.setDimAmount(getDialog(), dimAmount());
+    }
+}

+ 51 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/basic/fragment/CPermissionFragment.java

@@ -0,0 +1,51 @@
+/**
+ * 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.tools.common.basic.fragment;
+
+import android.content.pm.PackageManager;
+
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.Fragment;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
+import com.compdfkit.tools.common.utils.activitycontracts.CMultiplePermissionResultLauncher;
+import com.compdfkit.tools.common.utils.activitycontracts.CPermissionResultLauncher;
+import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
+
+
+public class CPermissionFragment extends Fragment {
+
+    protected final static String[] STORAGE_PERMISSIONS = CPermissionUtil.STORAGE_PERMISSIONS;
+
+    protected CPermissionResultLauncher permissionResultLauncher = new CPermissionResultLauncher(this);
+
+    protected CMultiplePermissionResultLauncher multiplePermissionResultLauncher = new CMultiplePermissionResultLauncher(this);
+
+    public boolean hasPermission(String permission){
+        return ContextCompat.checkSelfPermission(getContext(), permission) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    protected void showPermissionsRequiredDialog(){
+        CAlertDialog alertDialog = CAlertDialog.newInstance(getString(R.string.tools_permission_tips_title), getString(R.string.tools_permission_tips_msg));
+        alertDialog.setCancelable(false);
+        alertDialog.setConfirmClickListener(v -> {
+            toSelfSetting();
+            alertDialog.dismiss();
+        });
+        alertDialog.setCancelClickListener(v -> alertDialog.dismiss());
+        alertDialog.show(getChildFragmentManager(), "permissionRequiredDialog");
+    }
+
+    protected void toSelfSetting(){
+        CPermissionUtil.toSelfSetting(getContext());
+    }
+
+}

+ 0 - 2
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/contextmenu/impl/CEditImageContextMenuView.java

@@ -13,14 +13,12 @@ import android.widget.Toast;
 
 import androidx.fragment.app.FragmentActivity;
 
-import com.compdfkit.core.document.CPDFSdk;
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.common.contextmenu.CPDFContextMenuHelper;
 import com.compdfkit.tools.common.contextmenu.interfaces.ContextMenuEditImageProvider;
 import com.compdfkit.tools.common.contextmenu.provider.ContextMenuMultipleLineView;
 import com.compdfkit.tools.common.contextmenu.provider.ContextMenuView;
 import com.compdfkit.tools.common.utils.CToastUtil;
-import com.compdfkit.tools.common.utils.image.CBitmapUtil;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CAnnotStyle;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleDialogFragment;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleType;

+ 86 - 2
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CFileUtils.java

@@ -2,12 +2,15 @@ package com.compdfkit.tools.common.utils;
 
 import android.content.ActivityNotFoundException;
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.Intent;
+import android.database.Cursor;
 import android.net.Uri;
 import android.os.Build;
 import android.os.ParcelFileDescriptor;
-import android.util.Log;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
 
 import androidx.core.content.FileProvider;
 
@@ -24,6 +27,8 @@ import java.io.OutputStream;
 
 public class CFileUtils {
 
+    public static final String CERTIFICATE_DIGITAL_TYPE = "application/x-pkcs12";
+
     public static final String ROOT_FOLDER = "compdfkit/";
 
     public static final String CACHE_FOLDER = "compdfkit/temp";
@@ -100,7 +105,7 @@ public class CFileUtils {
         }
     }
 
-    public static String copyImageToInternalDirectory(
+    public static String copyFileToInternalDirectory(
             Context context,
             Uri imageUri,
             String dir,
@@ -271,6 +276,22 @@ public class CFileUtils {
         return intent;
     }
 
+    public static Intent getIntent(String type) {
+        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+        intent.addCategory(Intent.CATEGORY_OPENABLE);
+        intent.setType(type);
+        intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        return intent;
+    }
+
+    public static Intent selectSystemDir(boolean isOnlyLocal) {
+        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+        intent.putExtra("android.content.extra.SHOW_ADVANCED", isOnlyLocal);
+        intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
+        return intent;
+    }
+
     public static void takeUriPermission(Context context, Uri uri){
         try{
             context.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
@@ -278,4 +299,67 @@ public class CFileUtils {
 
         }
     }
+
+
+    public static String getFilePathFromUri(Context context, Uri uri) {
+        String filePath = null;
+
+        if (DocumentsContract.isDocumentUri(context, uri)) {
+            if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                if ("primary".equalsIgnoreCase(type)) {
+                    filePath = context.getExternalFilesDir(null) + "/" + split[1];
+                }
+            } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
+                final String id = DocumentsContract.getDocumentId(uri);
+                final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));
+                filePath = getDataColumn(context, contentUri, null, null);
+            } else if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                Uri contentUri = null;
+                if ("image".equals(type)) {
+                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+
+                final String selection = "_id=?";
+                final String[] selectionArgs = new String[] { split[1] };
+                filePath = getDataColumn(context, contentUri, selection, selectionArgs);
+            }
+        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
+            filePath = getDataColumn(context, uri, null, null);
+        }
+
+        return filePath;
+    }
+
+    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+        String filePath = null;
+        String[] projection = { MediaStore.Images.Media.DATA };
+        Cursor cursor = null;
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
+            if (cursor != null && cursor.moveToFirst()) {
+                int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+                filePath = cursor.getString(columnIndex);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return filePath;
+    }
+
 }

+ 78 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CPermissionUtil.java

@@ -0,0 +1,78 @@
+/**
+ * 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.tools.common.utils;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.Settings;
+
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+public class CPermissionUtil {
+
+    public final static String[] STORAGE_PERMISSIONS = new String[]{
+            android.Manifest.permission.READ_EXTERNAL_STORAGE,
+            android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+    };
+
+    public static boolean hasStoragePermissions(Context context) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            return true;
+        }
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+            return Environment.isExternalStorageManager();
+        }
+        for (String perm : STORAGE_PERMISSIONS) {
+            if (ContextCompat.checkSelfPermission(context, perm)
+                    != PackageManager.PERMISSION_GRANTED) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static void openManageAllFileAppSettings(Context context){
+        try{
+            Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION, Uri.parse("package:"+context.getPackageName()));
+            context.startActivity(intent);
+        }catch (Exception e){
+            Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
+            context.startActivity(intent);
+        }
+    }
+
+    public static void toSelfSetting(Context context) {
+        Intent mIntent = new Intent();
+        mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        if (Build.VERSION.SDK_INT >= 9) {
+            mIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
+            mIntent.setData(Uri.fromParts("package", context.getPackageName(), null));
+        } else if (Build.VERSION.SDK_INT <= 8) {
+            mIntent.setAction(Intent.ACTION_VIEW);
+            mIntent.setClassName("com.android.settings", "com.android.setting.InstalledAppDetails");
+            mIntent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
+        }
+        context.startActivity(mIntent);
+    }
+
+    public static boolean shouldShowRequestPermissionRationale(Activity activity, String permission){
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M){
+            return true;
+        }
+        return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
+    }
+}

+ 43 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CUriUtil.java

@@ -1,13 +1,16 @@
 package com.compdfkit.tools.common.utils;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
 import android.media.ExifInterface;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
 import android.provider.MediaStore;
 import android.text.TextUtils;
 
 import java.io.File;
+import java.io.InputStream;
 
 public class CUriUtil {
 
@@ -34,6 +37,29 @@ public class CUriUtil {
         return "";
     }
 
+    public static String getUriData(Context context, Uri uri) {
+
+        Cursor cursor = null;
+        final String column = MediaStore.Files.FileColumns.DATA;
+        final String[] projection = {column};
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, null, null,
+                    null);
+            if (cursor != null && cursor.moveToFirst()) {
+                final int column_index = cursor.getColumnIndexOrThrow(column);
+                return cursor.getString(column_index);
+            }
+        } catch (Exception e) {
+
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return "";
+    }
+
     public static String copyUriToInternalCache(Context context, Uri uri) {
         try {
             File file = new File(context.getFilesDir(), CFileUtils.CACHE_FOLDER);
@@ -41,7 +67,7 @@ public class CUriUtil {
             if (TextUtils.isEmpty(fileName)) {
                 fileName = "pic_" + System.currentTimeMillis() + ".png";
             }
-            String image = CFileUtils.copyImageToInternalDirectory(
+            String image = CFileUtils.copyFileToInternalDirectory(
                     context, uri, file.getAbsolutePath(), fileName);
             return image;
         } catch (Exception e) {
@@ -79,4 +105,20 @@ public class CUriUtil {
             return degree;
         }
     }
+
+    public static int getUriFd(Context context, Uri uri){
+        try {
+            ContentResolver resolver = context.getContentResolver();
+            InputStream inputStream = resolver.openInputStream(uri);
+            ParcelFileDescriptor fileDescriptor = resolver.openFileDescriptor(uri, "r");
+            int detachFd = fileDescriptor.detachFd();
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            fileDescriptor.close();
+            return detachFd;
+        } catch (Exception e) {
+            return 0;
+        }
+    }
 }

+ 33 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/BaseActivityResultLauncher.java

@@ -0,0 +1,33 @@
+package com.compdfkit.tools.common.utils.activitycontracts;
+
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.ActivityResultCaller;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContract;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public class BaseActivityResultLauncher<I, O> {
+
+    private final ActivityResultLauncher<I> launcher;
+    private ActivityResultCallback<O> callback;
+
+    public BaseActivityResultLauncher(@NonNull ActivityResultCaller caller,
+                                      @NonNull ActivityResultContract<I, O> contract) {
+        launcher = caller.registerForActivityResult(contract, result -> {
+            if (callback != null) {
+                callback.onActivityResult(result);
+                callback = null;
+            }
+        });
+    }
+
+    public void launch(@Nullable I input, @NonNull ActivityResultCallback<O> callback) {
+        this.callback = callback;
+        launcher.launch(input);
+    }
+
+    public void launch(@Nullable I input) {
+        launcher.launch(input);
+    }
+}

+ 0 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CImageResultContracts.java

@@ -26,7 +26,6 @@ import com.compdfkit.tools.common.utils.date.CDateUtil;
 
 import java.io.File;
 
-
 public class CImageResultContracts extends ActivityResultContract<CImageResultContracts.RequestType, Uri> {
 
     public enum RequestType {

+ 14 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CMultiplePermissionResultLauncher.java

@@ -0,0 +1,14 @@
+package com.compdfkit.tools.common.utils.activitycontracts;
+
+import androidx.activity.result.ActivityResultCaller;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+
+import java.util.Map;
+
+public class CMultiplePermissionResultLauncher extends BaseActivityResultLauncher<String[], Map<String, Boolean>> {
+
+    public CMultiplePermissionResultLauncher(@NonNull ActivityResultCaller caller) {
+        super(caller, new ActivityResultContracts.RequestMultiplePermissions());
+    }
+}

+ 18 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CPermissionResultLauncher.java

@@ -0,0 +1,18 @@
+package com.compdfkit.tools.common.utils.activitycontracts;
+
+import androidx.activity.result.ActivityResultCaller;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+
+/**
+ * @classname:
+ * @author: LiuXiaoLong
+ * @date: 2023/8/30
+ * description:
+ */
+public class CPermissionResultLauncher extends BaseActivityResultLauncher<String, Boolean>{
+    public CPermissionResultLauncher(@NonNull ActivityResultCaller caller) {
+        super(caller, new ActivityResultContracts.RequestPermission());
+    }
+}
+

+ 25 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/activitycontracts/CSelectPDFDocumentResultContract.java

@@ -0,0 +1,25 @@
+package com.compdfkit.tools.common.utils.activitycontracts;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import androidx.activity.result.contract.ActivityResultContract;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.compdfkit.tools.common.utils.CFileUtils;
+
+
+public class CSelectPDFDocumentResultContract extends ActivityResultContract<Void, Uri> {
+    @NonNull
+    @Override
+    public Intent createIntent(@NonNull Context context, Void unused) {
+        return CFileUtils.getContentIntent();
+    }
+
+    @Override
+    public Uri parseResult(int i, @Nullable Intent intent) {
+        return intent != null ? intent.getData() : null;
+    }
+}

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/animation/CFillScreenManager.java

@@ -23,7 +23,7 @@ public class CFillScreenManager {
 
     public static final long CONFIG_SHORT_ANIM_TIME = 200L;
 
-    private LinkedHashSet<View> topToolViewList = new LinkedHashSet<>();
+    public LinkedHashSet<View> topToolViewList = new LinkedHashSet<>();
 
     public LinkedHashSet<View> bottomToolViewList = new LinkedHashSet<>();
 

+ 9 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/animation/ConstraintSetUtils.java

@@ -66,7 +66,15 @@ public class ConstraintSetUtils {
         constraintSet.connect(view.getId(), ConstraintSet.TOP, view.getId(), ConstraintSet.PARENT_ID, ConstraintSet.TOP);
         constraintSet.connect(view.getId(), ConstraintSet.BOTTOM, view.getId(), ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM);
     }
-    
+
+    public void show(ConstraintSet constraintSet, View view){
+        constraintSet.setVisibility(view.getId(), ConstraintSet.VISIBLE);
+    }
+
+    public void hide(ConstraintSet constraintSet, View view){
+        constraintSet.setVisibility(view.getId(), ConstraintSet.GONE);
+    }
+
     public void apply(ConstraintSet constraintSet, ConstraintLayout rootView){
         AutoTransition autoTransition = new AutoTransition();
         autoTransition.setDuration(200);

+ 17 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/date/CDateUtil.java

@@ -3,12 +3,15 @@ package com.compdfkit.tools.common.utils.date;
 
 import android.text.TextUtils;
 
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.TimeZone;
 
 public class CDateUtil {
 
     public static final String NORMAL_DATE_FORMAT = "yyyy_MM_dd_HH_mm_ss";
+    public static final String NORMAL_DATE_FORMAT_1 = "yyyy.MM.dd HH:mm:ss";
 
     /**
      * Transform a PDF date string in the format D:20230130060237+00'00' to a human-readable yyyy-MM-dd HH:mm:ss date string.
@@ -38,4 +41,18 @@ public class CDateUtil {
         return df.format(new Date());
     }
 
+    public static String formatPDFUTCDate(String pdfUTCDate){
+        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+        inputFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        try {
+            Date date = inputFormat.parse(pdfUTCDate);
+            String formattedOutput = outputFormat.format(date);
+            return formattedOutput;
+        } catch (ParseException e) {
+            e.printStackTrace();
+            return pdfUTCDate;
+        }
+    }
+
 }

+ 0 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/image/CBitmapUtil.java

@@ -19,7 +19,6 @@ import com.compdfkit.tools.common.utils.CUriUtil;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 
 public class CBitmapUtil {

+ 130 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/view/CEditText.java

@@ -0,0 +1,130 @@
+/**
+ * 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.tools.common.utils.view;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.AttributeSet;
+import android.view.inputmethod.EditorInfo;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.interfaces.COnTextChangedListener;
+
+
+public class CEditText extends FrameLayout {
+
+    AppCompatEditText editText;
+
+    AppCompatTextView tvTitle;
+
+    private COnTextChangedListener textChangedListener;
+
+    public CEditText(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+        initAttr(context, attrs);
+
+    }
+
+    private void initAttr(Context context, AttributeSet attrs) {
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CEditText);
+        if (typedArray != null) {
+            String title = typedArray.getString(R.styleable.CEditText_android_title);
+            String hint = typedArray.getString(R.styleable.CEditText_android_hint);
+            int imeOptions = typedArray.getInt(R.styleable.CEditText_android_imeOptions, EditorInfo.IME_ACTION_DONE);
+            int inputType = typedArray.getInt(R.styleable.CEditText_android_inputType, EditorInfo.TYPE_CLASS_TEXT);
+            tvTitle.setVisibility(TextUtils.isEmpty(title)?  GONE : VISIBLE);
+            tvTitle.setText(title);
+            editText.setImeOptions(imeOptions);
+            editText.setInputType(inputType);
+            editText.setHint(hint);
+            typedArray.recycle();
+        }
+    }
+
+    private void initView(Context context){
+        inflate(context, R.layout.tools_layout_c_edit_text, this);
+        editText = findViewById(R.id.edit_text);
+        tvTitle = findViewById(R.id.tv_title);
+        editText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                if (textChangedListener != null) {
+                    textChangedListener.onTextChanged(s, start, before, count);
+                }
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+
+            }
+        });
+    }
+
+    public AppCompatEditText getEditText() {
+        return editText;
+    }
+
+    public AppCompatTextView getTitle() {
+        return tvTitle;
+    }
+
+    public void setTitle(String title) {
+        this.tvTitle.setText(title);
+    }
+
+    public void setOnEditorActionListener(TextView.OnEditorActionListener listener){
+        editText.setOnEditorActionListener(listener);
+    }
+
+    public void addTextChangedListener(COnTextChangedListener textChangedListener){
+       this.textChangedListener = textChangedListener;
+    }
+
+    public String getText() {
+        if (TextUtils.isEmpty(editText.getText())){
+            return "";
+        }else {
+            return editText.getText().toString();
+        }
+    }
+
+    public void setText(String text){
+        editText.setText(text);
+    }
+
+
+    public void setError(boolean error){
+        editText.setBackgroundResource(error ? R.drawable.tools_bg_import_certificate_digital_id_error_item : R.drawable.tools_bg_import_certificate_digital_id_item);
+    }
+}

+ 5 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/viewutils/CDimensUtils.java

@@ -24,6 +24,11 @@ public class CDimensUtils {
         return (int) (dp * scale + 0.5f);
     }
 
+    public static int spToPx(float sp, Context context) {
+        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+        return (int) (sp * fontScale + 0.5f);
+    }
+
     public static DisplayMetrics getDisplayMetrics(Context context){
         return context.getResources().getDisplayMetrics();
     }

+ 13 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/window/CModeSwitchDialogFragment.java

@@ -42,6 +42,8 @@ public class CModeSwitchDialogFragment extends BottomSheetDialogFragment
 
     private RadioButton rbPageEdit;
 
+    private RadioButton rbSignature;
+
     private LinkedHashSet<CPreviewMode> previewModes = new LinkedHashSet<>();
 
     private CPreviewMode selectMode;
@@ -90,6 +92,7 @@ public class CModeSwitchDialogFragment extends BottomSheetDialogFragment
         rbPDFEdit = rootView.findViewById(R.id.r_btn_pdf_edit_mode);
         rbForm = rootView.findViewById(R.id.r_btn_form_mode);
         rbPageEdit = rootView.findViewById(R.id.r_btn_page_edit_mode);
+        rbSignature = rootView.findViewById(R.id.r_btn_signature_mode);
         return rootView;
     }
 
@@ -128,15 +131,18 @@ public class CModeSwitchDialogFragment extends BottomSheetDialogFragment
             case PageEdit:
                 rbPageEdit.setChecked(true);
                 break;
+            case Signature:
+                rbSignature.setChecked(true);
+                break;
             default:break;
         }
         modifyPopupMenuStatus();
-//        radioGroup.setOnCheckedChangeListener(this);
         rbViewer.setOnClickListener(this);
         rbAnnotation.setOnClickListener(this);
         rbPDFEdit.setOnClickListener(this);
         rbForm.setOnClickListener(this);
         rbPageEdit.setOnClickListener(this);
+        rbSignature.setOnClickListener(this);
     }
 
     @Override
@@ -156,6 +162,9 @@ public class CModeSwitchDialogFragment extends BottomSheetDialogFragment
         } else if (v.getId() == R.id.r_btn_form_mode) {
             rbForm.setChecked(true);
             changeMode(CPreviewMode.Form);
+        } else if (v.getId() == R.id.r_btn_signature_mode){
+            rbSignature.setChecked(true);
+            changeMode(CPreviewMode.Signature);
         }
         dismiss();
     }
@@ -177,6 +186,9 @@ public class CModeSwitchDialogFragment extends BottomSheetDialogFragment
         if (rbPageEdit != null) {
             rbPageEdit.setVisibility(previewModes.contains(CPreviewMode.PageEdit) ? View.VISIBLE : View.GONE);
         }
+        if (rbSignature != null) {
+            rbSignature.setVisibility(previewModes.contains(CPreviewMode.Signature) ? View.VISIBLE : View.GONE);
+        }
     }
 
 

+ 8 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/CToolBar.java

@@ -15,6 +15,7 @@ import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.widget.FrameLayout;
 
@@ -26,6 +27,7 @@ import androidx.appcompat.widget.AppCompatImageView;
 import androidx.appcompat.widget.AppCompatTextView;
 
 import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
 import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
 
 /**
@@ -83,6 +85,8 @@ public class CToolBar extends FrameLayout {
         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CToolBar);
         if (typedArray != null) {
             String toolBarTitle = typedArray.getString(R.styleable.CToolBar_android_title);
+            float textSize = typedArray.getDimensionPixelSize(R.styleable.CToolBar_android_textSize, CDimensUtils.spToPx(22, getContext()));
+            tvToolBarTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
             if (!TextUtils.isEmpty(toolBarTitle)) {
                 tvToolBarTitle.setText(toolBarTitle);
             }
@@ -115,4 +119,8 @@ public class CToolBar extends FrameLayout {
     public void setBackImageIconResource(@DrawableRes int iconResId) {
         ivToolBarBackBtn.setImageResource(iconResId);
     }
+
+    public AppCompatImageView getIvToolBarBackBtn() {
+        return ivToolBarBackBtn;
+    }
 }

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/font/CExternFontSpinnerAdapter.java

@@ -68,7 +68,7 @@ public class CExternFontSpinnerAdapter extends BaseAdapter {
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
         LayoutInflater inflater = LayoutInflater.from(mContext);
-        convertView = inflater.inflate(R.layout.tools_font_list_item, null);
+        convertView = inflater.inflate(R.layout.tools_spinner_list_item, null);
         if (convertView != null){
             AppCompatTextView textView = convertView.findViewById(R.id.tv_menu_title);
             if (position < list.size()) {

+ 1 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/font/CFontSpinnerAdapter.java

@@ -54,7 +54,7 @@ public class CFontSpinnerAdapter extends BaseAdapter {
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
         LayoutInflater inflater = LayoutInflater.from(mContext);
-        convertView = inflater.inflate(R.layout.tools_font_list_item, null);
+        convertView = inflater.inflate(R.layout.tools_spinner_list_item, null);
         if (convertView != null){
             AppCompatTextView textView = convertView.findViewById(R.id.tv_menu_title);
             CPDFTextAttribute.FontNameHelper.FontType fontType = (CPDFTextAttribute.FontNameHelper.FontType) getItem(position);

+ 0 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/pdfstyle/CAnnotStyle.java

@@ -30,7 +30,6 @@ import com.compdfkit.tools.common.utils.CLog;
 
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 public class CAnnotStyle implements Serializable {

+ 0 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfproperties/stamp/CPDFStampTextView.java

@@ -12,7 +12,6 @@ import android.graphics.Shader;
 import android.text.Layout;
 import android.text.TextPaint;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 
 import androidx.annotation.Nullable;

+ 0 - 4
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPDFViewCtrl.java

@@ -11,15 +11,11 @@ package com.compdfkit.tools.common.views.pdfview;
 
 import android.animation.ObjectAnimator;
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.TypedArray;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
-import android.provider.Settings;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;

+ 5 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPreviewMode.java

@@ -7,7 +7,9 @@ public enum CPreviewMode {
     Annotation,
     Edit,
     Form,
-    PageEdit;
+    PageEdit,
+
+    Signature;
 
     public int getTitleByMode() {
         switch (this) {
@@ -19,6 +21,8 @@ public enum CPreviewMode {
                 return R.string.tools_page_edit_mode;
             case Form:
                 return R.string.tools_form_mode;
+            case Signature:
+                return R.string.tools_digital_signature;
             default:
                 return R.string.tools_pdf_viewer_mode;
         }

+ 0 - 4
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/contenteditor/pdfproperties/CEditImagePropertiesFragment.java

@@ -22,9 +22,7 @@ import androidx.appcompat.widget.AppCompatImageView;
 import androidx.constraintlayout.widget.ConstraintLayout;
 
 import com.compdfkit.tools.R;
-import com.compdfkit.tools.common.utils.CFileUtils;
 import com.compdfkit.tools.common.utils.activitycontracts.CImageResultContracts;
-import com.compdfkit.tools.common.utils.date.CDateUtil;
 import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
 import com.compdfkit.tools.common.utils.view.sliderbar.CSliderBar;
 import com.compdfkit.tools.common.views.pdfproperties.basic.CBasicPropertiesFragment;
@@ -32,8 +30,6 @@ import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CAnnotStyle;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleType;
 import com.compdfkit.tools.common.views.pdfproperties.preview.CStylePreviewView;
 
-import java.io.File;
-
 
 public class CEditImagePropertiesFragment extends CBasicPropertiesFragment implements View.OnClickListener {
     private CStylePreviewView stylePreviewView;

+ 0 - 3
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/forms/pdfformbar/CFormToolbar.java

@@ -14,7 +14,6 @@ import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
@@ -26,8 +25,6 @@ import androidx.recyclerview.widget.RecyclerView;
 
 import com.compdfkit.core.annotation.form.CPDFWidget;
 import com.compdfkit.core.undo.CPDFUndoManager;
-import com.compdfkit.core.undo.exception.CPDFRedoFailedException;
-import com.compdfkit.core.undo.exception.CPDFUndoFailedException;
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.common.interfaces.COnFormChangeListener;
 import com.compdfkit.tools.common.utils.CLog;

+ 0 - 4
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/forms/pdfproperties/pdfsign/CustomSignatureWidgetImpl.java

@@ -10,7 +10,6 @@
 package com.compdfkit.tools.forms.pdfproperties.pdfsign;
 
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.text.TextUtils;
 
 import androidx.fragment.app.FragmentActivity;
@@ -25,9 +24,6 @@ import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleUIParams;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.manager.CStyleManager;
 import com.compdfkit.ui.proxy.form.CPDFSignatureWidgetImpl;
 
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-
 
 public class CustomSignatureWidgetImpl extends CPDFSignatureWidgetImpl {
 

+ 78 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/CSignatureToolBar.java

@@ -0,0 +1,78 @@
+/**
+ * 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.tools.signature;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.compdfkit.core.annotation.form.CPDFWidget;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.ui.reader.CPDFReaderView;
+
+public class CSignatureToolBar extends FrameLayout {
+
+    ConstraintLayout clAddSignatures;
+
+    ConstraintLayout clVerifySign;
+
+    private CPDFViewCtrl pdfView;
+
+    public void initWithPDFView(CPDFViewCtrl pdfView) {
+        this.pdfView = pdfView;
+    }
+
+    public CSignatureToolBar(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CSignatureToolBar(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CSignatureToolBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        inflate(context, R.layout.tools_signature_tool_bar, this);
+        clAddSignatures = findViewById(R.id.cl_add_digital_signature);
+        clVerifySign = findViewById(R.id.cl_verify_digital_signature);
+        clAddSignatures.setOnClickListener(v -> {
+            if (pdfView != null) {
+                clAddSignatures.setSelected(!clAddSignatures.isSelected());
+                if (clAddSignatures.isSelected()){
+                    pdfView.setViewMode(CPDFReaderView.ViewMode.FORM);
+                    pdfView.changeFormType(CPDFWidget.WidgetType.Widget_SignatureFields);
+                }else {
+                    pdfView.setViewMode(CPDFReaderView.ViewMode.VIEW);
+                    pdfView.changeFormType(CPDFWidget.WidgetType.Widget_Unknown);
+                }
+            }
+        });
+    }
+
+    public View getVerifySignButton() {
+        return clVerifySign;
+    }
+
+    public void reset(){
+        clAddSignatures.setSelected(false);
+    }
+
+}

+ 298 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/CertificateDigitalDatas.java

@@ -0,0 +1,298 @@
+/**
+ * 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.tools.signature;
+
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.annotation.Nullable;
+
+import com.compdfkit.core.annotation.form.CPDFSignatureWidget;
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFOwnerInfo;
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.core.document.signature.CPDFSigner;
+import com.compdfkit.core.document.signature.CPDFX509;
+import com.compdfkit.core.utils.TFileUtils;
+import com.compdfkit.tools.common.utils.CLog;
+import com.compdfkit.tools.common.utils.CUriUtil;
+import com.compdfkit.tools.signature.pdfproperties.pdfsign.CDigitalSignStyleData;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CertificateDigitalDatas {
+
+    /**
+     * Generate a digital signature certificate based on relevant information
+     *
+     * @param ownerInfo Certificate information
+     * @param password
+     * @param saveDir   Local storage save path
+     * @param fileName  Certificate file name
+     * @return Whether a certificate was generated
+     */
+    public static boolean generatePKCS12Cert(CPDFOwnerInfo ownerInfo, String password, String saveDir, String fileName) {
+        CPDFSignature.CertUsage flag = CPDFSignature.CertUsage.PDFDigSig;
+        String pfxPath = new File(saveDir, fileName).getAbsolutePath();
+        return CPDFSignature.generatePKCS12Cert(ownerInfo, password, pfxPath, flag, true);
+    }
+
+    /**
+     * Get certificate information
+     *
+     * @param certFilePath Certificate local file path
+     * @param password
+     * @return
+     */
+    @Nullable
+    public static CPDFCertInfo getCertInfo(String certFilePath, String password) {
+        if (CPDFSignature.checkPKCS12Password(certFilePath, password)) {
+            CPDFX509 x509 = CPDFSignature.getX509ByPKCS12Cert(certFilePath, password);
+            return x509.getCertInfo();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get a collection of digital signatures in a pdf document
+     *
+     * @param document
+     * @return
+     */
+    @NotNull
+    public static List<CPDFSignature> getDigitalSignList(CPDFDocument document) {
+        List<CPDFSignature> list = new ArrayList<>();
+        for (int i = 0; i < document.getSignatureCount(); i++) {
+            CPDFSignature signature = document.getPdfSignature(i);
+            if (signature == null) {
+                continue;
+            }
+            CPDFSigner[] signers = signature.getSignerArr();
+            if (signers != null && signers.length > 0) {
+                list.add(signature);
+            }
+        }
+        return list;
+    }
+
+    public static boolean hasDigitalSignature(CPDFDocument document){
+        return getDigitalSignList(document).size() > 0;
+    }
+
+    /**
+     * Write digital signature into pdf document
+     *
+     * @param document
+     * @param signatureWidget
+     * @param styleData       Signature related information, such as: reason for signing, location, time, etc.
+     * @param certPath        Signed certificate local file path
+     * @param password        certificate password
+     * @param savePath        Document save path
+     * @return
+     */
+    public static boolean writeSignature(CPDFDocument document,
+                                         CPDFSignatureWidget signatureWidget,
+                                         CDigitalSignStyleData styleData,
+                                         String certPath,
+                                         String password,
+                                         String savePath
+    ) {
+        if (!TextUtils.isEmpty(document.getAbsolutePath())) {
+            return document.writeSignatureToPath(signatureWidget,
+                    document.getAbsolutePath(),
+                    savePath,
+                    certPath,
+                    password,
+                    styleData.getPosition(),
+                    styleData.getReason(),
+                    CPDFDocument.PDFDocMdpP.PDFDocMdpPForbidAllModify
+            );
+        } else if (document.getUri() != null) {
+            return document.writeSignatureToPath(signatureWidget,
+                    CUriUtil.getUriFd(document.getContext(), document.getUri()),
+                    savePath,
+                    certPath,
+                    password,
+                    styleData.getPosition(),
+                    styleData.getReason(),
+                    CPDFDocument.PDFDocMdpP.PDFDocMdpPForbidAllModify
+            );
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Verify that the specified digital signature is valid
+     *
+     * @param signature
+     * @param document
+     * @return
+     */
+    public static boolean verifySignIsValid(CPDFDocument document,CPDFSignature signature ) {
+        CPDFSigner[] signers = signature.getSignerArr();
+        if (!TextUtils.isEmpty(document.getAbsolutePath())) {
+            return signature.veryfyByPath(signers[0], document.getAbsolutePath());
+        } else {
+            return signature.verifyByFd(signers[0], CUriUtil.getUriFd(document.getContext(), document.getUri()));
+        }
+    }
+
+    /**
+     * Verify whether the document has been modified after the digital signature
+     *
+     * @param document
+     * @param signature
+     * @return
+     */
+    public static boolean verifyDocumentHasChanged(CPDFDocument document, CPDFSignature signature) {
+        return signature.verifyDocument(document);
+    }
+
+    /**
+     * Digital Signature Timestamp Authentication
+     *
+     * @param context
+     * @param signature
+     * @param signer
+     * @return
+     */
+    public static boolean verifyTimeStamp(Context context, CPDFSignature signature, CPDFSigner signer) {
+        return signature.veryfyTimestamp(context, signer);
+    }
+
+    /**
+     * Whether the certificate is trusted
+     *
+     * @param context
+     * @param cert
+     * @param signature
+     * @return
+     */
+    public static boolean verifyGetChain(Context context, CPDFX509 cert, CPDFSignature signature) {
+        return cert.verifyGetChain(context, signature);
+    }
+
+
+    public static SignatureStatus verifyDocumentSignStatus(CPDFDocument document) {
+        List<CPDFSignature> signatures = getDigitalSignList(document);
+        if (signatures != null && signatures.size() > 0) {
+            boolean hasInValid = false;
+            for (CPDFSignature signature : signatures) {
+                boolean result = verifySignIsValid(document, signature);
+                if (!result) {
+                    // Invalid digital signature
+                    hasInValid = true;
+                }
+            }
+            // Invalid signature in digital signature collection
+            if (hasInValid) {
+                return SignatureStatus.FAILURES;
+            }
+            // All the signatures in the digital signature set are valid,
+            // and it is judged whether there is an expired certificate
+            boolean hasIsExpiredSignature = false;
+            for (CPDFSignature signature : signatures) {
+                CPDFSigner[] signers = signature.getSignerArr();
+                CPDFSigner signers1 = signers[0];
+                if (signers1.getCert().isExpired()) {
+                    hasIsExpiredSignature = true;
+                }
+            }
+            return hasIsExpiredSignature ? SignatureStatus.WRONG : SignatureStatus.VALID;
+        } else {
+            return SignatureStatus.FAILURES;
+        }
+    }
+
+    public static SignatureStatus verifySignatureStatus(CPDFDocument document, CPDFSignature signature){
+        boolean isValid = verifySignIsValid( document, signature);
+        if (isValid) {
+            boolean isExpired = false;
+            CPDFSigner[] signers = signature.getSignerArr();
+            CPDFSigner signers1 = signers[0];
+            if (signers1.getCert().isExpired()) {
+                isExpired = true;
+            }
+            return isExpired ? SignatureStatus.WRONG : SignatureStatus.VALID;
+        }else {
+            return SignatureStatus.FAILURES;
+        }
+    }
+
+    public static boolean removeDigitalSign(CPDFDocument document, CPDFSignature signature) {
+        try {
+            boolean result = signature.removeSignature(document, true);
+            document.save();
+            return result;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public static List<CPDFX509> getCertDetails(Context context, CPDFSignature signature){
+        CPDFSigner[] signers = signature.getSignerArr();
+        List<CPDFX509> list = new ArrayList<>();
+        if (signers != null && signers.length > 0){
+            CPDFSigner signer = signers[0];
+            CPDFX509 cert = signer.getCert();
+            list.add(cert);
+            loopVerifyGetChain(context,list, signature, cert);
+        }
+        Collections.reverse(list);
+        return list;
+    }
+
+    private static void loopVerifyGetChain(Context context,List<CPDFX509> list, CPDFSignature signature, CPDFX509 cert){
+        cert.verifyGetChain(context, signature);
+        CPDFX509[] cpdfx509s = cert.getChanin();
+        if (cpdfx509s != null && cpdfx509s.length > 0) {
+            CPDFX509 a = cpdfx509s[0];
+            list.add(a);
+            loopVerifyGetChain(context, list, signature, a);
+        }
+    }
+
+
+    public static String getOwnerContent(CPDFOwnerInfo ownerInfo){
+        StringBuilder builder = new StringBuilder();
+        List<String> infos = new ArrayList<>();
+        if (!TextUtils.isEmpty(ownerInfo.getCountry())){
+            infos.add("C="+ownerInfo.getCountry());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getOrgnize())){
+            infos.add("O="+ownerInfo.getOrgnize());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getOrgnizeUnit())){
+            infos.add("OU="+ownerInfo.getOrgnizeUnit());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getCommonName())){
+            infos.add("CN="+ownerInfo.getCommonName());
+        }
+        for (int i = 0; i < infos.size(); i++) {
+            String item = infos.get(i);
+            builder.append(item);
+            if (i != infos.size() -1){
+                builder.append(",");
+            }
+        }
+        return builder.toString();
+    }
+
+}

+ 20 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/SignatureStatus.java

@@ -0,0 +1,20 @@
+/**
+ * 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.tools.signature;
+
+
+public enum SignatureStatus {
+
+    VALID,
+
+    FAILURES,
+
+    WRONG
+}

+ 64 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/bean/CPDFCertAttrDataItem.java

@@ -0,0 +1,64 @@
+/**
+ * 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.tools.signature.bean;
+
+
+public class CPDFCertAttrDataItem {
+
+    public CPDFCertAttrDataItem(String headTitle){
+        this.headTitle = headTitle;
+        this.isHead = true;
+    }
+
+    public CPDFCertAttrDataItem(String title, String value){
+        this.title = title;
+        this.value = value;
+    }
+
+    private boolean isHead;
+
+    private String headTitle;
+
+    private String title;
+
+    private String value;
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public boolean isHead() {
+        return isHead;
+    }
+
+    public void setHead(boolean head) {
+        isHead = head;
+    }
+
+    public String getHeadTitle() {
+        return headTitle;
+    }
+
+    public void setHeadTitle(String headTitle) {
+        this.headTitle = headTitle;
+    }
+}

+ 93 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/bean/CPDFOwnerItemData.java

@@ -0,0 +1,93 @@
+/**
+ * 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.tools.signature.bean;
+
+
+import android.text.TextUtils;
+
+import com.compdfkit.core.document.signature.CPDFOwnerInfo;
+import com.compdfkit.core.document.signature.CPDFX509;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CPDFOwnerItemData {
+
+    public CPDFOwnerItemData() {
+
+    }
+
+    public CPDFOwnerItemData(CPDFX509 cpdfx509){
+        this.cpdfx509 = cpdfx509;
+        StringBuilder builder = new StringBuilder();
+        CPDFOwnerInfo ownerInfo = cpdfx509.getCertInfo().getSubject();
+        List<String> infos = new ArrayList<>();
+        if (!TextUtils.isEmpty(ownerInfo.getCountry())){
+            infos.add("C="+ownerInfo.getCountry());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getOrgnize())){
+            infos.add("O="+ownerInfo.getOrgnize());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getOrgnizeUnit())){
+            infos.add("OU="+ownerInfo.getOrgnizeUnit());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getCommonName())){
+            infos.add("CN="+ownerInfo.getCommonName());
+        }
+        for (int i = 0; i < infos.size(); i++) {
+            String item = infos.get(i);
+            builder.append(item);
+            if (i != infos.size() -1){
+                builder.append(",");
+            }
+        }
+        this.content = builder.toString();
+    }
+
+    private CPDFX509 cpdfx509;
+
+    private String content;
+
+    private boolean isExpanded = true;
+
+    private boolean hasParent;
+
+    public CPDFX509 getCpdfx509() {
+        return cpdfx509;
+    }
+
+    public void setCpdfx509(CPDFX509 cpdfx509) {
+        this.cpdfx509 = cpdfx509;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public void setExpanded(boolean expanded) {
+        isExpanded = expanded;
+    }
+
+    public boolean isExpanded() {
+        return isExpanded;
+    }
+
+    public void setHasParent(boolean hasParent) {
+        this.hasParent = hasParent;
+    }
+
+    public boolean isHasParent() {
+        return hasParent;
+    }
+}

+ 35 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/bean/CPDFSignatureItemData.java

@@ -0,0 +1,35 @@
+package com.compdfkit.tools.signature.bean;
+
+
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.tools.signature.SignatureStatus;
+
+public class CPDFSignatureItemData {
+
+    public CPDFSignatureItemData(){}
+
+    public CPDFSignatureItemData(CPDFSignature signature, SignatureStatus signatureStatus){
+        this.signature = signature;
+        this.signatureStatus = signatureStatus;
+    }
+
+    private CPDFSignature signature;
+
+    private SignatureStatus signatureStatus;
+
+    public CPDFSignature getSignature() {
+        return signature;
+    }
+
+    public void setSignature(CPDFSignature signature) {
+        this.signature = signature;
+    }
+
+    public SignatureStatus getSignatureStatus() {
+        return signatureStatus;
+    }
+
+    public void setSignatureStatus(SignatureStatus signatureStatus) {
+        this.signatureStatus = signatureStatus;
+    }
+}

+ 209 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CImportCertificateDigitalDialog.java

@@ -0,0 +1,209 @@
+/**
+ * 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.tools.signature.importcert.create;
+
+
+import static com.compdfkit.tools.common.utils.CFileUtils.CERTIFICATE_DIGITAL_TYPE;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatEditText;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.CFileUtils;
+import com.compdfkit.tools.common.utils.CUriUtil;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.signature.interfaces.COnSelectCertFileListener;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+import java.io.File;
+
+public class CImportCertificateDigitalDialog extends CBasicBottomSheetDialogFragment implements View.OnClickListener {
+
+    public static final String EXTRA_CERTIFICATE_DIGITAL_URI = "extra_certificate_digital_uri";
+
+    private AppCompatTextView tvTitle;
+
+    private AppCompatImageView ivClose;
+
+    private ConstraintLayout clCertificate;
+
+    private AppCompatEditText etPassword;
+
+    private AppCompatImageView ivClearPassword;
+
+    private AppCompatButton btnOk;
+
+    private AppCompatTextView tvCertificateDigitalName;
+
+    private AppCompatTextView tvPasswordError;
+
+    private Uri certificateUri = null;
+
+    private COnSelectCertFileListener selectCertFileListener;
+
+    private ActivityResultLauncher<Intent> selectCertificateLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
+        if (result.getData() != null && result.getData().getData() != null) {
+            Uri certificateUri = result.getData().getData();
+            CFileUtils.takeUriPermission(getContext(), certificateUri);
+            setCertificateInfo(certificateUri);
+            if (getArguments() != null) {
+                getArguments().putParcelable(EXTRA_CERTIFICATE_DIGITAL_URI, certificateUri);
+            }
+        }
+    });
+
+
+    public static CImportCertificateDigitalDialog newInstance(Uri certificateUri) {
+        Bundle args = new Bundle();
+        args.putParcelable(EXTRA_CERTIFICATE_DIGITAL_URI, certificateUri);
+        CImportCertificateDigitalDialog fragment = new CImportCertificateDigitalDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_import_certificate_digital_id_fragment;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        tvTitle = view.findViewById(R.id.tv_tool_bar_title);
+        ivClose = view.findViewById(R.id.iv_tool_bar_close);
+        clCertificate = view.findViewById(R.id.cl_certificate);
+        tvCertificateDigitalName = view.findViewById(R.id.tv_certificate);
+        etPassword = view.findViewById(R.id.et_password);
+        ivClearPassword = view.findViewById(R.id.iv_remove_password);
+        tvPasswordError = view.findViewById(R.id.tv_password_error);
+        btnOk = view.findViewById(R.id.btn_ok);
+        ivClose.setOnClickListener(this);
+        ivClearPassword.setOnClickListener(this);
+        btnOk.setOnClickListener(this);
+        clCertificate.setOnClickListener(this);
+        etPassword.setOnEditorActionListener((v, actionId, event) -> {
+            if (actionId == EditorInfo.IME_ACTION_DONE) {
+                verifyCertificate();
+                return true;
+            }
+            return false;
+        });
+    }
+
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected int getStyle() {
+        return R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle_TopCorners;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected void onViewCreate() {
+        Uri uri = getArguments().getParcelable(EXTRA_CERTIFICATE_DIGITAL_URI);
+        if (uri != null) {
+            setCertificateInfo(uri);
+        }
+        tvTitle.setText(R.string.tools_add_a_signature_field);
+        etPassword.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                ivClearPassword.setVisibility(TextUtils.isEmpty(s) ? View.GONE : View.VISIBLE);
+                if (TextUtils.isEmpty(s) && tvPasswordError.getVisibility() == View.VISIBLE) {
+                    tvPasswordError.setVisibility(View.GONE);
+                }
+                btnOk.setEnabled(!TextUtils.isEmpty(s));
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+
+            }
+        });
+    }
+
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.iv_tool_bar_close) {
+            dismiss();
+        } else if (v.getId() == R.id.iv_remove_password) {
+            etPassword.setText("");
+        } else if (v.getId() == R.id.btn_ok) {
+            verifyCertificate();
+        } else if (v.getId() == R.id.cl_certificate) {
+            selectCertificateLauncher.launch(CFileUtils.getIntent(CERTIFICATE_DIGITAL_TYPE));
+        }
+    }
+
+    private void setCertificateInfo(Uri uri) {
+        certificateUri = uri;
+        String idName = CUriUtil.getUriFileName(getContext(), uri);
+        tvCertificateDigitalName.setText(idName);
+        etPassword.setText("");
+        etPassword.requestFocus();
+        CViewUtils.showKeyboard(etPassword);
+    }
+
+    private void verifyCertificate() {
+        if (TextUtils.isEmpty(etPassword.getText())) {
+            tvPasswordError.setVisibility(View.VISIBLE);
+            return;
+        }
+        String password = etPassword.getText().toString();
+        String dir = new File(getContext().getCacheDir(), CFileUtils.CACHE_FOLDER + File.separator + "certFile").getAbsolutePath();
+        String certPath = CFileUtils.copyFileToInternalDirectory(getContext(), certificateUri, dir, CUriUtil.getUriFileName(getContext(), certificateUri));
+        if (!CPDFSignature.checkPKCS12Password(certPath, password)) {
+            tvPasswordError.setVisibility(View.VISIBLE);
+            return;
+        }
+        if (selectCertFileListener != null && certificateUri != null) {
+            selectCertFileListener.certificateFile(certPath, password);
+        }
+    }
+
+    public void setSelectCertFileListener(COnSelectCertFileListener selectCertFileListener) {
+        this.selectCertFileListener = selectCertFileListener;
+    }
+}

+ 159 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CPDFSelectDigitalSignatureDialog.java

@@ -0,0 +1,159 @@
+/**
+ * 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.tools.signature.importcert.create;
+
+
+import static com.compdfkit.tools.common.utils.CFileUtils.CERTIFICATE_DIGITAL_TYPE;
+
+import android.Manifest;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.RadioGroup;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.annotation.pdfproperties.pdfsignature.CAddSignatureActivity;
+import com.compdfkit.tools.common.utils.CFileUtils;
+import com.compdfkit.tools.common.utils.CPermissionUtil;
+import com.compdfkit.tools.signature.interfaces.COnSelectCertFileListener;
+
+public class CPDFSelectDigitalSignatureDialog extends DialogFragment implements View.OnClickListener {
+
+    private RadioGroup rgType;
+
+    private String certFilePath;
+
+    private String certPassword;
+
+    private COnCertDigitalSignListener certDigitalSignListener;
+
+    private ActivityResultLauncher<String> requestStorageLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
+
+    });
+
+    private ActivityResultLauncher<Intent> addSignatureLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
+        Fragment fragment = getChildFragmentManager().findFragmentByTag("certDialog");
+        if (fragment != null) {
+            ((DialogFragment) fragment).dismiss();
+        }
+        if (result.getData() != null) {
+            String signImagePath;
+            if (result.getData().getStringExtra("file_path") != null){
+                signImagePath = result.getData().getStringExtra("file_path");
+                if (certDigitalSignListener != null) {
+                    certDigitalSignListener.sign(certFilePath,certPassword, signImagePath);
+                }
+            }else if (result.getData().getBooleanExtra(CAddSignatureActivity.RESULT_NONE, false)){
+                //none
+                signImagePath = "";
+                if (certDigitalSignListener != null) {
+                    certDigitalSignListener.sign(certFilePath,certPassword, signImagePath);
+                }
+            }
+        }
+    });
+
+    private COnSelectCertFileListener selectCertFileListener = (filePath, password) -> {
+        certFilePath = filePath;
+        certPassword = password;
+        openSignActivity();
+    };
+
+    private void openSignActivity(){
+        Intent intent = new Intent(getContext(), CAddSignatureActivity.class);
+        intent.putExtra(CAddSignatureActivity.EXTRA_SHOW_NONE_TYPE, true);
+        intent.putExtra(CAddSignatureActivity.EXTRA_TITLE, getString(R.string.tools_customize_the_signature_appearance));
+        intent.putExtra(CAddSignatureActivity.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        addSignatureLauncher.launch(intent);
+    }
+
+    public ActivityResultLauncher<Intent> selectCertificateLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
+        if (result.getData() != null && result.getData().getData()!=null) {
+            Uri certificateUri = result.getData().getData();
+            CImportCertificateDigitalDialog digitalDialog = CImportCertificateDigitalDialog.newInstance(certificateUri);
+            digitalDialog.setSelectCertFileListener(selectCertFileListener);
+            digitalDialog.show(getChildFragmentManager(), "certDialog");
+        }
+    });
+
+    public static CPDFSelectDigitalSignatureDialog newInstance() {
+        Bundle args = new Bundle();
+        CPDFSelectDigitalSignatureDialog fragment = new CPDFSelectDigitalSignatureDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setStyle(STYLE_NO_TITLE, R.style.tools_dialog_theme);
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        if (getDialog() != null && getDialog().getWindow() != null) {
+            getDialog().getWindow().setBackgroundDrawableResource(R.drawable.tools_dialog_background);
+        }
+        View view = inflater.inflate(R.layout.tools_sign_digital_sign_select_dialog, container, false);
+        rgType = view.findViewById(R.id.rg_type);
+        Button btnCancel = view.findViewById(R.id.btn_cancel);
+        Button btnDone = view.findViewById(R.id.btn_confirm);
+        btnCancel.setOnClickListener(this);
+        btnDone.setOnClickListener(this);
+        return view;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.btn_cancel) {
+            dismiss();
+        } else if (v.getId() == R.id.btn_confirm) {
+            if (!CPermissionUtil.hasStoragePermissions(getContext())){
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+                    CPermissionUtil.openManageAllFileAppSettings(getContext());
+                }else {
+                    requestStorageLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+                }
+                return;
+            }
+            if (rgType.getCheckedRadioButtonId() == R.id.rb_import_digital_sign){
+                selectCertificateLauncher.launch(CFileUtils.getIntent(CERTIFICATE_DIGITAL_TYPE));
+            }else {
+                CreateCertificateDigitalDialog dialog = CreateCertificateDigitalDialog.newInstance();
+                dialog.setSelectCertFileListener(selectCertFileListener);
+                dialog.show(getChildFragmentManager(), "certDialog");
+            }
+        }
+    }
+
+    public void setCertDigitalSignListener(COnCertDigitalSignListener certDigitalSignListener) {
+        this.certDigitalSignListener = certDigitalSignListener;
+    }
+
+    public interface COnCertDigitalSignListener{
+        void sign(String certFilePath, String certPassword, String signImagePath);
+    }
+}
+
+

+ 93 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CountryReginSpinnerAdapter.java

@@ -0,0 +1,93 @@
+/**
+ * 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.tools.signature.importcert.create;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.tools.R;
+
+import java.util.List;
+import java.util.Locale;
+
+
+public class CountryReginSpinnerAdapter extends BaseAdapter {
+
+    public List<Locale> list;
+
+    private Context mContext;
+
+    private Locale selectLocal;
+
+    public CountryReginSpinnerAdapter(@NonNull Context context, List<Locale> locales) {
+        selectLocal = new Locale("", Locale.getDefault().getCountry());
+        this.list = locales;
+        mContext = context;
+    }
+
+    public void setSelectLocal(Locale selectLocal) {
+        this.selectLocal = selectLocal;
+    }
+
+    public int getSelectPosition(){
+        if (selectLocal != null){
+            for (int i = 0; i < list.size(); i++) {
+                Locale item = list.get(i);
+                if (selectLocal.equals(item)) {
+                    return i;
+                }
+            }
+        }
+        return 0;
+    }
+
+    public String getSelectCountryRegin(){
+        if (selectLocal != null){
+            return selectLocal.getCountry();
+        }
+        return Locale.getDefault().getCountry();
+    }
+
+    @Override
+    public int getCount() {
+        return list.size();
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return list.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        convertView = inflater.inflate(R.layout.tools_spinner_list_item, null);
+        if (convertView != null){
+            AppCompatTextView textView = convertView.findViewById(R.id.tv_menu_title);
+            Locale locale = list.get(position);
+            textView.setText(locale.getCountry() +" - " + locale.getDisplayName(Locale.US));
+            textView.setTypeface(selectLocal != null && selectLocal == locale ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
+            convertView.setBackgroundResource(locale == selectLocal ? R.drawable.tools_annotation_font_bold_bg : 0);
+        }
+        return convertView;
+    }
+}

+ 339 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/importcert/create/CreateCertificateDigitalDialog.java

@@ -0,0 +1,339 @@
+/**
+ * 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.tools.signature.importcert.create;
+
+import android.app.Dialog;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.Switch;
+import android.widget.ViewSwitcher;
+
+import androidx.activity.ComponentDialog;
+import androidx.activity.OnBackPressedCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatSpinner;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.core.document.signature.CPDFOwnerInfo;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.CFileUtils;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
+import com.compdfkit.tools.common.utils.view.CEditText;
+import com.compdfkit.tools.signature.CertificateDigitalDatas;
+import com.compdfkit.tools.signature.interfaces.COnSelectCertFileListener;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.UUID;
+
+
+public class CreateCertificateDigitalDialog extends CBasicBottomSheetDialogFragment implements View.OnClickListener {
+
+    private AppCompatTextView tvTitle;
+
+    private AppCompatImageView ivClose;
+
+    private CEditText etName;
+
+    private CEditText etOrganizationUnit;
+
+    private CEditText etOrganizationName;
+
+    private CEditText etEmailAddress;
+
+    private AppCompatSpinner spinnerCountry;
+
+    private Switch swSaveToFile;
+
+    private AppCompatButton btnOk;
+
+    private ViewSwitcher switcher;
+
+    private AppCompatTextView tvSaveAddress;
+
+    private LinearLayout llSaveAddress;
+
+    private CEditText etPassword;
+
+    private CEditText etConfirmPassword;
+
+    private AppCompatButton btnConfirmCreate;
+
+    private boolean showSaveStatus = false;
+
+    private OnBackPressedCallback callback;
+
+    private String customSavePath;
+
+    private AppCompatTextView tvPasswordError;
+
+    private COnSelectCertFileListener selectCertFileListener;
+
+    private ScrollView scrollView;
+
+    private CountryReginSpinnerAdapter countryReginSpinnerAdapter;
+
+    private String fileName = "";
+
+    private ActivityResultLauncher<Intent> selectDirLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
+        if (result.getData() != null && result.getData().getData() != null) {
+            Uri uri = result.getData().getData();
+            CFileUtils.takeUriPermission(getContext(), result.getData().getData());
+            customSavePath = Environment.getExternalStorageDirectory().getAbsolutePath()  + File.separator + uri.getPath().replace("/tree/primary:", "");
+            tvSaveAddress.setText(getSaveAddress() + File.separator + fileName);
+        }
+    });
+
+    public static CreateCertificateDigitalDialog newInstance() {
+        Bundle args = new Bundle();
+        CreateCertificateDigitalDialog fragment = new CreateCertificateDigitalDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    protected int getStyle() {
+        return R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle_TopCorners;
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        Dialog dialog = super.onCreateDialog(savedInstanceState);
+        if (dialog instanceof ComponentDialog) {
+            ComponentDialog componentDialog = (ComponentDialog) dialog;
+            callback = new OnBackPressedCallback(true) {
+                @Override
+                public void handleOnBackPressed() {
+                    if (showSaveStatus) {
+                        showInfoStatusView();
+                        showSaveStatus = false;
+                        callback.setEnabled(false);
+                    } else {
+                        dismiss();
+                    }
+                }
+            };
+            componentDialog.getOnBackPressedDispatcher().addCallback(callback);
+        }
+        return dialog;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_create_cert_digital_id_fragment;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        tvTitle = view.findViewById(R.id.tv_tool_bar_title);
+        ivClose = view.findViewById(R.id.iv_tool_bar_close);
+        etName = view.findViewById(R.id.et_name);
+        etOrganizationUnit = view.findViewById(R.id.et_organization_unit);
+        etOrganizationName = view.findViewById(R.id.et_organization_name);
+        scrollView = view.findViewById(R.id.scroll_view);
+        etEmailAddress = view.findViewById(R.id.et_email_address);
+        spinnerCountry = view.findViewById(R.id.spinner_country_regin);
+        swSaveToFile = view.findViewById(R.id.sw_save_to_file);
+        btnOk = view.findViewById(R.id.btn_ok);
+        switcher = view.findViewById(R.id.view_switcher);
+        tvSaveAddress = view.findViewById(R.id.tv_save_address);
+        llSaveAddress = view.findViewById(R.id.ll_save_address);
+        etPassword = view.findViewById(R.id.et_password);
+        etConfirmPassword = view.findViewById(R.id.et_confirm_password);
+        btnConfirmCreate = view.findViewById(R.id.btn_save);
+        tvPasswordError = view.findViewById(R.id.tv_password_error);
+        btnOk.setOnClickListener(this);
+        tvSaveAddress.setOnClickListener(this);
+        btnConfirmCreate.setOnClickListener(this);
+        ivClose.setOnClickListener(this);
+    }
+
+    @Override
+    protected void onViewCreate() {
+        String uuid = UUID.randomUUID().toString();
+        fileName = "new_cert_"+  uuid.substring(uuid.length()-4, uuid.length())+".p12";
+        tvTitle.setText(R.string.tools_create_a_self_signed_digital_id);
+        initCountryReginData();
+        etName.addTextChangedListener((s, start, before, count) -> {
+            enableConfirmButton();
+        });
+        etOrganizationUnit.addTextChangedListener((s, start, before, count) -> {
+            enableConfirmButton();
+        });
+        etEmailAddress.addTextChangedListener((s, start, before, count) -> {
+            enableConfirmButton();
+        });
+        etOrganizationName.addTextChangedListener((s, start, before, count) -> {
+            enableConfirmButton();
+        });
+        swSaveToFile.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            llSaveAddress.setVisibility(isChecked ? View.VISIBLE : View.GONE);
+            tvSaveAddress.setText(getSaveAddress() + File.separator + fileName);
+        });
+        tvSaveAddress.setText(getSaveAddress() + File.separator + fileName);
+        enableConfirmButton();
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.btn_ok) {
+            callback.setEnabled(true);
+            showSaveStatusView();
+            showSaveStatus = true;
+        } else if (v.getId() == R.id.iv_tool_bar_close) {
+            dismiss();
+        } else if (v.getId() == R.id.tv_save_address) {
+            selectDirLauncher.launch(CFileUtils.selectSystemDir(true));
+        } else if (v.getId() == R.id.btn_save){
+            String name = etName.getText();
+            String grantor = etOrganizationUnit.getText();
+            String sectoral = etOrganizationName.getText();
+            String email = etEmailAddress.getText();
+            String countryArea = countryReginSpinnerAdapter.getSelectCountryRegin();
+            String password = etPassword.getText();
+            String verifyPassword = etConfirmPassword.getText();
+
+            if (TextUtils.isEmpty(password) || TextUtils.isEmpty(verifyPassword) || !password.equals(verifyPassword)){
+                etPassword.setError(true);
+                etConfirmPassword.setError(true);
+                tvPasswordError.setVisibility(View.VISIBLE);
+                return;
+            }
+            etPassword.setError(false);
+            etConfirmPassword.setError(false);
+            tvPasswordError.setVisibility(View.GONE);
+
+            CPDFOwnerInfo ownerInfo = new CPDFOwnerInfo();
+            ownerInfo.setCommonName(name);
+            ownerInfo.setOrgnizeUnit(grantor);
+            ownerInfo.setOrgnize(sectoral);
+            ownerInfo.setEmail(email);
+            ownerInfo.setCountry(countryArea);
+
+            String saveDir = getSaveAddress();
+            boolean success = CertificateDigitalDatas.generatePKCS12Cert(ownerInfo, etPassword.getText(),
+                    saveDir, fileName);
+            if (success){
+                if (selectCertFileListener != null) {
+                    selectCertFileListener.certificateFile(new File(saveDir, fileName).getAbsolutePath(), etPassword.getText());
+                }
+            }
+        }
+    }
+
+    private void initCountryReginData(){
+        CThreadPoolUtils.getInstance().execute(()->{
+            List<Locale> datas = getLocals();
+            if (getActivity() != null) {
+                getActivity().runOnUiThread(()->{
+                    countryReginSpinnerAdapter = new CountryReginSpinnerAdapter(getContext(), datas);
+                    spinnerCountry.setAdapter(countryReginSpinnerAdapter);
+                    spinnerCountry.setSelection(countryReginSpinnerAdapter.getSelectPosition());
+                });
+            }
+        });
+        spinnerCountry.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                if (countryReginSpinnerAdapter != null) {
+                    countryReginSpinnerAdapter.setSelectLocal(countryReginSpinnerAdapter.list.get(position));
+                }
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+
+            }
+        });
+    }
+
+    private void enableConfirmButton() {
+        String name = etName.getText();
+        String grantor = etOrganizationUnit.getText();
+        String sectoral = etOrganizationName.getText();
+        String email = etEmailAddress.getText();
+        String countryArea = "CN";
+        boolean enable = !TextUtils.isEmpty(name) && !TextUtils.isEmpty(grantor)
+                && !TextUtils.isEmpty(sectoral) && !TextUtils.isEmpty(email) && !TextUtils.isEmpty(countryArea);
+        btnOk.setEnabled(enable);
+    }
+
+    private void showSaveStatusView() {
+        switcher.setInAnimation(getContext(), R.anim.tools_slide_in_right);
+        switcher.setOutAnimation(getContext(), R.anim.tools_slide_out_left);
+        switcher.showNext();
+        tvTitle.setText(R.string.tools_save_a_self_signed_digital_id);
+    }
+
+    private void showInfoStatusView() {
+        switcher.setInAnimation(getContext(), R.anim.tools_slide_in_left);
+        switcher.setOutAnimation(getContext(), R.anim.tools_slide_out_right);
+        switcher.showPrevious();
+        tvTitle.setText(R.string.tools_create_a_self_signed_digital_id);
+
+    }
+
+    private String getSaveAddress() {
+        if (!TextUtils.isEmpty(customSavePath)){
+            return customSavePath;
+        }
+        File file;
+        if (swSaveToFile.isChecked()) {
+            file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), CFileUtils.ROOT_FOLDER);
+        } else {
+            file = new File(getContext().getCacheDir(), CFileUtils.CACHE_FOLDER);
+        }
+        return file.getAbsolutePath();
+    }
+
+    private List<Locale> getLocals(){
+        String[] isos = Locale.getISOCountries();
+        List<Locale> list = new ArrayList<>();
+        for (String iso : isos) {
+            list.add(new Locale("", iso));
+        }
+        return list;
+    }
+
+    public void setSelectCertFileListener(COnSelectCertFileListener selectCertFileListener) {
+        this.selectCertFileListener = selectCertFileListener;
+    }
+}

+ 129 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertAttrDatas.java

@@ -0,0 +1,129 @@
+/**
+ * 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.tools.signature.info;
+
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.compdfkit.core.document.signature.CPDFAuinfoac;
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFExtInfo;
+import com.compdfkit.core.document.signature.CPDFOwnerInfo;
+import com.compdfkit.core.document.signature.CPDFX509;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.date.CDateUtil;
+import com.compdfkit.tools.signature.bean.CPDFCertAttrDataItem;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CertAttrDatas {
+
+    public static List<CPDFCertAttrDataItem> getAbstractInfo(Context context, CPDFX509 cpdfx509){
+        List<CPDFCertAttrDataItem> list = new ArrayList<>();
+        CPDFCertInfo certInfo = cpdfx509.getCertInfo();
+        CPDFExtInfo extInfo = certInfo.getExtInfo();
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_subject), getOwnerContent(certInfo.getSubject())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_issuer), getOwnerContent(certInfo.getIssuer())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_valid_start_date), CDateUtil.formatPDFUTCDate(certInfo.getValidDateBegin())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_valid_until_date), CDateUtil.formatPDFUTCDate(certInfo.getValidDateEnd())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_expected_usage), ""));
+        return list;
+    }
+
+
+    public static List<CPDFCertAttrDataItem> getCertAttrDetailInfoList(Context context, CPDFX509 cpdfx509){
+        List<CPDFCertAttrDataItem> list = new ArrayList<>();
+        CPDFCertInfo certInfo = cpdfx509.getCertInfo();
+        CPDFExtInfo extInfo = certInfo.getExtInfo();
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_version), certInfo.getVersion()));
+        CPDFCertInfo.CPDFAlgorithmType algorithmType = certInfo.getAlgorithmType(certInfo.getSignatureAlgOid());
+        String signatureAlgorithm = algorithmType.name().replace("PDFSignatureAlgorithmType","");
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_signature_algorithm), signatureAlgorithm + "(" +  certInfo.getSignatureAlgOid() +")"));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_subject), getOwnerContent(certInfo.getSubject())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_issuer), getOwnerContent(certInfo.getIssuer())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_valid_start_date), CDateUtil.formatPDFUTCDate(certInfo.getValidDateBegin())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_valid_until_date), CDateUtil.formatPDFUTCDate(certInfo.getValidDateEnd())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_certificate_policy), getCertStringArrayInfo(extInfo.getCertificatePolicies())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_crl_distribution_point), getCertStringArrayInfo(extInfo.getCrlDistribute())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_auth_info_access), getAuthInfoAccessContent(extInfo.getAuthorizedInforAccess())));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_issuing_auth_key_identifier), extInfo.getAuthKeyIdentifier()));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_subject_key_identifier), extInfo.getSubjectKeyIdentifier()));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_basic_limit), ""));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_key_usage), extInfo.getKeyUsage()));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_public_key), certInfo.getPublicKey()));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_x_509_data), certInfo.getX509Data()));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_sha1_digest), certInfo.getSha1Digest()));
+        list.add(new CPDFCertAttrDataItem(context.getString(R.string.tools_md5_digest), certInfo.getMd5Digest()));
+        return list;
+    }
+
+    private static String getAuthInfoAccessContent(CPDFAuinfoac[] cpdfAuinfoacs){
+        if (cpdfAuinfoacs != null && cpdfAuinfoacs.length > 0) {
+            StringBuilder builder = new StringBuilder();
+            for (int i = 0; i < cpdfAuinfoacs.length; i++) {
+                CPDFAuinfoac item = cpdfAuinfoacs[i];
+                if (item != null){
+                    builder.append("methodType:").append(item.getMethod_type()).append("\n");
+                    builder.append("nid:").append(item.getNid()).append("\n");
+                    builder.append("URL:").append(item.getUrl());
+                }
+                if (i != cpdfAuinfoacs.length -1){
+                    builder.append("\n\n");
+                }
+            }
+            return builder.toString();
+        }
+        return "";
+    }
+
+    private static String getCertStringArrayInfo(String[] array){
+        if (array != null && array.length > 0){
+            StringBuilder builder = new StringBuilder();
+            for (int i = 0; i < array.length; i++) {
+                String policy = array[i];
+                builder.append(policy);
+                if (i != array.length -1){
+                    builder.append("\n");
+                }
+            }
+            return builder.toString();
+        }
+        return "";
+    }
+
+
+    private static String getOwnerContent(CPDFOwnerInfo ownerInfo){
+        StringBuilder builder = new StringBuilder();
+        List<String> infos = new ArrayList<>();
+        if (!TextUtils.isEmpty(ownerInfo.getCountry())){
+            infos.add("C="+ownerInfo.getCountry());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getOrgnize())){
+            infos.add("O="+ownerInfo.getOrgnize());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getOrgnizeUnit())){
+            infos.add("OU="+ownerInfo.getOrgnizeUnit());
+        }
+        if (!TextUtils.isEmpty(ownerInfo.getCommonName())){
+            infos.add("CN="+ownerInfo.getCommonName());
+        }
+        for (int i = 0; i < infos.size(); i++) {
+            String item = infos.get(i);
+            builder.append(item);
+            if (i != infos.size() -1){
+                builder.append("\n");
+            }
+        }
+        return builder.toString();
+    }
+
+}

+ 57 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertAttrListAdapter.java

@@ -0,0 +1,57 @@
+/**
+ * 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.tools.signature.info;
+
+import android.content.Context;
+import android.view.ViewGroup;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickAdapter;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickViewHolder;
+import com.compdfkit.tools.signature.bean.CPDFCertAttrDataItem;
+
+import java.util.EventListener;
+
+
+public class CertAttrListAdapter extends CBaseQuickAdapter<CPDFCertAttrDataItem, CBaseQuickViewHolder> {
+
+    public static final int ITEM_HEAD = 0;
+
+    public static final int ITEM_CONTENT = 1;
+
+    @Override
+    protected CBaseQuickViewHolder onCreateViewHolder(Context context, ViewGroup parent, int viewType) {
+        if (viewType == ITEM_HEAD){
+            return new CBaseQuickViewHolder(R.layout.tools_sign_certificate_attributes_list_head_item, parent);
+        }else {
+            return new CBaseQuickViewHolder(R.layout.tools_sign_certificate_attributes_list_item, parent);
+        }
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        if (list.get(position).isHead()) {
+            return ITEM_HEAD;
+        } else {
+            return ITEM_CONTENT;
+        }
+    }
+
+    @Override
+    protected void onBindViewHolder(CBaseQuickViewHolder holder, int position, CPDFCertAttrDataItem item) {
+        if (item.isHead()) {
+            holder.setText(R.id.tv_head, item.getHeadTitle());
+        }else {
+            holder.setText(R.id.tv_attr_title, item.getTitle() + ":");
+            holder.setText(R.id.tv_attr_value, item.getValue());
+        }
+
+    }
+}

+ 127 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDetailsDialog.java

@@ -0,0 +1,127 @@
+/**
+ * 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.tools.signature.info;
+
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.core.document.signature.CPDFSigner;
+import com.compdfkit.core.document.signature.CPDFX509;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.CLog;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.views.CToolBar;
+import com.compdfkit.tools.signature.CertificateDigitalDatas;
+import com.compdfkit.tools.signature.bean.CPDFOwnerItemData;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CertDetailsDialog extends CBasicBottomSheetDialogFragment {
+
+    private CToolBar toolBar;
+
+    private RecyclerView recyclerView;
+
+    private CPDFSignature signature;
+
+    private CertDetailsListAdapter detailsListAdapter;
+
+    public static CertDetailsDialog newInstance(CPDFSignature signature) {
+        Bundle args = new Bundle();
+        CertDetailsDialog fragment = new CertDetailsDialog();
+        fragment.setSignature(signature);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public void setSignature(CPDFSignature signature) {
+        this.signature = signature;
+    }
+
+
+    @Override
+    protected int getStyle() {
+        return  R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected float dimAmount() {
+        return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_certificate_details_dialog;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        toolBar = view.findViewById(R.id.tool_bar);
+        recyclerView = view.findViewById(R.id.recycler_view);
+        toolBar.setBackBtnClickListener(v -> {
+            dismiss();
+        });
+    }
+
+    @Override
+    protected void onViewCreate() {
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        detailsListAdapter = new CertDetailsListAdapter();
+        recyclerView.setAdapter(detailsListAdapter);
+        CertificateDigitalDatas.getCertDetails(getContext(), signature);
+        detailsListAdapter.setOnItemClickListener((adapter, view1, position) -> {
+            CPDFOwnerItemData item = detailsListAdapter.list.get(position);
+            CertDigitalSignAttributesDialog dialog = CertDigitalSignAttributesDialog.newInstance(item.getCpdfx509());
+            dialog.show(getChildFragmentManager(), "certAttrDialog");
+        });
+        initData();
+    }
+
+    private void initData(){
+        List<CPDFX509> list = CertificateDigitalDatas.getCertDetails(getContext(), signature);
+        List<CPDFOwnerItemData> dataList = new ArrayList<>();
+        for (int i = 0; i < list.size(); i++) {
+            CPDFX509 cpdfx509 = list.get(i);
+            CPDFOwnerItemData data = new CPDFOwnerItemData(cpdfx509);
+            if (i != list.size() -1){
+                data.setHasParent(true);
+            }
+            dataList.add(data);
+        }
+        detailsListAdapter.setList(dataList);
+    }
+}

+ 102 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDetailsListAdapter.java

@@ -0,0 +1,102 @@
+/**
+ * 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.tools.signature.info;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickAdapter;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickViewHolder;
+import com.compdfkit.tools.common.utils.viewutils.CDimensUtils;
+import com.compdfkit.tools.signature.bean.CPDFOwnerItemData;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class CertDetailsListAdapter extends CBaseQuickAdapter<CPDFOwnerItemData, CBaseQuickViewHolder> {
+
+    private static final String REFRESH_ARROW = "refresh_arrow";
+
+    private List<CPDFOwnerItemData> backList = new ArrayList<>();
+
+    @Override
+    public void setList(List<CPDFOwnerItemData> list) {
+        super.setList(list);
+        backList.addAll(list);
+    }
+
+    @Override
+    protected CBaseQuickViewHolder onCreateViewHolder(Context context, ViewGroup parent, int viewType) {
+        return new CBaseQuickViewHolder(R.layout.tools_sign_certificate_details_list_item, parent);
+    }
+
+    @Override
+    protected void onBindViewHolder(CBaseQuickViewHolder holder, int position, CPDFOwnerItemData item) {
+        holder.setText(R.id.tv_item_title, item.getContent());
+        ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) holder.getView(R.id.iv_item_arrow).getLayoutParams();
+        layoutParams.setMarginStart(getLevelMargin(holder.itemView.getContext(), position +1));
+        holder.setBackgroundColor(R.id.cl_root, ContextCompat.getColor(holder.itemView.getContext(), position == 0 ? R.color.tools_reader_setting_head_bg_color : R.color.tools_color_background));
+        AppCompatTextView title = holder.getView(R.id.tv_item_title);
+        title.setTypeface(position == 0 ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
+        holder.setImageResource(R.id.iv_item_arrow, item.isExpanded() ? R.drawable.tools_ic_arrow_down : R.drawable.tools_ic_right);
+        View view = holder.getView(R.id.iv_item_arrow);
+        view.setVisibility(item.isHasParent() ? View.VISIBLE : View.INVISIBLE);
+        holder.setOnClickListener(R.id.iv_item_arrow, v -> {
+            if (item.isExpanded()) {
+                collapseItem(position, item);
+            }else {
+                expandItem(position, item);
+            }
+        });
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+        super.onBindViewHolder(holder, position);
+        CPDFOwnerItemData item = list.get(position);
+        ((CBaseQuickViewHolder) holder)
+                .setImageResource(R.id.iv_item_arrow, item.isExpanded() ? R.drawable.tools_ic_arrow_down : R.drawable.tools_ic_right);
+    }
+
+    private int getLevelMargin(Context context, int position) {
+        return CDimensUtils.dp2px(context, (position - 1) * 15);
+    }
+
+    private void expandItem(int positionStart, CPDFOwnerItemData item) {
+        item.setExpanded(true);
+        List<CPDFOwnerItemData> tempList = new ArrayList<>(backList.subList(positionStart +1, backList.size()));
+        list.addAll(positionStart + 1, tempList);
+        // Notify the adapter that the arrow status of the clicked item has changed
+        notifyItemChanged(positionStart, REFRESH_ARROW);
+        // Notify the adapter that data has been inserted
+        notifyItemRangeInserted(positionStart + 1, tempList.size());
+    }
+
+
+    private void collapseItem(int positionStart, CPDFOwnerItemData item) {
+        item.setExpanded(false);
+        int removeCount = list.size() - positionStart -1;
+        for (int i = list.size() -1; i > positionStart; i--) {
+            list.remove(i);
+        }
+        notifyItemChanged(positionStart, REFRESH_ARROW);
+        notifyItemRangeRemoved(positionStart + 1, removeCount);
+    }
+}

+ 111 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDigitalSignAttributesDialog.java

@@ -0,0 +1,111 @@
+/**
+ * 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.tools.signature.info;
+
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFX509;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.views.CToolBar;
+import com.compdfkit.tools.signature.bean.CPDFCertAttrDataItem;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CertDigitalSignAttributesDialog extends CBasicBottomSheetDialogFragment {
+
+    private CToolBar toolBar;
+
+    private RecyclerView recyclerView;
+
+    private CPDFX509 cpdfx509;
+
+    private CertAttrListAdapter attrListAdapter;
+
+    public static CertDigitalSignAttributesDialog newInstance(CPDFX509 cpdfx509) {
+        Bundle args = new Bundle();
+        CertDigitalSignAttributesDialog fragment = new CertDigitalSignAttributesDialog();
+        fragment.setCpdfx509(cpdfx509);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public void setCpdfx509(CPDFX509 cpdfx509) {
+        this.cpdfx509 = cpdfx509;
+    }
+
+    @Override
+    protected int getStyle() {
+        return R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected float dimAmount() {
+        return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_certificate_attributes_fragment;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        toolBar = view.findViewById(R.id.tool_bar);
+        recyclerView = view.findViewById(R.id.recycler_view);
+        toolBar.setBackBtnClickListener(v -> {
+            dismiss();
+        });
+    }
+
+    @Override
+    protected void onViewCreate() {
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        attrListAdapter = new CertAttrListAdapter();
+        recyclerView.setAdapter(attrListAdapter);
+        initData();
+    }
+
+    private void initData() {
+        if (cpdfx509 != null) {
+            List<CPDFCertAttrDataItem> list = new ArrayList<>();
+            list.add(new CPDFCertAttrDataItem(getString(R.string.tools_reader_pdf_info_abstract)));
+            list.addAll(CertAttrDatas.getAbstractInfo(getContext(), cpdfx509));
+            list.add(new CPDFCertAttrDataItem(getString(R.string.tools_details)));
+            list.addAll(CertAttrDatas.getCertAttrDetailInfoList(getContext(), cpdfx509));
+            attrListAdapter.setList(list);
+        }
+    }
+}

+ 141 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/CertDigitalSignInfoDialog.java

@@ -0,0 +1,141 @@
+/**
+ * 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.tools.signature.info;
+
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.core.document.signature.CPDFSigner;
+import com.compdfkit.core.document.signature.CPDFX509;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.date.CDateUtil;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.signature.CertificateDigitalDatas;
+import com.compdfkit.tools.signature.SignatureStatus;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+public class CertDigitalSignInfoDialog extends CBasicBottomSheetDialogFragment implements View.OnClickListener {
+
+    private AppCompatTextView tvTitle;
+
+    private AppCompatImageView ivClose;
+
+    private AppCompatTextView tvFounder;
+
+    private AppCompatTextView tvDateOfSignature;
+
+    private AppCompatButton btnSignDetails;
+
+    private CPDFSignature cpdfSignature;
+
+    private AppCompatTextView tvSignStatement;
+
+    private CPDFDocument document;
+
+    public static CertDigitalSignInfoDialog newInstance() {
+        Bundle args = new Bundle();
+        CertDigitalSignInfoDialog fragment = new CertDigitalSignInfoDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public void setDocument(CPDFDocument document) {
+        this.document = document;
+    }
+
+    public void setPDFSignature(CPDFSignature signature) {
+        this.cpdfSignature = signature;
+    }
+
+    @Override
+    protected int getStyle() {
+        return R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle_TopCorners;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_certificate_digital_sign_info_fragment;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        tvTitle = view.findViewById(R.id.tv_tool_bar_title);
+        ivClose = view.findViewById(R.id.iv_tool_bar_close);
+        tvFounder = view.findViewById(R.id.tv_sign_founder);
+        btnSignDetails = view.findViewById(R.id.btn_cert_detail);
+        tvDateOfSignature = view.findViewById(R.id.tv_date_of_sign);
+        tvSignStatement = view.findViewById(R.id.tv_sign_statement_info);
+        ivClose.setOnClickListener(this);
+        btnSignDetails.setOnClickListener(this);
+    }
+
+    @Override
+    protected void onViewCreate() {
+        tvTitle.setText(R.string.tools_view_digital_signature);
+        if (cpdfSignature != null) {
+            CPDFSigner[] signers = cpdfSignature.getSignerArr();
+            if (signers != null && signers.length > 0) {
+                CPDFX509 cert = signers[0].getCert();
+                CPDFCertInfo certInfo = cert.getCertInfo();
+                String commonName = certInfo.getSubject().getCommonName();
+                tvFounder.setText(commonName);
+            }
+            tvDateOfSignature.setText(CDateUtil.transformPDFDate(cpdfSignature.getDate()));
+            SignatureStatus status = CertificateDigitalDatas.verifySignatureStatus(document, cpdfSignature);
+            switch (status) {
+                case VALID:
+                    tvSignStatement.setText(R.string.tools_sign_is_valid_info);
+                    break;
+                case FAILURES:
+                    tvSignStatement.setText(R.string.tools_sign_is_in_valid_info);
+                    break;
+                case WRONG:
+                    tvSignStatement.setText(R.string.tools_sign_cert_has_expired);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.iv_tool_bar_close) {
+            dismiss();
+        } else if (v.getId() == R.id.btn_cert_detail) {
+            CertDetailsDialog detailsDialog = CertDetailsDialog.newInstance(cpdfSignature);
+            detailsDialog.show(getChildFragmentManager(), "certDetailDialog");
+        }
+    }
+}

+ 152 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/signlist/CPDFCertDigitalSignListDialog.java

@@ -0,0 +1,152 @@
+package com.compdfkit.tools.signature.info.signlist;
+
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.CLog;
+import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.threadpools.SimpleBackgroundTask;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.views.CToolBar;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.tools.signature.CertificateDigitalDatas;
+import com.compdfkit.tools.signature.SignatureStatus;
+import com.compdfkit.tools.signature.bean.CPDFSignatureItemData;
+import com.compdfkit.tools.signature.info.CertDigitalSignInfoDialog;
+import com.compdfkit.tools.signature.info.signlist.adapter.CertDigitalSignListAdapter;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CPDFCertDigitalSignListDialog extends CBasicBottomSheetDialogFragment {
+
+    private RecyclerView recyclerView;
+
+    private CToolBar toolBar;
+
+    private ProgressBar progressBar;
+
+    private CPDFViewCtrl pdfView;
+
+    private CertDigitalSignListAdapter signListAdapter;
+
+
+    public void initWithPDFView(CPDFViewCtrl pdfView) {
+        this.pdfView = pdfView;
+    }
+
+    public static CPDFCertDigitalSignListDialog newInstance() {
+        Bundle args = new Bundle();
+        CPDFCertDigitalSignListDialog fragment = new CPDFCertDigitalSignListDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    protected int getStyle() {
+        return R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected float dimAmount() {
+        return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_cert_digital_sign_list_fragment;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        recyclerView = view.findViewById(R.id.recycler_view);
+        toolBar = view.findViewById(R.id.tool_bar);
+        progressBar = view.findViewById(R.id.progress_bar);
+        toolBar.setBackBtnClickListener(v -> {
+            dismiss();
+        });
+    }
+
+    @Override
+    protected void onViewCreate() {
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        signListAdapter = new CertDigitalSignListAdapter(pdfView.getCPdfReaderView().getPDFDocument());
+        recyclerView.setAdapter(signListAdapter);
+        initSignatureDatas();
+        signListAdapter.setOnItemClickListener((adapter, view1, position) -> {
+            CPDFSignatureItemData signature = adapter.list.get(position);
+            CertDigitalSignInfoDialog infoDialog = CertDigitalSignInfoDialog.newInstance();
+            infoDialog.setPDFSignature(signature.getSignature());
+            infoDialog.setDocument(pdfView.getCPdfReaderView().getPDFDocument());
+            infoDialog.show(getChildFragmentManager(), "signInfoDialog");
+        });
+        signListAdapter.addOnItemChildClickListener(R.id.iv_delete, (adapter, view1, position) -> {
+            CPDFSignatureItemData signature = adapter.list.get(position);
+            CAlertDialog alertDialog = CAlertDialog.newInstance(getString(R.string.tools_warning), getString(R.string.tools_are_you_sure_to_delete));
+            alertDialog.setCancelClickListener(v -> {
+                alertDialog.dismiss();
+            });
+            alertDialog.setConfirmClickListener(v -> {
+                boolean result = CertificateDigitalDatas.removeDigitalSign(pdfView.getCPdfReaderView().getPDFDocument(), signature.getSignature());
+                if (result) {
+                    signListAdapter.remove(position);
+                    signListAdapter.notifyItemRemoved(position);
+                }
+                alertDialog.dismiss();
+            });
+            alertDialog.show(getChildFragmentManager(), "alertDialog");
+        });
+    }
+
+    private void initSignatureDatas() {
+        progressBar.setVisibility(View.VISIBLE);
+        SimpleBackgroundTask<List<CPDFSignatureItemData>> task = new SimpleBackgroundTask<List<CPDFSignatureItemData>>(getContext()) {
+
+            @Override
+            protected List<CPDFSignatureItemData> onRun() {
+                CPDFDocument document = pdfView.getCPdfReaderView().getPDFDocument();
+                List<CPDFSignatureItemData> itemDataList = new ArrayList<>();
+                List<CPDFSignature> list = CertificateDigitalDatas.getDigitalSignList(document);
+                for (CPDFSignature signature : list) {
+                    SignatureStatus status = CertificateDigitalDatas.verifySignatureStatus(document, signature);
+                    itemDataList.add(new CPDFSignatureItemData(signature, status));
+                }
+                return itemDataList;
+            }
+
+            @Override
+            protected void onSuccess(List<CPDFSignatureItemData> result) {
+                signListAdapter.setList(result);
+                progressBar.setVisibility(View.GONE);
+                recyclerView.setVisibility(View.VISIBLE);
+            }
+        };
+        task.execute();
+    }
+}

+ 61 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/info/signlist/adapter/CertDigitalSignListAdapter.java

@@ -0,0 +1,61 @@
+package com.compdfkit.tools.signature.info.signlist.adapter;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.ViewGroup;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFSigner;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickAdapter;
+import com.compdfkit.tools.common.utils.adapter.CBaseQuickViewHolder;
+import com.compdfkit.tools.common.utils.date.CDateUtil;
+import com.compdfkit.tools.signature.bean.CPDFSignatureItemData;
+
+
+public class CertDigitalSignListAdapter extends CBaseQuickAdapter<CPDFSignatureItemData, CBaseQuickViewHolder> {
+
+    private CPDFDocument document;
+
+    public CertDigitalSignListAdapter(CPDFDocument document){
+        this.document = document;
+    }
+
+    @Override
+    protected CBaseQuickViewHolder onCreateViewHolder(Context context, ViewGroup parent, int viewType) {
+        return new CBaseQuickViewHolder(R.layout.tools_sign_cert_digital_sign_list_item, parent);
+    }
+
+    @Override
+    protected void onBindViewHolder(CBaseQuickViewHolder holder, int position, CPDFSignatureItemData item) {
+        Context context = holder.itemView.getContext();
+        CPDFSigner[] signers = item.getSignature().getSignerArr();
+        CPDFCertInfo certInfos = signers[0].getCert().getCertInfo();
+        switch (item.getSignatureStatus()){
+            case VALID:
+                holder.setText(R.id.tv_sign_status, R.string.tools_authentication_successful);
+                holder.setImageResource(R.id.iv_icon, R.drawable.tools_ic_digital_sign_is_valid);
+                holder.setText(R.id.tv_sign_desc, context.getString(R.string.tools_valid_signature) + "," +
+                        context.getString(R.string.tools_signed_by) + " " + certInfos.getSubject().getCommonName());
+                break;
+            case FAILURES:
+                holder.setText(R.id.tv_sign_status, R.string.tools_authentication_failures);
+                holder.setImageResource(R.id.iv_icon, R.drawable.tools_ic_digital_sign_is_failures);
+                holder.setText(R.id.tv_sign_desc, context.getString(R.string.tools_valid_in_signature) + "," +
+                        context.getString(R.string.tools_signed_by) + " " + certInfos.getSubject().getCommonName());
+                break;
+            case WRONG:
+                holder.setText(R.id.tv_sign_status, R.string.tools_authentication_wailures);
+                holder.setImageResource(R.id.iv_icon, R.drawable.tools_ic_digital_sign_is_wrong);
+                holder.setText(R.id.tv_sign_desc, context.getString(R.string.tools_valid_in_signature) + "," +
+                        context.getString(R.string.tools_signed_by) + " " + certInfos.getSubject().getCommonName());
+                break;
+        }
+        if (TextUtils.isEmpty(item.getSignature().getDate())) {
+            holder.setText(R.id.tv_sign_date, "");
+        } else {
+            holder.setText(R.id.tv_sign_date, context.getString(R.string.tools_signature_time) + " " + CDateUtil.transformPDFDate(item.getSignature().getDate()));
+        }
+    }
+}

+ 8 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/interfaces/COnSelectCertFileListener.java

@@ -0,0 +1,8 @@
+package com.compdfkit.tools.signature.interfaces;
+
+
+public interface COnSelectCertFileListener {
+
+    void certificateFile(String filePath, String password);
+
+}

+ 129 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/pdfproperties/pdfsign/CDigitalSignStyleData.java

@@ -0,0 +1,129 @@
+/**
+ * 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.tools.signature.pdfproperties.pdfsign;
+
+
+import androidx.annotation.DrawableRes;
+
+import com.compdfkit.core.document.CPDFSdk;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.date.CDateUtil;
+
+import java.io.Serializable;
+
+public class CDigitalSignStyleData implements Serializable {
+
+
+    public CDigitalSignStyleData(){
+
+    }
+
+    public static CDigitalSignStyleData defaultConfig(String signImagePath){
+        CDigitalSignStyleData data = new CDigitalSignStyleData();
+        data.setLogoResId(R.drawable.tools_ic_compdfkit_logo);
+        data.setSignImagePath(signImagePath);
+        data.setDate(CDateUtil.getDataTime(CDateUtil.NORMAL_DATE_FORMAT));
+        data.setName("");
+        data.setSdkVersion(CPDFSdk.getSDKVersion());
+        data.setAlignment(CDigitalSignStylePreviewView.Alignment.left);
+        return data;
+    }
+
+    private String signImagePath;
+
+    private CDigitalSignStylePreviewView.Alignment alignment = CDigitalSignStylePreviewView.Alignment.left;
+
+    private String position;
+
+    private String reason;
+
+    private String name;
+
+    private String date;
+
+    private @DrawableRes int logoResId;
+
+    private String digtinguishableName;
+
+    private String sdkVersion;
+
+    public String getSignImagePath() {
+        return signImagePath;
+    }
+
+    public void setSignImagePath(String signImagePath) {
+        this.signImagePath = signImagePath;
+    }
+
+    public String getPosition() {
+        return position;
+    }
+
+    public void setPosition(String position) {
+        this.position = position;
+    }
+
+    public String getReason() {
+        return reason;
+    }
+
+    public void setReason(String reason) {
+        this.reason = reason;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDate() {
+        return date;
+    }
+
+    public void setDate(String date) {
+        this.date = date;
+    }
+
+    public String getDigtinguishableName() {
+        return digtinguishableName;
+    }
+
+    public void setDigtinguishableName(String digtinguishableName) {
+        this.digtinguishableName = digtinguishableName;
+    }
+
+    public String getSdkVersion() {
+        return sdkVersion;
+    }
+
+    public void setSdkVersion(String sdkVersion) {
+        this.sdkVersion = sdkVersion;
+    }
+
+
+    public void setAlignment(CDigitalSignStylePreviewView.Alignment alignment) {
+        this.alignment = alignment;
+    }
+
+    public CDigitalSignStylePreviewView.Alignment getAlignment() {
+        return alignment;
+    }
+
+    public int getLogoResId() {
+        return logoResId;
+    }
+
+    public void setLogoResId(int logoResId) {
+        this.logoResId = logoResId;
+    }
+}

+ 244 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/pdfproperties/pdfsign/CDigitalSignStylePreviewView.java

@@ -0,0 +1,244 @@
+package com.compdfkit.tools.signature.pdfproperties.pdfsign;
+
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.constraintlayout.widget.ConstraintSet;
+import androidx.transition.TransitionManager;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.date.CDateUtil;
+import com.compdfkit.tools.common.utils.glide.GlideApp;
+import com.compdfkit.tools.common.utils.image.CBitmapUtil;
+
+public class CDigitalSignStylePreviewView extends FrameLayout {
+
+    private AppCompatImageView ivSignImage;
+
+    private AppCompatTextView tvSignInfo;
+
+    private AppCompatImageView ivLogo;
+
+    private ConstraintLayout clPreview;
+
+    private CDigitalSignStyleData previewData;
+
+    private ConstraintLayout clRoot;
+
+    private ConstraintSet constraintSet = new ConstraintSet();
+
+    private boolean showName = false;
+
+    private boolean showDate = false;
+
+    private boolean showLogo = false;
+
+    private boolean showDistinguishableName;
+
+    private boolean showSDKVersion;
+
+    private boolean showTab;
+
+    private boolean showPosition;
+
+    private boolean showReason;
+
+    public CDigitalSignStylePreviewView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CDigitalSignStylePreviewView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CDigitalSignStylePreviewView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        inflate(context, R.layout.tools_sign_style_preview_view, this);
+        ivSignImage = findViewById(R.id.iv_sign);
+        tvSignInfo = findViewById(R.id.tv_sign_info);
+        ivLogo = findViewById(R.id.iv_logo);
+        clPreview = findViewById(R.id.cl_preview);
+        clRoot = findViewById(R.id.cl_root);
+        constraintSet.clone(clPreview);
+    }
+
+    public void setPreviewData(CDigitalSignStyleData data) {
+        previewData = data;
+        update();
+    }
+
+    private void setSignImage(String signImagePath) {
+        previewData.setSignImagePath(signImagePath);
+        update();
+    }
+
+    public void setShowName(boolean show) {
+        this.showName = show;
+        update();
+    }
+
+    public void setShowTab(boolean show) {
+        this.showTab = show;
+        update();
+    }
+
+    public void setShowSDKVersion(boolean show) {
+        this.showSDKVersion = show;
+        update();
+    }
+
+    public void setShowDate(boolean show) {
+        if (previewData != null) {
+            previewData.setDate(show ? CDateUtil.getDataTime(CDateUtil.NORMAL_DATE_FORMAT_1) : "");
+        }
+        this.showDate = show;
+        update();
+    }
+
+    public void setShowLogo(boolean show) {
+        this.showLogo = show;
+        update();
+    }
+
+    public void setShowDistinguishableName(boolean show) {
+        this.showDistinguishableName = show;
+        update();
+    }
+
+    public void setShowPosition(boolean show){
+        this.showPosition = show;
+        update();
+    }
+
+    public void setShowReason(boolean show){
+        this.showReason = show;
+        update();
+    }
+
+    public void setPosition(String position) {
+        previewData.setPosition(position);
+        update();
+    }
+
+    public void setReason(String reason) {
+        previewData.setReason(reason);
+        update();
+    }
+
+    public CDigitalSignStyleData getPreviewData() {
+        return previewData;
+    }
+
+    public void setAlignment(Alignment alignment){
+        previewData.setAlignment(alignment);
+        update();
+        if (alignment == Alignment.left){
+            constraintSet.connect(R.id.iv_sign, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
+            constraintSet.connect(R.id.iv_sign, ConstraintSet.END, R.id.tv_sign_info, ConstraintSet.START);
+            constraintSet.connect(R.id.tv_sign_info, ConstraintSet.START, R.id.iv_sign, ConstraintSet.END);
+            constraintSet.connect(R.id.tv_sign_info, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
+        }else {
+            constraintSet.connect(R.id.iv_sign, ConstraintSet.START, R.id.tv_sign_info, ConstraintSet.END);
+            constraintSet.connect(R.id.iv_sign, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
+            constraintSet.connect(R.id.tv_sign_info, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
+            constraintSet.connect(R.id.tv_sign_info, ConstraintSet.END, R.id.iv_sign, ConstraintSet.START);
+        }
+        TransitionManager.beginDelayedTransition(clPreview);
+        constraintSet.applyTo(clPreview);
+    }
+
+    private void update() {
+        if (previewData != null) {
+            if (!TextUtils.isEmpty(previewData.getSignImagePath())) {
+                GlideApp.with(getContext())
+                        .load(previewData.getSignImagePath())
+                        .into(ivSignImage);
+            }
+            ivSignImage.setVisibility(TextUtils.isEmpty(previewData.getSignImagePath()) ? GONE : VISIBLE);
+            ivLogo.setVisibility(showLogo ? VISIBLE : GONE);
+            StringBuilder builder = new StringBuilder();
+            if (showName){
+                appendData(builder, showTab, R.string.tools_field_name, previewData.getName());
+            }
+            if (!TextUtils.isEmpty(builder) && showDistinguishableName && !TextUtils.isEmpty(previewData.getDigtinguishableName())){
+                builder.append("\n");
+            }
+            if (showDistinguishableName){
+                appendData(builder, showTab, R.string.tools_distinguishable_name, previewData.getDigtinguishableName());
+            }
+            if (!TextUtils.isEmpty(builder) && showReason && !TextUtils.isEmpty(previewData.getReason())){
+                builder.append("\n");
+            }
+            if (showReason){
+                appendData(builder, showTab, R.string.tools_reason, previewData.getReason());
+            }
+            if (!TextUtils.isEmpty(builder) && showPosition && !TextUtils.isEmpty(previewData.getPosition())){
+                builder.append("\n");
+            }
+            if (showPosition){
+                appendData(builder, showTab, R.string.tools_location, previewData.getPosition());
+            }
+            if (!TextUtils.isEmpty(builder) && showDate && !TextUtils.isEmpty(previewData.getDate())){
+                builder.append("\n");
+            }
+            if (showDate){
+                appendData(builder, showTab, R.string.tools_date, previewData.getDate());
+            }
+            if (!TextUtils.isEmpty(builder) && showSDKVersion && !TextUtils.isEmpty(previewData.getSdkVersion())){
+                builder.append("\n");
+            }
+            if (showSDKVersion) {
+                appendData(builder, showTab, R.string.tools_compdfkit_versions, previewData.getSdkVersion());
+            }
+            tvSignInfo.setText(builder);
+            if (previewData.getAlignment() == Alignment.left) {
+                tvSignInfo.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
+            }else {
+                tvSignInfo.setGravity(Gravity.CENTER_VERTICAL | Gravity.END);
+            }
+        }
+    }
+
+
+
+    private void appendData(StringBuilder builder, boolean showTab, @StringRes int tabStringResId, String value) {
+        if (!TextUtils.isEmpty(value)) {
+            if (showTab) {
+                builder.append(getString(tabStringResId)).append(": ");
+            }
+            builder.append(value);
+        }
+    }
+
+    private String getString(@StringRes int stringResId) {
+        return getContext().getString(stringResId);
+    }
+
+    public Bitmap getBitmap(){
+        buildDrawingCache();
+        Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
+        Bitmap resultBitmap = CBitmapUtil.cropTransparent(bitmap);
+        return resultBitmap;
+    }
+
+    public enum Alignment {
+        left,
+        right
+    }
+
+}

+ 89 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/pdfproperties/pdfsign/CDigitalSignatureWidgetImpl.java

@@ -0,0 +1,89 @@
+/**
+ * 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.tools.signature.pdfproperties.pdfsign;
+
+import android.graphics.Bitmap;
+
+import androidx.fragment.app.FragmentActivity;
+
+import com.compdfkit.core.annotation.CPDFImageScaleType;
+import com.compdfkit.core.annotation.form.CPDFSignatureWidget;
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.core.document.signature.CPDFSignature;
+import com.compdfkit.core.document.signature.CPDFSigner;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.CFileUtils;
+import com.compdfkit.tools.common.utils.CToastUtil;
+import com.compdfkit.tools.common.utils.image.CBitmapUtil;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.tools.signature.CertificateDigitalDatas;
+import com.compdfkit.tools.signature.importcert.create.CPDFSelectDigitalSignatureDialog;
+import com.compdfkit.tools.signature.info.CertDigitalSignInfoDialog;
+import com.compdfkit.tools.signature.preview.CDigitalSignStylePreviewDialog;
+import com.compdfkit.ui.proxy.form.CPDFSignatureWidgetImpl;
+
+import java.io.File;
+
+
+public class CDigitalSignatureWidgetImpl extends CPDFSignatureWidgetImpl {
+
+    @Override
+    public void onSignatureWidgetFocused(CPDFSignatureWidget cpdfSignatureWidget) {
+        CPDFSignature signature = readerView.getPDFDocument().getPdfSignature(cpdfSignatureWidget);
+        CPDFSigner[]  signers = signature.getSignerArr();
+        if (signature.isDigitalSigned()){
+            CertDigitalSignInfoDialog signInfoDialog = CertDigitalSignInfoDialog.newInstance();
+            signInfoDialog.setDocument(readerView.getPDFDocument());
+            signInfoDialog.setPDFSignature(signature);
+            if (readerView.getContext() instanceof FragmentActivity) {
+                signInfoDialog.show(((FragmentActivity) readerView.getContext()).getSupportFragmentManager(), "signInfoDialog");
+            }
+            return;
+        }
+
+        CPDFSelectDigitalSignatureDialog dialog = CPDFSelectDigitalSignatureDialog.newInstance();
+        dialog.setCertDigitalSignListener((certFilePath, certPassword, signImagePath) -> {
+            CPDFCertInfo certInfo = CertificateDigitalDatas.getCertInfo(certFilePath, certPassword);
+            CDigitalSignStylePreviewDialog previewDialog = CDigitalSignStylePreviewDialog.newInstance(signImagePath, certInfo.getSubject().getCommonName());
+            previewDialog.setResultDigitalSignListener((digitalSignImagePath, styleData) -> {
+                try {
+                    // set sign image
+                    Bitmap bitmap = CBitmapUtil.decodeBitmap(digitalSignImagePath);
+                    ((CPDFSignatureWidget) pdfAnnotation).updateApWithBitmap(bitmap, CPDFImageScaleType.SCALETYPE_fitCenter);
+                    refresh();
+                    File saveFile = new File(readerView.getContext().getCacheDir(),
+                            CFileUtils.ROOT_FOLDER + "digitalSign" + File.separator + readerView.getPDFDocument().getFileName());
+                    saveFile.getParentFile().mkdirs();
+                    // sign this pdf document
+                    boolean result = CertificateDigitalDatas.writeSignature(readerView.getPDFDocument(),
+                            cpdfSignatureWidget, styleData,
+                            certFilePath, certPassword, saveFile.getAbsolutePath());
+                    if (result){
+                        CToastUtil.showToast(readerView.getContext(), readerView.getContext().getString(R.string.tools_digital_sign_success));
+                        if (readerView.getParent() instanceof CPDFViewCtrl) {
+                            // open signed pdf document
+                            CPDFViewCtrl pdfView = (CPDFViewCtrl) readerView.getParent();
+                            pdfView.openPDF(saveFile.getAbsolutePath());
+                        }
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+                dialog.dismiss();
+            });
+            if (readerView.getContext() instanceof FragmentActivity) {
+                previewDialog.show(((FragmentActivity) readerView.getContext()).getSupportFragmentManager(), "digitalSignPreviewDialog");
+            }
+        });
+        if (readerView.getContext() instanceof FragmentActivity) {
+            dialog.show(((FragmentActivity) readerView.getContext()).getSupportFragmentManager(), "styleDialog");
+        }
+    }
+}

+ 295 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/preview/CDigitalSignStylePreviewDialog.java

@@ -0,0 +1,295 @@
+/**
+ * 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.tools.signature.preview;
+
+import android.app.Dialog;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+import androidx.activity.ComponentDialog;
+import androidx.activity.OnBackPressedCallback;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatCheckBox;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.core.document.signature.CPDFCertInfo;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.annotation.pdfproperties.pdfsignature.data.CSignatureDatas;
+import com.compdfkit.tools.common.basic.fragment.CBasicBottomSheetDialogFragment;
+import com.compdfkit.tools.common.utils.dialog.CDialogFragmentUtil;
+import com.compdfkit.tools.common.utils.viewutils.CViewUtils;
+import com.compdfkit.tools.common.views.CToolBar;
+import com.compdfkit.tools.signature.pdfproperties.pdfsign.CDigitalSignStyleData;
+import com.compdfkit.tools.signature.pdfproperties.pdfsign.CDigitalSignStylePreviewView;
+import com.compdfkit.tools.signature.preview.view.CSignStylePositionView;
+import com.compdfkit.tools.signature.preview.view.CSignStyleReasonView;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+
+public class CDigitalSignStylePreviewDialog extends CBasicBottomSheetDialogFragment implements View.OnClickListener {
+
+    public static final String EXTRA_SIGN_IMAGE_PATH = "extra_sign_image_path";
+    public static final String EXTRA_COMMON_NAME = "extra_common_name";
+
+    private CDigitalSignStylePreviewView previewView;
+
+    private AppCompatTextView tvPosition;
+
+    private AppCompatTextView tvReason;
+
+    private AppCompatTextView tvPositionDesc;
+
+    private AppCompatTextView tvReasonDesc;
+
+    private CSignStylePositionView positionView;
+
+    private CSignStyleReasonView reasonView;
+
+    private AppCompatButton btnSave;
+
+    private CToolBar toolBar;
+
+    private ScrollView slMain;
+
+    private AppCompatCheckBox cbName;
+
+    private AppCompatCheckBox cbDate;
+
+    private AppCompatCheckBox cbLogo;
+
+    private AppCompatCheckBox cbDistinguishableName;
+
+    private AppCompatCheckBox cbSDKVersion;
+
+    private AppCompatCheckBox cbTab;
+
+    private OnBackPressedCallback callback;
+
+    private LinearLayout llAlignment;
+
+    private AppCompatTextView tvAlignment;
+
+    private AppCompatImageView ivAlignmentLeft;
+
+    private AppCompatImageView ivAlignmentRight;
+
+    private COnResultDigitalSignListener resultDigitalSignListener;
+
+    public static CDigitalSignStylePreviewDialog newInstance(String signImagePath, String commonName) {
+        Bundle args = new Bundle();
+        args.putString(EXTRA_SIGN_IMAGE_PATH, signImagePath);
+        args.putString(EXTRA_COMMON_NAME, commonName);
+        CDigitalSignStylePreviewDialog fragment = new CDigitalSignStylePreviewDialog();
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @NonNull
+    @Override
+    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
+        Dialog dialog = super.onCreateDialog(savedInstanceState);
+        if (dialog instanceof ComponentDialog) {
+            ComponentDialog componentDialog = (ComponentDialog) dialog;
+            callback = new OnBackPressedCallback(true) {
+                @Override
+                public void handleOnBackPressed() {
+                    toolBar.getIvToolBarBackBtn().performClick();
+                }
+            };
+            componentDialog.getOnBackPressedDispatcher().addCallback(callback);
+        }
+        return dialog;
+    }
+
+    @Override
+    protected int getStyle() {
+        return  R.style.Tools_Base_Theme_BasicBottomSheetDialogStyle;
+    }
+
+    @Override
+    protected boolean fullScreen() {
+        return true;
+    }
+
+    @Override
+    protected float dimAmount() {
+        return CViewUtils.isLandScape(getContext()) ? 0.2F : 0F;
+    }
+
+    @Override
+    protected boolean draggable() {
+        return false;
+    }
+
+    @Override
+    protected int layoutId() {
+        return R.layout.tools_sign_style_preview_dialog;
+    }
+
+    @Override
+    protected void onCreateView(View view) {
+        previewView = view.findViewById(R.id.digital_sign_preview);
+        tvPosition = view.findViewById(R.id.tv_position);
+        tvReason = view.findViewById(R.id.tv_reason);
+        tvPositionDesc = view.findViewById(R.id.tv_position_desc);
+        tvReasonDesc = view.findViewById(R.id.tv_reason_desc);
+        toolBar = view.findViewById(R.id.tool_bar);
+        positionView = view.findViewById(R.id.view_position);
+        reasonView = view.findViewById(R.id.view_reason);
+        slMain = view.findViewById(R.id.sl_main);
+        btnSave = view.findViewById(R.id.btn_save);
+        cbName = view.findViewById(R.id.cb_name);
+        cbDate = view.findViewById(R.id.cb_date);
+        cbLogo = view.findViewById(R.id.cb_logo);
+        cbDistinguishableName = view.findViewById(R.id.cb_distinguishable_name);
+        cbSDKVersion = view.findViewById(R.id.cb_compdfkit_version);
+        cbTab = view.findViewById(R.id.cb_tab);
+        ivAlignmentLeft = view.findViewById(R.id.iv_alignment_left);
+        ivAlignmentRight = view.findViewById(R.id.iv_alignment_right);
+        llAlignment = view.findViewById(R.id.ll_alignment_type);
+        tvAlignment = view.findViewById(R.id.tv_alignment);
+    }
+
+    @Override
+    protected void onViewCreate() {
+        initListener();
+        initData();
+    }
+
+    private void initListener(){
+        tvPosition.setOnClickListener(this);
+        tvReason.setOnClickListener(this);
+        toolBar.setBackBtnClickListener(this);
+        btnSave.setOnClickListener(this);
+        ivAlignmentLeft.setOnClickListener(this);
+        ivAlignmentRight.setOnClickListener(this);
+        positionView.setCheckedChangeListener((buttonView, isChecked) -> {
+            if (isChecked){
+                tvPositionDesc.setText(positionView.getPosition());
+            }else {
+                tvPositionDesc.setText(R.string.tools_close);
+            }
+            previewView.setShowPosition(isChecked);
+        });
+        positionView.setTextChangedListener((s, start, before, count) -> {
+            if (positionView.isEnablePosition()){
+                tvPositionDesc.setText(s);
+                previewView.setPosition(TextUtils.isEmpty(s) ?"" : s.toString());
+            }
+        });
+        reasonView.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            if (isChecked){
+                tvReasonDesc.setText(reasonView.getReason());
+            } else {
+                tvReasonDesc.setText(R.string.tools_close);
+            }
+            previewView.setShowReason(isChecked);
+            previewView.setReason(reasonView.getReason());
+        });
+        reasonView.setSelectReasonListener(reason -> {
+            if (reasonView.isEnableReason()){
+                tvReasonDesc.setText(reason);
+                previewView.setReason(reason);
+            }
+        });
+        cbTab.setOnCheckedChangeListener((buttonView, isChecked) -> previewView.setShowTab(isChecked));
+        cbName.setOnCheckedChangeListener((buttonView, isChecked) -> previewView.setShowName(isChecked));
+        cbDate.setOnCheckedChangeListener((buttonView, isChecked) -> previewView.setShowDate(isChecked));
+        cbDistinguishableName.setOnCheckedChangeListener((buttonView, isChecked) -> previewView.setShowDistinguishableName(isChecked));
+        cbSDKVersion.setOnCheckedChangeListener((buttonView, isChecked) -> previewView.setShowSDKVersion(isChecked));
+        cbLogo.setOnCheckedChangeListener((buttonView, isChecked) -> previewView.setShowLogo(isChecked));
+    }
+
+    private void initData(){
+        String signImagePath = getArguments().getString(EXTRA_SIGN_IMAGE_PATH, "");
+        CDigitalSignStyleData data = CDigitalSignStyleData.defaultConfig(signImagePath);
+        if (getArguments() != null && !TextUtils.isEmpty(getArguments().getString(EXTRA_COMMON_NAME))) {
+            String commonName = getArguments().getString(EXTRA_COMMON_NAME);
+            data.setDigtinguishableName(commonName);
+            data.setName(commonName);
+        }
+        previewView.setPreviewData(data);
+        previewView.setShowName(cbName.isChecked());
+        previewView.setShowDate(cbDate.isChecked());
+        previewView.setShowLogo(cbLogo.isChecked());
+        previewView.setShowDistinguishableName(cbDistinguishableName.isChecked());
+        previewView.setShowSDKVersion(cbSDKVersion.isChecked());
+        previewView.setShowTab(cbTab.isChecked());
+        ivAlignmentLeft.setSelected(true);
+        tvAlignment.setVisibility(TextUtils.isEmpty(signImagePath) ? View.GONE : View.VISIBLE);
+        llAlignment.setVisibility(TextUtils.isEmpty(signImagePath) ? View.GONE : View.VISIBLE);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v.getId() == R.id.tv_position) {
+            positionView.setVisibility(View.VISIBLE);
+            slMain.setVisibility(View.GONE);
+        } else if (v.getId() == R.id.tv_reason) {
+            reasonView.setVisibility(View.VISIBLE);
+            slMain.setVisibility(View.GONE);
+        } else if (v.getId() == toolBar.getIvToolBarBackBtn().getId()){
+            if (positionView.getVisibility() == View.VISIBLE){
+                positionView.setVisibility(View.GONE);
+                slMain.setVisibility(View.VISIBLE);
+                return;
+            }
+            if (reasonView.getVisibility() == View.VISIBLE){
+                reasonView.setVisibility(View.GONE);
+                slMain.setVisibility(View.VISIBLE);
+                return;
+            }
+            dismiss();
+        } else if (v.getId() == R.id.iv_alignment_left) {
+            ivAlignmentLeft.setSelected(true);
+            ivAlignmentRight.setSelected(false);
+            previewView.setAlignment(CDigitalSignStylePreviewView.Alignment.left);
+        } else if (v.getId() == R.id.iv_alignment_right) {
+            ivAlignmentLeft.setSelected(false);
+            ivAlignmentRight.setSelected(true);
+            previewView.setAlignment(CDigitalSignStylePreviewView.Alignment.right);
+        } else if (v.getId() == R.id.btn_save){
+            if (positionView.getVisibility() == View.VISIBLE){
+                positionView.setVisibility(View.GONE);
+                slMain.setVisibility(View.VISIBLE);
+                return;
+            }
+            if (reasonView.getVisibility() == View.VISIBLE){
+                reasonView.setVisibility(View.GONE);
+                slMain.setVisibility(View.VISIBLE);
+                return;
+            }
+            Bitmap bitmap = previewView.getBitmap();
+            String imagePath = CSignatureDatas.saveSignatureBitmap(getContext(), bitmap);
+            if (resultDigitalSignListener != null) {
+                resultDigitalSignListener.sign(imagePath, previewView.getPreviewData());
+            }
+            dismiss();
+        }
+    }
+
+    public void setResultDigitalSignListener(COnResultDigitalSignListener resultDigitalSignListener) {
+        this.resultDigitalSignListener = resultDigitalSignListener;
+    }
+
+    public interface COnResultDigitalSignListener{
+        void sign(String digitalSignImagePath, CDigitalSignStyleData styleData);
+    }
+}

+ 89 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/preview/view/CSignStylePositionView.java

@@ -0,0 +1,89 @@
+/**
+ * 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.tools.signature.preview.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.FrameLayout;
+import android.widget.Switch;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.interfaces.COnTextChangedListener;
+import com.compdfkit.tools.common.utils.view.CEditText;
+
+
+public class CSignStylePositionView extends FrameLayout {
+
+    private Switch swPosition;
+
+    private CEditText etPosition;
+
+    private View line;
+
+    private COnTextChangedListener textChangedListener;
+
+    private CompoundButton.OnCheckedChangeListener checkedChangeListener;
+
+    public CSignStylePositionView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CSignStylePositionView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CSignStylePositionView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    private void initView(Context context) {
+        inflate(context, R.layout.tools_sign_style_preview_position, this);
+        line = findViewById(R.id.view_line);
+        swPosition = findViewById(R.id.sw_position);
+        etPosition = findViewById(R.id.et_position);
+        swPosition.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            etPosition.setVisibility(isChecked ? VISIBLE : GONE);
+            line.setVisibility(isChecked ? VISIBLE : GONE);
+            if (!isChecked){
+                etPosition.setText("");
+            }
+            if (checkedChangeListener != null) {
+                checkedChangeListener.onCheckedChanged(buttonView, isChecked);
+            }
+        });
+        etPosition.addTextChangedListener((s, start, before, count) -> {
+            if (textChangedListener != null) {
+                textChangedListener.onTextChanged(s, start, before, count);
+            }
+        });
+    }
+
+    public boolean isEnablePosition() {
+        return swPosition.isChecked();
+    }
+
+    public String getPosition() {
+        return etPosition.getText();
+    }
+
+    public void setCheckedChangeListener(CompoundButton.OnCheckedChangeListener checkedChangeListener) {
+        this.checkedChangeListener = checkedChangeListener;
+    }
+
+    public void setTextChangedListener(COnTextChangedListener textChangedListener) {
+        this.textChangedListener = textChangedListener;
+    }
+}

+ 103 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/preview/view/CSignStyleReasonView.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.tools.signature.preview.view;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.FrameLayout;
+import android.widget.RadioGroup;
+import android.widget.Switch;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.compdfkit.tools.R;
+
+public class CSignStyleReasonView extends FrameLayout {
+
+    private Switch swReason;
+
+    private RadioGroup rgReason;
+
+    private View viewLine;
+
+    private CompoundButton.OnCheckedChangeListener onCheckedChangeListener;
+
+    private COnSelectReasonListener selectReasonListener;
+
+    private String selectReason;
+
+    public CSignStyleReasonView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CSignStyleReasonView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CSignStyleReasonView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView(context);
+    }
+
+    private void initView(Context context){
+        inflate(context, R.layout.tools_sign_style_preview_reason, this);
+        swReason = findViewById(R.id.sw_reason);
+        rgReason = findViewById(R.id.rg_reason);
+        viewLine = findViewById(R.id.view_line);
+        swReason.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            rgReason.setVisibility(isChecked ? VISIBLE : GONE);
+            viewLine.setVisibility(isChecked ? VISIBLE : GONE);
+            if (onCheckedChangeListener != null) {
+                onCheckedChangeListener.onCheckedChanged(buttonView, isChecked);
+            }
+        });
+        selectReason = context.getString(R.string.tools_i_am_the_owner_of_the_document);
+        rgReason.setOnCheckedChangeListener((group, checkedId) -> {
+            if (checkedId == R.id.rb_approving){
+                selectReason = context.getString(R.string.tools_i_am_approving_the_document);
+            } else if (checkedId == R.id.rb_have_reviewed) {
+                selectReason = context.getString(R.string.tools_i_have_reviewed_this_document);
+            } else if (checkedId == R.id.rb_owner) {
+                selectReason = context.getString(R.string.tools_i_am_the_owner_of_the_document);
+            } else if (checkedId == R.id.rb_none){
+                selectReason = context.getString(R.string.tools_none);
+            }
+            if (selectReasonListener != null) {
+                selectReasonListener.reason(selectReason);
+            }
+        });
+    }
+
+
+
+    public String getReason(){
+        return selectReason;
+    }
+
+    public boolean isEnableReason(){
+        return swReason.isChecked();
+    }
+
+    public void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener onCheckedChangeListener) {
+        this.onCheckedChangeListener = onCheckedChangeListener;
+    }
+
+    public void setSelectReasonListener(COnSelectReasonListener selectReasonListener) {
+        this.selectReasonListener = selectReasonListener;
+    }
+
+    public interface COnSelectReasonListener{
+        void reason(String reason);
+    }
+}

+ 117 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/signature/verify/view/CVerifySignStatusView.java

@@ -0,0 +1,117 @@
+/**
+ * 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.tools.signature.verify.view;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatButton;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.fragment.app.FragmentActivity;
+
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
+import com.compdfkit.tools.signature.SignatureStatus;
+import com.compdfkit.tools.signature.info.signlist.CPDFCertDigitalSignListDialog;
+
+public class CVerifySignStatusView extends FrameLayout {
+
+    private AppCompatImageView ivStatus;
+
+    private AppCompatTextView tvStatus;
+
+    private AppCompatButton btnDetails;
+
+    private SignatureStatus status;
+
+    private CPDFViewCtrl pdfView;
+
+    public void initWithPDFView(CPDFViewCtrl pdfView) {
+        this.pdfView = pdfView;
+    }
+
+    public CVerifySignStatusView(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CVerifySignStatusView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public CVerifySignStatusView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initAttr(context, attrs);
+        initView(context);
+        updateStatus();
+    }
+
+    private void initView(Context context) {
+        inflate(context, R.layout.tools_sign_verify_sign_status_view, this);
+        ivStatus = findViewById(R.id.iv_status);
+        tvStatus = findViewById(R.id.tv_status);
+        btnDetails = findViewById(R.id.btn_details);
+        btnDetails.setOnClickListener(v -> {
+            if (getContext() instanceof FragmentActivity) {
+                CPDFCertDigitalSignListDialog signListDialog = CPDFCertDigitalSignListDialog.newInstance();
+                signListDialog.initWithPDFView(pdfView);
+                signListDialog.show(((FragmentActivity) getContext()).getSupportFragmentManager(), "signListDialog");
+            }
+        });
+    }
+
+    private void initAttr(Context context, AttributeSet attrs) {
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CVerifySignStatusView);
+        if (typedArray != null) {
+            int statusFlag = typedArray.getInt(R.styleable.CVerifySignStatusView_status, SignatureStatus.VALID.ordinal());
+            switch (statusFlag) {
+                case 1:
+                    status = SignatureStatus.FAILURES;
+                    break;
+                case 2:
+                    status = SignatureStatus.WRONG;
+                    break;
+                default:
+                    status = SignatureStatus.VALID;
+                    break;
+            }
+            typedArray.recycle();
+        }
+    }
+
+    public void setStatus(SignatureStatus status) {
+        this.status = status;
+        updateStatus();
+    }
+
+    private void updateStatus() {
+        switch (status) {
+            case VALID:
+                ivStatus.setImageResource(R.drawable.tools_ic_digital_sign_is_valid);
+                tvStatus.setText(R.string.tools_sign_is_valid_info);
+                break;
+            case FAILURES:
+                ivStatus.setImageResource(R.drawable.tools_ic_digital_sign_is_failures);
+                tvStatus.setText(R.string.tools_sign_is_in_valid_info);
+                break;
+            case WRONG:
+                ivStatus.setImageResource(R.drawable.tools_ic_digital_sign_is_wrong);
+                tvStatus.setText(R.string.tools_sign_cert_has_expired);
+                break;
+            default:
+                break;
+        }
+    }
+}

+ 7 - 0
ComPDFKit_Tools/src/main/res/anim/tools_slide_in_left.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="-50%p" android:toXDelta="0"
+        android:duration="@android:integer/config_mediumAnimTime"/>
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_mediumAnimTime" />
+</set>

+ 7 - 0
ComPDFKit_Tools/src/main/res/anim/tools_slide_out_right.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <translate android:fromXDelta="0" android:toXDelta="100%p"
+        android:duration="@android:integer/config_mediumAnimTime"/>
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+        android:duration="@android:integer/config_mediumAnimTime" />
+</set>

File diff suppressed because it is too large
+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable-night/tools_ic_digital_signature.xml


+ 9 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_bg_import_certificate_digital_id_error_item.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item >
+        <shape >
+            <solid android:color="@color/tools_text_color_primary_inverse"/>
+            <stroke android:color="@color/tools_error" android:width="2dp"/>
+        </shape>
+    </item>
+</selector>

+ 15 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_bg_import_certificate_digital_id_item.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_focused="true">
+        <shape >
+            <solid android:color="@color/tools_text_color_primary_inverse"/>
+            <stroke android:color="@color/tools_color_accent" android:width="2dp"/>
+        </shape>
+    </item>
+    <item >
+        <shape >
+            <solid android:color="@color/tools_text_color_primary_inverse"/>
+            <stroke android:color="@color/tools_item_dividing_line_color" android:width="1px"/>
+        </shape>
+    </item>
+</selector>

+ 23 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_compdfkit_logo.xml

@@ -0,0 +1,23 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="61dp"
+    android:viewportWidth="60"
+    android:viewportHeight="61">
+  <path
+      android:pathData="M0,5.417C0,2.577 2.303,0.274 5.143,0.274H41.143C43.983,0.274 46.286,2.577 46.286,5.417V49.131H5.143C2.303,49.131 0,46.829 0,43.988V5.417Z"
+      android:strokeAlpha="0.4"
+      android:fillColor="#3863F1"
+      android:fillAlpha="0.4"/>
+  <path
+      android:pathData="M32.572,11.417C22.157,11.417 13.715,19.86 13.715,30.274C13.715,40.688 22.157,49.131 32.572,49.131H46.286V11.417H32.572ZM32.572,23.417C28.785,23.417 25.715,26.487 25.715,30.274C25.715,34.061 28.785,37.131 32.572,37.131H46.286V23.417H32.572Z"
+      android:strokeAlpha="0.4"
+      android:fillColor="#ffffff"
+      android:fillType="evenOdd"
+      android:fillAlpha="1"/>
+  <path
+      android:pathData="M13.715,32.721C13.715,32.763 13.715,32.804 13.715,32.846V49.131V55.131C13.715,57.971 16.017,60.274 18.858,60.274H54.858C57.698,60.274 60,57.971 60,55.131V16.56C60,13.719 57.698,11.417 54.858,11.417H35.143C35.11,11.417 35.077,11.417 35.044,11.417H46.286V49.131H13.715V32.721ZM25.715,30.274C25.715,26.487 28.785,23.417 32.572,23.417H46.286V37.131H32.572C28.785,37.131 25.715,34.061 25.715,30.274Z"
+      android:strokeAlpha="0.4"
+      android:fillColor="#31BC98"
+      android:fillType="evenOdd"
+      android:fillAlpha="0.4"/>
+</vector>

+ 13 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_dark_oval_close.xml

@@ -0,0 +1,13 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="21dp"
+    android:height="20dp"
+    android:viewportWidth="21"
+    android:viewportHeight="20">
+  <path
+      android:pathData="M10.5,10m0,9a9,9 0,1 1,0 -18a9,9 0,1 1,0 18"
+      android:fillColor="#666666"/>
+  <path
+      android:pathData="M9.616,9.911L5.639,13.889L6.523,14.773L10.5,10.795L14.477,14.773L15.361,13.889L11.384,9.911L15.361,5.934L14.477,5.05L10.5,9.027L6.523,5.05L5.639,5.934L9.616,9.911Z"
+      android:fillColor="#ffffff"
+      android:fillType="evenOdd"/>
+</vector>

+ 7 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_checkbox.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/tools_ic_digital_sign_checkbox_select" android:state_checked="true"/>
+    <item android:drawable="@drawable/tools_ic_digital_sign_checkbox_normal" android:state_checked="false"/>
+
+    <item android:drawable="@drawable/tools_ic_digital_sign_checkbox_normal"/>
+</selector>

+ 15 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_checkbox_normal.xml

@@ -0,0 +1,15 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="20dp"
+    android:height="20dp"
+    android:viewportWidth="20"
+    android:viewportHeight="20">
+  <group>
+    <clip-path
+        android:pathData="M1,0L19,0A1,1 0,0 1,20 1L20,19A1,1 0,0 1,19 20L1,20A1,1 0,0 1,0 19L0,1A1,1 0,0 1,1 0z"/>
+    <path
+        android:pathData="M1,0L19,0A1,1 0,0 1,20 1L20,19A1,1 0,0 1,19 20L1,20A1,1 0,0 1,0 19L0,1A1,1 0,0 1,1 0z"
+        android:strokeWidth="3"
+        android:fillColor="#ffffff"
+        android:strokeColor="#D9D9D9"/>
+  </group>
+</vector>

+ 15 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_checkbox_select.xml

@@ -0,0 +1,15 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="20dp"
+    android:height="20dp"
+    android:viewportWidth="20"
+    android:viewportHeight="20">
+  <path
+      android:pathData="M1,0L19,0A1,1 0,0 1,20 1L20,19A1,1 0,0 1,19 20L1,20A1,1 0,0 1,0 19L0,1A1,1 0,0 1,1 0z"
+      android:fillColor="#2D77FA"/>
+  <path
+      android:pathData="M14.683,7.541L8.352,13.872L6.004,11.524"
+      android:strokeWidth="1.5"
+      android:fillColor="#00000000"
+      android:strokeColor="#ffffff"
+      android:strokeLineCap="square"/>
+</vector>

File diff suppressed because it is too large
+ 27 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_is_failures.xml


File diff suppressed because it is too large
+ 18 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_is_valid.xml


File diff suppressed because it is too large
+ 17 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_sign_is_wrong.xml


File diff suppressed because it is too large
+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_digital_signature.xml


File diff suppressed because it is too large
+ 27 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_import_digital_signature.xml


+ 10 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_ic_sign_none.xml

@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M18.5,12C18.5,15.59 15.59,18.5 12,18.5C8.41,18.5 5.5,15.59 5.5,12C5.5,8.41 8.41,5.5 12,5.5C15.59,5.5 18.5,8.41 18.5,12ZM20,12C20,16.418 16.418,20 12,20C7.582,20 4,16.418 4,12C4,7.582 7.582,4 12,4C16.418,4 20,7.582 20,12ZM15.705,9.8C15.998,9.508 15.998,9.033 15.705,8.74C15.412,8.447 14.937,8.447 14.644,8.74L8.359,15.025C8.066,15.318 8.066,15.793 8.359,16.086C8.651,16.379 9.126,16.379 9.419,16.086L15.705,9.8Z"
+      android:fillColor="#43474D"
+      android:fillType="evenOdd"/>
+</vector>

+ 5 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_import_certificate_digital_id_btn.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/tools_color_accent"/>
+    <corners android:radius="2dp"/>
+</shape>

+ 6 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_sign_cert_info_btn_bg.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <stroke android:color="@color/tools_color_accent" android:width="1dp"
+        />
+    <corners android:radius="2dp"/>
+</shape>

+ 19 - 0
ComPDFKit_Tools/src/main/res/drawable/tools_signature_toolbar_btn_corner_status_bg.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:state_selected="true">
+        <shape android:shape="rectangle">
+            <corners android:radius="4dp" />
+            <solid android:color="@color/tools_annot_list_item_select_bg_color" />
+        </shape>
+    </item>
+
+    <item>
+        <shape android:shape="rectangle">
+            <corners android:radius="4dp" />
+            <solid android:color="@color/tools_color_primary" />
+        </shape>
+    </item>
+
+
+</selector>

+ 16 - 0
ComPDFKit_Tools/src/main/res/layout-land/tools_properties_signature_style_add_activity.xml

@@ -83,6 +83,22 @@
             app:layout_constraintTop_toTopOf="@id/iv_add_draw_signature"
             app:srcCompat="@drawable/tools_ic_annotation_pic" />
 
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_none"
+            android:layout_width="38dp"
+            android:layout_height="38dp"
+            android:layout_marginStart="12dp"
+            android:background="@drawable/tools_annot_properties_signature_type_btn_bg"
+            android:foreground="@drawable/tools_common_btn_corner_ripple"
+            android:padding="4dp"
+            app:tint="@color/tools_icon_status_color"
+            app:layout_constraintBottom_toBottomOf="@id/iv_add_draw_signature"
+            app:layout_constraintStart_toEndOf="@id/iv_add_pic_signature"
+            app:layout_constraintTop_toTopOf="@id/iv_add_draw_signature"
+            android:visibility="gone"
+            tools:visibility="visible"
+            app:srcCompat="@drawable/tools_ic_sign_none" />
+
         <com.compdfkit.tools.common.views.pdfproperties.colorlist.ColorListView
             android:id="@+id/color_list_view"
             android:layout_width="200dp"

+ 71 - 0
ComPDFKit_Tools/src/main/res/layout-land/tools_sign_style_preview_dialog.xml

@@ -0,0 +1,71 @@
+<?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:background="@color/tools_style_content_bg">
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:elevation="4dp"
+        android:title="@string/tools_customize_the_signature_appearance"
+        app:layout_constraintTop_toTopOf="parent"
+        app:tools_toolbar_back_icon="@drawable/tools_ic_back">
+
+        <androidx.appcompat.widget.AppCompatButton
+            android:id="@+id/btn_save"
+            android:layout_width="wrap_content"
+            android:layout_height="32dp"
+            android:layout_gravity="end|center_vertical"
+            android:layout_marginEnd="16dp"
+            android:background="@drawable/tools_properties_signature_add_sign"
+            android:minWidth="70dp"
+            android:text="@string/tools_save"
+            android:textColor="@color/tools_color_accent"
+            android:textSize="16sp" />
+
+    </com.compdfkit.tools.common.views.CToolBar>
+
+
+    <include
+        layout="@layout/tools_sign_style_preview_main"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar" />
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/guide_center"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_percent="0.5" />
+
+    <com.compdfkit.tools.signature.preview.view.CSignStylePositionView
+        android:id="@+id/view_position"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/guide_center"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar"
+        tools:background="@color/tools_color_background" />
+
+    <com.compdfkit.tools.signature.preview.view.CSignStyleReasonView
+        android:id="@+id/view_reason"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:visibility="gone"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="@id/guide_center"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar"
+        tools:background="@color/tools_color_background" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 243 - 0
ComPDFKit_Tools/src/main/res/layout-land/tools_sign_style_preview_main.xml

@@ -0,0 +1,243 @@
+<?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"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <com.compdfkit.tools.signature.pdfproperties.pdfsign.CDigitalSignStylePreviewView
+        android:id="@+id/digital_sign_preview"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_margin="16dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/guide_center_1"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.constraintlayout.widget.Guideline
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/guide_center_1"
+        app:layout_constraintGuide_percent="0.5"
+        android:orientation="vertical"
+        />
+
+    <ScrollView
+        android:layout_width="0dp"
+        android:id="@+id/sl_main"
+        android:layout_height="wrap_content"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/guide_center_1"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <androidx.constraintlayout.widget.ConstraintLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_text_signature"
+                android:layout_width="match_parent"
+                android:layout_height="28dp"
+                android:background="@color/tools_reader_setting_head_bg_color"
+                android:gravity="center_vertical"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
+                android:text="@string/tools_text_properties"
+                android:textColor="@color/tools_text_color_primary"
+                android:textSize="12sp"
+                app:layout_constraintTop_toTopOf="parent" />
+
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_alignment"
+                android:layout_width="match_parent"
+                android:layout_height="48dp"
+                android:background="@drawable/tools_common_btn_rectangle_ripple"
+                android:gravity="center_vertical"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
+                android:text="@string/tools_annot_align_type"
+                android:textColor="@color/tools_text_color_primary"
+                app:layout_constraintTop_toBottomOf="@id/tv_text_signature" />
+
+
+            <LinearLayout
+                android:id="@+id/ll_alignment_type"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="24dp"
+                android:background="@drawable/tools_annotation_font_alignment_root_bg"
+                android:orientation="horizontal"
+                app:layout_constraintBottom_toBottomOf="@id/tv_alignment"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintTop_toTopOf="@id/tv_alignment">
+
+                <androidx.appcompat.widget.AppCompatImageView
+                    android:id="@+id/iv_alignment_left"
+                    android:layout_width="49dp"
+                    android:layout_height="32dp"
+                    android:background="@drawable/tools_annotation_font_alignment_bg"
+                    android:button="@null"
+                    android:padding="4dp"
+                    android:textSize="0sp"
+                    app:srcCompat="@drawable/tools_font_alignment_left"
+                    app:tint="@color/tools_font_style_iv_color" />
+
+                <androidx.appcompat.widget.AppCompatImageView
+                    android:id="@+id/iv_alignment_right"
+                    android:layout_width="49dp"
+                    android:layout_height="32dp"
+                    android:background="@drawable/tools_annotation_font_alignment_bg"
+                    android:padding="4dp"
+                    app:srcCompat="@drawable/tools_font_alignment_right"
+                    app:tint="@color/tools_font_style_iv_color" />
+
+            </LinearLayout>
+
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_position"
+                android:layout_width="match_parent"
+                android:layout_height="48dp"
+                android:background="@drawable/tools_common_btn_rectangle_ripple"
+                android:drawableEnd="@drawable/tools_ic_right_arrow"
+                android:gravity="center_vertical"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
+                android:text="@string/tools_location"
+                android:textColor="@color/tools_text_color_primary"
+                app:drawableTint="@color/tools_text_color_primary"
+                app:layout_constraintTop_toBottomOf="@id/tv_alignment" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_position_desc"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="48dp"
+                android:text="@string/tools_close"
+                android:textColor="@color/tools_text_color_primary"
+                app:layout_constraintBaseline_toBaselineOf="@id/tv_position"
+                app:layout_constraintEnd_toEndOf="parent" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_reason"
+                android:layout_width="match_parent"
+                android:layout_height="48dp"
+                android:background="@drawable/tools_common_btn_rectangle_ripple"
+                android:drawableEnd="@drawable/tools_ic_right_arrow"
+                android:gravity="center_vertical"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
+                android:text="@string/tools_reason"
+                android:textColor="@color/tools_text_color_primary"
+                app:drawableTint="@color/tools_text_color_primary"
+                app:layout_constraintTop_toBottomOf="@id/tv_position" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_reason_desc"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginEnd="48dp"
+                android:text="@string/tools_close"
+                android:textColor="@color/tools_text_color_primary"
+                app:layout_constraintBaseline_toBaselineOf="@id/tv_reason"
+                app:layout_constraintEnd_toEndOf="parent" />
+
+            <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_optional_reasons"
+                android:layout_width="match_parent"
+                android:layout_height="28dp"
+                android:background="@color/tools_reader_setting_head_bg_color"
+                android:gravity="center_vertical"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
+                android:text="@string/tools_include_text"
+                android:textColor="@color/tools_text_color_primary"
+                android:textSize="12sp"
+                app:layout_constraintTop_toBottomOf="@id/tv_reason" />
+
+            <androidx.constraintlayout.helper.widget.Flow
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginHorizontal="16dp"
+                android:orientation="vertical"
+                app:constraint_referenced_ids="cb_name,cb_date,cb_logo,cb_distinguishable_name,cb_compdfkit_version,cb_tab"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toBottomOf="@id/tv_optional_reasons"
+
+                />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_name"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:checked="true"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_field_name"
+                android:textColor="@color/tools_text_color_primary" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_date"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:checked="true"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_date"
+                android:textColor="@color/tools_text_color_primary" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_logo"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:checked="true"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_logo"
+                android:textColor="@color/tools_text_color_primary" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_distinguishable_name"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_distinguishable_name"
+                android:textColor="@color/tools_text_color_primary" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_compdfkit_version"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_compdfkit_versions"
+                android:textColor="@color/tools_text_color_primary" />
+
+            <androidx.appcompat.widget.AppCompatCheckBox
+                android:id="@+id/cb_tab"
+                android:layout_width="0dp"
+                android:layout_height="45dp"
+                android:button="@drawable/tools_ic_digital_sign_checkbox"
+                android:checked="true"
+                android:gravity="center_vertical"
+                android:paddingStart="8dp"
+                android:text="@string/tools_tab"
+                android:textColor="@color/tools_text_color_primary" />
+        </androidx.constraintlayout.widget.ConstraintLayout>
+
+    </ScrollView>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+

+ 0 - 1
ComPDFKit_Tools/src/main/res/layout/tools_dialog_tool_bar.xml

@@ -22,7 +22,6 @@
         app:layout_constraintTop_toTopOf="parent"
         tools:text="Tools" />
 
-
     <androidx.appcompat.widget.AppCompatImageView
         android:id="@+id/iv_tool_bar_previous"
         android:layout_width="30dp"

+ 40 - 0
ComPDFKit_Tools/src/main/res/layout/tools_layout_c_edit_text.xml

@@ -0,0 +1,40 @@
+<?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="wrap_content"
+    android:layout_marginHorizontal="16dp">
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        tools:text="@tools:sample/first_names"
+        android:textColor="@color/tools_text_color_disable"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+
+    <androidx.appcompat.widget.AppCompatEditText
+        android:id="@+id/edit_text"
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        android:layout_marginTop="8dp"
+        android:background="@drawable/tools_bg_import_certificate_digital_id_item"
+        android:ellipsize="end"
+        android:textColorHint="@color/tools_text_color_secondary"
+        android:paddingHorizontal="8dp"
+        android:singleLine="true"
+        android:textColor="@color/tools_text_color_primary"
+        android:textSize="14sp"
+        app:drawableTint="@color/tools_text_color_primary"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_title"
+        app:layout_goneMarginTop="0dp"
+         />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
+

+ 9 - 0
ComPDFKit_Tools/src/main/res/layout/tools_pdf_mode_switch_dialog_fragment.xml

@@ -62,6 +62,15 @@
             tools:visibility="visible"
             android:drawableStart="@drawable/tools_page_edit"
             android:text="@string/tools_page_edit_mode" />
+
+        <androidx.appcompat.widget.AppCompatRadioButton
+            android:id="@+id/r_btn_signature_mode"
+            style="@style/tools_pdf_reader_mode_radio_button_style"
+            android:layout_height="60dp"
+            android:visibility="gone"
+            tools:visibility="visible"
+            android:drawableStart="@drawable/tools_ic_digital_signature"
+            android:text="@string/tools_digital_signature" />
     </RadioGroup>
 
 

+ 17 - 0
ComPDFKit_Tools/src/main/res/layout/tools_properties_signature_style_add_activity.xml

@@ -84,6 +84,23 @@
             app:layout_constraintTop_toTopOf="@id/iv_add_draw_signature"
             app:srcCompat="@drawable/tools_ic_annotation_pic" />
 
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_none"
+            android:layout_width="38dp"
+            android:layout_height="38dp"
+            android:layout_marginStart="12dp"
+            android:background="@drawable/tools_annot_properties_signature_type_btn_bg"
+            android:foreground="@drawable/tools_common_btn_corner_ripple"
+            android:padding="4dp"
+            app:tint="@color/tools_icon_status_color"
+            app:layout_constraintBottom_toBottomOf="@id/iv_add_draw_signature"
+            app:layout_constraintStart_toEndOf="@id/iv_add_pic_signature"
+            app:layout_constraintTop_toTopOf="@id/iv_add_draw_signature"
+            android:visibility="gone"
+            tools:visibility="visible"
+            app:srcCompat="@drawable/tools_ic_sign_none" />
+
+
         <com.compdfkit.tools.common.views.pdfproperties.colorlist.ColorListView
             android:id="@+id/color_list_view"
             android:layout_width="0dp"

+ 36 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_cert_digital_sign_list_fragment.xml

@@ -0,0 +1,36 @@
+<?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">
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:elevation="4dp"
+        android:title="@string/tools_signature_list"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recycler_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:visibility="invisible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar"
+        tools:listitem="@layout/tools_sign_cert_digital_sign_list_item" />
+
+
+    <ProgressBar
+        android:id="@+id/progress_bar"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar"
+        app:layout_constraintVertical_bias="0.4" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 98 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_cert_digital_sign_list_item.xml

@@ -0,0 +1,98 @@
+<?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="wrap_content"
+    android:layout_marginHorizontal="16dp"
+    android:layout_marginTop="16dp"
+    android:foreground="@drawable/tools_common_btn_rectangle_ripple"
+    android:background="@drawable/tools_style_signature_list_item_bg">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_icon"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:src="@drawable/tools_ic_digital_sign_is_valid"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="16dp"
+        android:textColor="@color/tools_text_color_primary"
+        android:textSize="15sp"
+        android:textStyle="bold"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@id/iv_icon"
+        app:layout_constraintTop_toTopOf="@id/iv_icon"
+        tools:text="Digital Signature Name" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_desc"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:layout_marginEnd="16dp"
+        android:lineSpacingMultiplier="1.2"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="@id/tv_sign_name"
+        app:layout_constraintTop_toBottomOf="@id/tv_sign_name"
+        tools:text="Valid signature, Signed by ComPDFKit xxxx@gmail.com " />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_date"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:layout_marginEnd="16dp"
+        android:lineSpacingMultiplier="1.2"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="@id/tv_sign_name"
+        app:layout_constraintTop_toBottomOf="@id/tv_sign_desc"
+        tools:text="Signature Time:2023 01 01 10:00:00" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_status"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="4dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="16dp"
+        android:lineSpacingMultiplier="1.2"
+        android:textColor="@color/tools_text_color_secondary"
+        android:textSize="12sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="@id/tv_sign_name"
+        app:layout_constraintTop_toBottomOf="@id/tv_sign_date"
+        tools:text="Authentication Successful" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_delete"
+        android:layout_width="35dp"
+        android:layout_height="35dp"
+        android:layout_margin="4dp"
+        android:background="@drawable/tools_common_oval_ripple"
+        android:padding="6dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/tools_ic_red_delete" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 28 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_attributes_fragment.xml

@@ -0,0 +1,28 @@
+<?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:background="@drawable/tools_annot_style_dialog_window_bg">
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:elevation="4dp"
+        android:title="@string/tools_digital_sign_attr"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recycler_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        tools:listitem="@layout/tools_sign_certificate_attributes_list_item"
+        />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 25 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_attributes_list_head_item.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginVertical="16dp"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_head"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/tools_version"
+        android:textStyle="bold"
+        android:textSize="18sp"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constraintStart_toStartOf="parent"
+        android:layout_marginStart="16dp"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintTop_toTopOf="parent" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 47 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_attributes_list_item.xml

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginVertical="16dp"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
+
+
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/guide"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        app:layout_constraintGuide_percent="0.35" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_attr_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/tools_version"
+        android:textStyle="bold"
+        android:textColor="@color/tools_text_color_secondary"
+        app:layout_constraintStart_toStartOf="parent"
+        android:layout_marginStart="16dp"
+        app:layout_constraintEnd_toEndOf="@id/guide"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_attr_value"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="8dp"
+        android:layout_marginTop="24dp"
+        android:textColor="@color/tools_text_color_secondary"
+        app:layout_constrainedWidth="true"
+        android:layout_marginEnd="16dp"
+        app:layout_constraintBaseline_toBaselineOf="@id/tv_attr_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/guide"
+        app:layout_constraintHorizontal_bias="0"
+        tools:text="V3" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 29 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_details_dialog.xml

@@ -0,0 +1,29 @@
+<?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:background="@drawable/tools_annot_style_dialog_window_bg">
+
+    <com.compdfkit.tools.common.views.CToolBar
+        android:id="@+id/tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?attr/actionBarSize"
+        android:elevation="4dp"
+        android:title="@string/tools_cert_details"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recycler_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintVertical_bias="0"
+        tools:itemCount="50"
+        app:layout_constrainedHeight="true"
+        tools:listitem="@layout/tools_sign_certificate_details_list_item"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 45 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_details_list_item.xml

@@ -0,0 +1,45 @@
+<?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:id="@+id/cl_root"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:foreground="@drawable/tools_common_btn_rectangle_ripple"
+    android:minHeight="32dp">
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_item_arrow"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginStart="4dp"
+        android:padding="8dp"
+        android:visibility="visible"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/tools_ic_right"
+        app:layout_constraintHorizontal_chainStyle="packed"
+        app:layout_constraintHorizontal_bias="0"
+        app:tint="@color/tools_text_color_primary"
+        app:layout_constraintEnd_toStartOf="@id/tv_item_title"
+        tools:visibility="visible" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_item_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dp"
+        android:paddingVertical="8dp"
+        android:textColor="@color/tools_text_color_secondary"
+        android:textSize="14sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toEndOf="@+id/iv_item_arrow"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="C=TW,O=KdanMobile,OU=Test..C=TW,TW,O=KdanMobile,OU=Test..C=TW," />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 144 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_digital_sign_info_fragment.xml

@@ -0,0 +1,144 @@
+<?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:background="@drawable/tools_annot_style_dialog_window_bg">
+
+    <include
+        android:id="@+id/tool_bar"
+        layout="@layout/tools_dialog_tool_bar" />
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_message"
+        android:layout_width="match_parent"
+        android:layout_height="28dp"
+        android:background="@color/tools_reader_setting_head_bg_color"
+        android:gravity="center_vertical"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:text="@string/tools_annot_signature"
+        android:textColor="@color/tools_text_color_primary"
+        android:textSize="12sp"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar" />
+
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/barrier"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:barrierDirection="end"
+        app:constraint_referenced_ids="tv_sign_founder_title,tv_date_of_sign_title" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_founder_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:text="@string/tools_signer"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_sign_message" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_founder"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:gravity="end"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBaseline_toBaselineOf="@id/tv_sign_founder_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="1"
+        app:layout_constraintStart_toEndOf="@id/barrier"
+        tools:text="ComPDFKitComPDFKitComPDFKitComPDFKitComPDFKitComPDFKit" />
+
+    <View
+        android:id="@+id/view_line"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:layout_marginTop="16dp"
+        android:background="@color/tools_item_dividing_line_color"
+        app:layout_constraintTop_toBottomOf="@id/tv_sign_founder" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_date_of_sign_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:text="@string/tools_signing_time"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/view_line" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_date_of_sign"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintBaseline_toBaselineOf="@id/tv_date_of_sign_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="1"
+        app:layout_constraintStart_toEndOf="@id/barrier"
+        tools:text="08/08/2023 15:12:04 " />
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_cert_auth_statement"
+        android:layout_width="match_parent"
+        android:layout_height="28dp"
+        android:layout_marginTop="16dp"
+        android:background="@color/tools_reader_setting_head_bg_color"
+        android:gravity="center_vertical"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:text="@string/tools_cert_auth_statement"
+        android:textColor="@color/tools_text_color_primary"
+        android:textSize="12sp"
+        app:layout_constraintTop_toBottomOf="@id/tv_date_of_sign_title" />
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_sign_statement_info"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="16dp"
+        android:layout_marginTop="16dp"
+        app:layout_constrainedWidth="true"
+        android:textColor="@color/tools_text_color_primary"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_cert_auth_statement"
+        tools:text="@string/tools_sign_is_valid_info" />
+
+    <androidx.appcompat.widget.AppCompatButton
+        android:id="@+id/btn_cert_detail"
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        android:layout_marginHorizontal="16dp"
+        android:layout_marginTop="32dp"
+        android:layout_marginBottom="40dp"
+        android:background="@drawable/tools_sign_cert_info_btn_bg"
+        android:foreground="@drawable/tools_common_btn_corner_ripple"
+        android:gravity="center"
+        android:text="@string/tools_view_cert"
+        android:textAllCaps="false"
+        android:textColor="@color/tools_color_accent"
+        android:textSize="16sp"
+        android:textStyle="bold"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_sign_statement_info"
+        app:layout_constraintVertical_bias="1" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 41 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_create_cert_digital_id_fragment.xml

@@ -0,0 +1,41 @@
+<?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"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/tools_annot_style_dialog_window_bg">
+
+    <include
+        android:id="@+id/tool_bar"
+        layout="@layout/tools_dialog_tool_bar" />
+
+    <ScrollView
+        android:id="@+id/scroll_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:fillViewport="true"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tool_bar">
+
+        <ViewSwitcher
+            android:id="@+id/view_switcher"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:inAnimation="@anim/tools_slide_in_right"
+            android:outAnimation="@anim/tools_slide_out_left">
+
+            <include
+                layout="@layout/tools_sign_create_cert_digital_id_info_layout"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
+
+            <include
+                layout="@layout/tools_sign_create_cert_digital_id_save_layout"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent" />
+        </ViewSwitcher>
+    </ScrollView>
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 0 - 0
ComPDFKit_Tools/src/main/res/layout/tools_sign_create_cert_digital_id_info_layout.xml


Some files were not shown because too many files changed in this diff