Преглед изворни кода

PDFTool(Android) - 1.综合Demo新增数字签名模块

liuxiaolong пре 1 година
родитељ
комит
e0830525f1

+ 3 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/forms/pdfproperties/pdfsign/CustomSignatureWidgetImpl.java

@@ -24,7 +24,9 @@ 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;
 
-
+/**
+ * Form signature form, electronic signature click interaction
+ */
 public class CustomSignatureWidgetImpl extends CPDFSignatureWidgetImpl {
 
     @Override

+ 181 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/forms/pdfproperties/pdfsign/SignatureWidgetImpl.java

@@ -0,0 +1,181 @@
+package com.compdfkit.tools.forms.pdfproperties.pdfsign;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Environment;
+import android.text.TextUtils;
+
+import androidx.fragment.app.FragmentActivity;
+
+import com.compdfkit.core.annotation.CPDFImageScaleType;
+import com.compdfkit.core.annotation.form.CPDFSignatureWidget;
+import com.compdfkit.core.signature.CPDFDigitalSigConfig;
+import com.compdfkit.core.signature.CPDFSignature;
+import com.compdfkit.core.signature.CPDFX509;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.common.utils.CToastUtil;
+import com.compdfkit.tools.common.utils.image.CBitmapUtil;
+import com.compdfkit.tools.common.views.directory.CFileDirectoryDialog;
+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;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.CStyleUIParams;
+import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.manager.CStyleManager;
+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;
+import java.util.UUID;
+
+
+/**
+ * Form signature form click interaction is implemented. This object contains two signature interactions: electronic signature and digital signature.
+ * If you only need electronic signature interaction, please check
+ * @see CustomSignatureWidgetImpl
+ * If you only need digital signature interaction, please check
+ * @see com.compdfkit.tools.signature.pdfproperties.pdfsign.CDigitalSignatureWidgetImpl
+ */
+public class SignatureWidgetImpl extends CPDFSignatureWidgetImpl {
+
+    @Override
+    public void onSignatureWidgetFocused(CPDFSignatureWidget cpdfSignatureWidget) {
+        if (!cpdfSignatureWidget.isSigned()) {
+            // unsigned
+            fillDigitalSign(cpdfSignatureWidget);
+            return;
+        }
+
+        // The form has been signed
+        CPDFSignature signature = readerView.getPDFDocument().getPdfSignature(cpdfSignatureWidget);
+        // Determine whether it is a digital signature
+        if (signature.isDigitalSigned()){
+            // digital signature
+            showDigitalSignInfo(signature);
+        } else {
+            // electronic signature
+            fillElectronicSignature();
+        }
+    }
+
+
+    /**
+     * A list of created electronic signature styles pops up,
+     * and you can also choose to create a new signature style.
+     */
+    private void fillElectronicSignature(){
+        CStyleManager styleManager = new CStyleManager(this, pageView);
+        CStyleDialogFragment styleDialogFragment = CStyleDialogFragment.newInstance(styleManager.getStyle(CStyleType.FORM_SIGNATURE_FIELDS));
+        CStyleUIParams styleUiParams = CStyleUIParams.defaultStyle(CStyleType.FORM_SIGNATURE_FIELDS);
+        styleDialogFragment.setStyleUiConfig(styleUiParams);
+        styleDialogFragment.setStyleDialogDismissListener(() -> {
+            CAnnotStyle annotStyle = styleDialogFragment.getAnnotStyle();
+            if (!TextUtils.isEmpty(annotStyle.getImagePath())) {
+                try {
+                    Bitmap bitmap = CBitmapUtil.decodeBitmap(annotStyle.getImagePath());
+                    ((CPDFSignatureWidget) pdfAnnotation).updateApWithBitmap(bitmap, CPDFImageScaleType.SCALETYPE_fitCenter);
+                    refresh();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+        if (readerView.getContext() instanceof FragmentActivity) {
+            styleDialogFragment.show(((FragmentActivity) readerView.getContext()).getSupportFragmentManager(), "styleDialog");
+        }
+    }
+
+    private void fillDigitalSign(CPDFSignatureWidget cpdfSignatureWidget){
+        CPDFSelectDigitalSignatureDialog dialog = CPDFSelectDigitalSignatureDialog.newInstance();
+        dialog.setCertDigitalSignListener((certFilePath, certPassword, signImagePath) -> {
+            CPDFX509 cpdfx509 = CertificateDigitalDatas.getCertInfo(certFilePath, certPassword);
+            if (cpdfx509 == null) {
+                return;
+            }
+            String dn = CertificateDigitalDatas.getOwnerContent(cpdfx509.getCertInfo().getSubject(), ",");
+            CDigitalSignStylePreviewDialog previewDialog = CDigitalSignStylePreviewDialog.newInstance(signImagePath, cpdfx509.getCertInfo().getSubject().getCommonName(), dn);
+            previewDialog.setResultDigitalSignListener((imagePath, config, location, reason) -> {
+                try {
+                    Context context = readerView.getContext();
+                    CFileDirectoryDialog directoryDialog = CFileDirectoryDialog.newInstance(
+                            Environment.getExternalStorageDirectory().getAbsolutePath(),
+                            context.getString(R.string.tools_select_folder),
+                            context.getString(R.string.tools_save_to_this_directory)
+                    );
+                    directoryDialog.setSelectFolderListener(dir -> {
+                        signDocument(cpdfSignatureWidget, config, location, reason, certFilePath, certPassword, dir);
+                    });
+                    if (readerView.getContext() instanceof FragmentActivity) {
+                        directoryDialog.show(((FragmentActivity) readerView.getContext()).getSupportFragmentManager(), "selectFolderDialog");
+                    }
+                } 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");
+        }
+    }
+
+    /**
+     * View digital signature and signature certificate related information
+     * @param signature
+     */
+    private void showDigitalSignInfo(CPDFSignature signature){
+        CertDigitalSignInfoDialog signInfoDialog = CertDigitalSignInfoDialog.newInstance();
+        signInfoDialog.setDocument(readerView.getPDFDocument());
+        signInfoDialog.setPDFSignature(signature);
+        if (readerView.getContext() instanceof FragmentActivity) {
+            signInfoDialog.show(((FragmentActivity) readerView.getContext()).getSupportFragmentManager(), "signInfoDialog");
+        }
+    }
+
+    private void signDocument(CPDFSignatureWidget cpdfSignatureWidget,
+                              CPDFDigitalSigConfig config,
+                              String location,
+                              String reason,
+                              String certFilePath,
+                              String certPassword,
+                              String saveDir) {
+
+        String uuid = UUID.randomUUID().toString().substring(0, 4);
+        String fileName = readerView.getPDFDocument().getFileName();
+        File saveFile = new File(saveDir + File.separator + fileName + "_" + uuid, readerView.getPDFDocument().getFileName());
+        saveFile.getParentFile().mkdirs();
+
+        boolean updateSignApResult = cpdfSignatureWidget.updateApWithDigitalSigConfig(config);
+        if (!updateSignApResult){
+            return;
+        }
+        CPDFX509 cpdfx509 = CertificateDigitalDatas.getCertInfo(certFilePath, certPassword);
+        if (cpdfx509 != null) {
+            if (!cpdfx509.checkCertificateIsTrusted(readerView.getContext())) {
+                cpdfx509.addToTrustedCertificates(readerView.getContext());
+            }
+        }
+
+        // sign this pdf document
+        boolean result = CertificateDigitalDatas.writeSignature(readerView.getPDFDocument(),
+                cpdfSignatureWidget, location, reason,
+                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());
+            }
+        } else {
+            CToastUtil.showToast(readerView.getContext(), "Signature Fail");
+        }
+    }
+
+}

+ 1 - 1
ComPDFKit_Tools/src/main/res/layout/tools_sign_certificate_digital_sign_info_fragment.xml

@@ -131,7 +131,7 @@
                 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"

+ 2 - 1
DigitalSignature/src/main/AndroidManifest.xml

@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:tools="http://schemas.android.com/tools"
+    xmlns:android="http://schemas.android.com/apk/res/android">
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

+ 9 - 1
PDFViewer/src/main/AndroidManifest.xml

@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
@@ -21,6 +22,13 @@
 
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+
+
+            <intent-filter tools:ignore="AppLinkUrlError">
+                <action android:name="android.intent.action.VIEW"/>
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="application/pdf"/>
+            </intent-filter>
         </activity>
         <meta-data
             android:name="compdfkit_key"

+ 28 - 1
PDFViewer/src/main/java/com/compdfkit/pdfviewer/CSampleScreenManager.java

@@ -14,7 +14,7 @@ import com.compdfkit.tools.common.views.pdfview.CPreviewMode;
 public class CSampleScreenManager {
     private PdfSampleActivityBinding binding;
 
-    private CFillScreenManager fillScreenManager = new CFillScreenManager();
+    public CFillScreenManager fillScreenManager = new CFillScreenManager();
 
     private boolean isFillScreen;
 
@@ -28,6 +28,7 @@ public class CSampleScreenManager {
         fillScreenManager.bindRightToolViewList(binding.pdfView.slideBar);
         fillScreenManager.bindBottomToolViewList(binding.pdfView.indicatorView);
         fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
+        fillScreenManager.bindBottomToolViewList(binding.signatureToolBar);
     }
 
 
@@ -40,18 +41,28 @@ public class CSampleScreenManager {
             binding.annotationToolBar.setVisibility(View.VISIBLE);
             binding.editToolBar.setVisibility(View.GONE);
             binding.formToolBar.setVisibility(View.GONE);
+            binding.signatureToolBar.setVisibility(View.GONE);
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         } else if (mode == CPreviewMode.Edit) {
             fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
             binding.annotationToolBar.setVisibility(View.GONE);
             binding.editToolBar.setVisibility(View.VISIBLE);
             binding.formToolBar.setVisibility(View.GONE);
+            binding.signatureToolBar.setVisibility(View.GONE);
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         } else if (mode == CPreviewMode.Form){
             fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
             binding.annotationToolBar.setVisibility(View.GONE);
             binding.editToolBar.setVisibility(View.GONE);
             binding.formToolBar.setVisibility(View.VISIBLE);
+            binding.signatureToolBar.setVisibility(View.GONE);
+            constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
+        } else if (mode == CPreviewMode.Signature){
+            fillScreenManager.bindBottomToolViewList(binding.flBottomToolBar);
+            binding.annotationToolBar.setVisibility(View.GONE);
+            binding.editToolBar.setVisibility(View.GONE);
+            binding.formToolBar.setVisibility(View.GONE);
+            binding.signatureToolBar.setVisibility(View.VISIBLE);
             constraintSetUtils.showFromBottom(constraintSet, binding.flBottomToolBar);
         }
         constraintSetUtils.apply(constraintSet, binding.getRoot());
@@ -91,6 +102,7 @@ public class CSampleScreenManager {
             //enter full screen
             constraintSetUtils.hideFromTop(constraintSet, binding.flTool);
             constraintSetUtils.hideFromBottom(constraintSet, binding.flBottomToolBar);
+            constraintSetUtils.hideFromBottom(constraintSet, binding.signatureToolBar);
             isFillScreen = true;
         } else {
             //enter normal state
@@ -101,8 +113,23 @@ public class CSampleScreenManager {
             }else {
                 constraintSetUtils.hideFromBottom(constraintSet, binding.flBottomToolBar);
             }
+            if (fillScreenManager.topToolViewList.contains(binding.signStatusView)) {
+                constraintSetUtils.show(constraintSet, binding.signStatusView);
+            }else {
+                constraintSetUtils.hide(constraintSet, binding.signStatusView);
+            }
             isFillScreen = false;
         }
         constraintSetUtils.apply(constraintSet, binding.getRoot());
     }
+
+    public void constraintShow(View view){
+        constraintSetUtils.show(constraintSet, view);
+        constraintSetUtils.apply(constraintSet, binding.getRoot());
+    }
+
+    public void constraintHide(View view){
+        constraintSetUtils.hide(constraintSet, view);
+        constraintSetUtils.apply(constraintSet, binding.getRoot());
+    }
 }

+ 76 - 7
PDFViewer/src/main/java/com/compdfkit/pdfviewer/MainActivity.java

@@ -24,6 +24,10 @@ import androidx.activity.result.ActivityResultLauncher;
 import androidx.annotation.Nullable;
 
 import com.compdfkit.core.annotation.CPDFAnnotation;
+import com.compdfkit.core.annotation.form.CPDFComboboxWidget;
+import com.compdfkit.core.annotation.form.CPDFListboxWidget;
+import com.compdfkit.core.annotation.form.CPDFSignatureWidget;
+import com.compdfkit.core.document.CPDFDocument;
 import com.compdfkit.core.edit.CPDFEditManager;
 import com.compdfkit.pdfviewer.databinding.PdfSampleActivityBinding;
 import com.compdfkit.tools.common.basic.activity.CBasicPDFActivity;
@@ -34,6 +38,7 @@ import com.compdfkit.tools.common.utils.activitycontracts.CSelectPDFDocumentResu
 import com.compdfkit.tools.common.utils.annotation.CPDFAnnotationManager;
 import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
 import com.compdfkit.tools.common.utils.task.CExtractAssetFileTask;
+import com.compdfkit.tools.common.utils.threadpools.CThreadPoolUtils;
 import com.compdfkit.tools.common.utils.window.CPopupMenuWindow;
 import com.compdfkit.tools.common.views.pdfbota.CPDFBOTA;
 import com.compdfkit.tools.common.views.pdfbota.CPDFBotaDialogFragment;
@@ -43,8 +48,16 @@ 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;
 import com.compdfkit.tools.common.views.pdfproperties.pdfstyle.manager.CStyleManager;
+import com.compdfkit.tools.common.views.pdfview.CPDFViewCtrl;
 import com.compdfkit.tools.common.views.pdfview.CPreviewMode;
 import com.compdfkit.tools.contenteditor.CPDFEditPage;
+import com.compdfkit.tools.forms.pdfproperties.pdfcombobox.CustomComboBoxWidgetImpl;
+import com.compdfkit.tools.forms.pdfproperties.pdflistbox.CustomListBoxWidgetImpl;
+import com.compdfkit.tools.forms.pdfproperties.pdfsign.CustomSignatureWidgetImpl;
+import com.compdfkit.tools.forms.pdfproperties.pdfsign.SignatureWidgetImpl;
+import com.compdfkit.tools.signature.CertificateDigitalDatas;
+import com.compdfkit.tools.signature.bean.CPDFDocumentSignInfo;
+import com.compdfkit.tools.signature.info.signlist.CPDFCertDigitalSignListDialog;
 import com.compdfkit.tools.viewer.pdfsearch.CSearchResultDialogFragment;
 import com.compdfkit.ui.contextmenu.IContextMenuShowListener;
 import com.compdfkit.ui.proxy.form.CPDFComboboxWidgetImpl;
@@ -77,13 +90,13 @@ public class MainActivity extends CBasicPDFActivity {
                 readerView.getContextMenuShowListener().dismissContextMenu();
             }
             CFileUtils.takeUriPermission(this, uri);
-            resetContextMenu(binding.pdfView, CPreviewMode.Viewer);
             binding.pdfView.resetAnnotationType();
             binding.formToolBar.reset();
             binding.editToolBar.resetStatus();
+            binding.signatureToolBar.reset();
             setPreviewMode(CPreviewMode.Viewer);
-            binding.pdfToolBar.selectMode(CPreviewMode.Viewer);
             screenManager.changeWindowStatus(CPreviewMode.Viewer);
+            screenManager.constraintHide(binding.signStatusView);
             binding.pdfView.openPDF(uri, null, () -> {
                 binding.editToolBar.setEditMode(false);
             });
@@ -103,17 +116,24 @@ public class MainActivity extends CBasicPDFActivity {
         initAnnotToolbar();
         initFormToolbar();
         initEditBar();
+        initSignatureToolbar();
         setPreviewMode(CPreviewMode.Viewer);
         onDoNext();
     }
 
     private void initPDFView() {
-        CExtractAssetFileTask.extract(this, QUICK_START_GUIDE, QUICK_START_GUIDE, (filePath) -> {
-                    binding.pdfView.openPDF(filePath);
-                    binding.editToolBar.setEditMode(false);
+        if (getIntent().getData() != null) {
+            CFileUtils.takeUriPermission(this, getIntent().getData());
+            binding.pdfView.openPDF(getIntent().getData());
+            binding.editToolBar.setEditMode(false);
+        }else {
+            CExtractAssetFileTask.extract(this, QUICK_START_GUIDE, QUICK_START_GUIDE, (filePath) -> {
+                        binding.pdfView.openPDF(filePath);
+                        binding.editToolBar.setEditMode(false);
+                    }
+            );
+        }
 
-                }
-        );
         binding.pdfView.getCPdfReaderView().setMinScaleEnable(false);
         resetContextMenu(binding.pdfView, CPreviewMode.Viewer);
         initAnnotationAttr(binding.pdfView);
@@ -188,6 +208,9 @@ public class MainActivity extends CBasicPDFActivity {
                 case Form:
                     binding.pdfView.getCPdfReaderView().setViewMode(CPDFReaderView.ViewMode.FORM);
                     break;
+                case Signature:
+                    binding.pdfView.getCPdfReaderView().setViewMode(CPDFReaderView.ViewMode.VIEW);
+                    break;
                 default:
                     break;
             }
@@ -198,6 +221,7 @@ public class MainActivity extends CBasicPDFActivity {
         binding.pdfToolBar.addMode(CPreviewMode.Annotation);
         binding.pdfToolBar.addMode(CPreviewMode.Edit);
         binding.pdfToolBar.addMode(CPreviewMode.Form);
+        binding.pdfToolBar.addMode(CPreviewMode.Signature);
         binding.pdfToolBar.setPreviewModeChangeListener(this::setPreviewMode);
         binding.pdfToolBar.setSearchBtnClickListener(v -> {
             if (binding.pdfView.getCPdfReaderView().getEditManager().isEditMode()) {
@@ -377,6 +401,44 @@ public class MainActivity extends CBasicPDFActivity {
         });
     }
 
+    private void initSignatureToolbar() {
+        binding.signStatusView.initWithPDFView(binding.pdfView);
+        binding.signStatusView.getBtnDetails().setOnClickListener(v -> {
+            CPDFCertDigitalSignListDialog signListDialog = CPDFCertDigitalSignListDialog.newInstance();
+            signListDialog.initWithPDFView(binding.pdfView);
+            signListDialog.setDialogDismissListener(this::verifyDocumentSignStatus);
+            signListDialog.show(getSupportFragmentManager(), "signListDialog");
+        });
+        binding.signatureToolBar.initWithPDFView(binding.pdfView);
+        binding.signatureToolBar.getVerifySignButton().setOnClickListener(v -> {
+            verifyDocumentSignStatus();
+        });
+    }
+
+    /**
+     *
+     */
+    private void verifyDocumentSignStatus() {
+        CPDFDocument document = binding.pdfView.getCPdfReaderView().getPDFDocument();
+        if (CertificateDigitalDatas.hasDigitalSignature(document)) {
+            CThreadPoolUtils.getInstance().executeIO(() -> {
+                CPDFDocumentSignInfo status = CertificateDigitalDatas.verifyDocumentSignStatus(document);
+                runOnUiThread(() -> {
+                    if (status != null) {
+                        binding.signStatusView.setStatus(status);
+                        screenManager.fillScreenManager.bindTopToolView(binding.signStatusView);
+                        screenManager.constraintShow(binding.signStatusView);
+                    }
+                });
+            });
+        } else {
+            if (binding.signStatusView.getVisibility() == View.VISIBLE) {
+                screenManager.fillScreenManager.removeAndHideToolView(binding.signStatusView);
+                screenManager.constraintHide(binding.signStatusView);
+            }
+        }
+    }
+
     private void selectDocument() {
         if (binding.pdfToolBar.getMode() == CPreviewMode.Edit) {
             binding.pdfView.exitEditMode();
@@ -458,6 +520,13 @@ public class MainActivity extends CBasicPDFActivity {
         }
     }
 
+    @Override
+    protected void registerFormHelper(CPDFViewCtrl pdfView) {
+        super.registerFormHelper(pdfView);
+        pdfView.getCPdfReaderView().getAnnotImplRegistry()
+                // Register the CustomSignatureWidgetImpl.class to implement a custom dropdown options popup.
+                .registImpl(CPDFSignatureWidget.class, SignatureWidgetImpl.class);
+    }
 
     @Override
     public void onBackPressed() {

+ 17 - 1
PDFViewer/src/main/res/layout/pdf_sample_activity.xml

@@ -58,7 +58,16 @@
         android:visibility="gone"
         app:layout_constraintTop_toBottomOf="@id/fl_tool" />
 
-
+    <com.compdfkit.tools.signature.verify.CVerifySignStatusView
+        android:id="@+id/sign_status_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/fl_tool"
+        android:visibility="gone"
+        tools:visibility="visible"
+        app:status="valid" />
 
     <FrameLayout
         android:id="@+id/fl_bottom_tool_bar"
@@ -86,6 +95,13 @@
             android:layout_height="?android:attr/actionBarSize"
             android:visibility="gone"
             />
+
+        <com.compdfkit.tools.signature.CSignatureToolBar
+            android:id="@+id/signature_tool_bar"
+            android:layout_width="match_parent"
+            android:visibility="gone"
+            android:layout_height="?android:attr/actionBarSize"
+            app:layout_constraintBottom_toBottomOf="parent" />
     </FrameLayout>