瀏覽代碼

PDFTool(Android) - 进入阅读界面获取存储权限,避免通过ACTION_GET_CONTENT uri无写入权限

liuxiaolong 1 年之前
父節點
當前提交
b3fb3730d8

+ 67 - 69
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/pdf/CPDFDocumentFragment.java

@@ -23,6 +23,7 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,6 +32,7 @@ import android.widget.FrameLayout;
 
 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.constraintlayout.widget.ConstraintLayout;
@@ -50,13 +52,11 @@ import com.compdfkit.tools.common.contextmenu.CPDFContextMenuHelper;
 import com.compdfkit.tools.common.pdf.config.CPDFConfiguration;
 import com.compdfkit.tools.common.pdf.config.ToolbarConfig;
 import com.compdfkit.tools.common.utils.CFileUtils;
-import com.compdfkit.tools.common.utils.CLog;
 import com.compdfkit.tools.common.utils.CPermissionUtil;
 import com.compdfkit.tools.common.utils.CToastUtil;
 import com.compdfkit.tools.common.utils.activitycontracts.CSelectPDFDocumentResultContract;
 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.CPDFToolBar;
@@ -104,15 +104,9 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
 
     public static final String EXTRA_CONFIGURATION = "extra_configuration";
 
-    /**
-     * assets folder pdf file
-     */
-    public static final String QUICK_START_GUIDE = "ComPDFKit_Sample_File_Android.pdf";
-
+    protected CSampleScreenManager screenManager = new CSampleScreenManager();
 
-    CSampleScreenManager screenManager = new CSampleScreenManager();
-
-    private CPDFConfiguration cpdfConfiguration;
+    protected CPDFConfiguration cpdfConfiguration;
 
     public ConstraintLayout clRoot;
 
@@ -168,7 +162,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
             if (readerView != null && readerView.getEditManager() != null) {
                 readerView.getEditManager().endEdit();
             }
-            if (readerView.getContextMenuShowListener() != null) {
+            if (readerView != null && readerView.getContextMenuShowListener() != null) {
                 readerView.getContextMenuShowListener().dismissContextMenu();
             }
             CFileUtils.takeUriPermission(getContext(), uri);
@@ -179,9 +173,13 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
             setPreviewMode(cpdfConfiguration.modeConfig.initialViewMode);
             screenManager.changeWindowStatus(cpdfConfiguration.modeConfig.initialViewMode);
             screenManager.constraintHide(signStatusView);
-            pdfView.openPDF(uri, null, () -> {
-                editToolBar.setEditMode(false);
-            });
+            pdfView.openPDF(uri, null, () -> editToolBar.setEditMode(false));
+        }
+    });
+
+    private ActivityResultLauncher<Intent> requestManageStoragePermission = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
+        if (CPermissionUtil.hasStoragePermissions(getContext())) {
+            initDocument(null);
         }
     });
 
@@ -197,9 +195,8 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
                 } else {
                     onBackPressedCallback.setEnabled(false);
                     if (pdfView != null) {
-                        pdfView.savePDF((filePath, pdfUri) -> {
-                            requireActivity().onBackPressed();
-                        }, e -> {
+                        pdfView.savePDF((filePath, pdfUri) -> requireActivity().onBackPressed(), e -> {
+                            e.printStackTrace();
                             requireActivity().onBackPressed();
                         });
                     }
@@ -360,16 +357,14 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
             for (ToolbarConfig.ToolbarAction androidAvailableAction : toolbarConfig.androidAvailableActions) {
                 switch (androidAvailableAction) {
                     case Thumbnail:
-                        pdfToolBar.addAction(R.drawable.tools_ic_thumbnail, v -> {
-                            showPageEdit(pdfView, false, () -> {
-                                if (curEditMode > CPDFEditPage.LoadNone && pdfToolBar.getMode() == CPreviewMode.Edit) {
-                                    CPDFEditManager editManager = pdfView.getCPdfReaderView().getEditManager();
-                                    if (!editManager.isEditMode()) {
-                                        editManager.beginEdit(curEditMode);
-                                    }
+                        pdfToolBar.addAction(R.drawable.tools_ic_thumbnail, v -> showPageEdit(pdfView, false, () -> {
+                            if (curEditMode > CPDFEditPage.LoadNone && pdfToolBar.getMode() == CPreviewMode.Edit) {
+                                CPDFEditManager editManager = pdfView.getCPdfReaderView().getEditManager();
+                                if (!editManager.isEditMode()) {
+                                    editManager.beginEdit(curEditMode);
                                 }
-                            });
-                        });
+                            }
+                        }));
                         break;
                     case Search:
                         pdfToolBar.addAction(R.drawable.tools_ic_search, v -> {
@@ -416,9 +411,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
                         break;
 
                     case Menu:
-                        pdfToolBar.addAction(R.drawable.tools_ic_more, v -> {
-                            showToolbarMenuDialog(v);
-                        });
+                        pdfToolBar.addAction(R.drawable.tools_ic_more, this::showToolbarMenuDialog);
                         break;
                     default:
                         break;
@@ -428,7 +421,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
     }
 
     private void requestStoragePermissions(CRequestPermissionListener permissionListener) {
-        if (Build.VERSION.SDK_INT >= 33) {
+        if (Build.VERSION.SDK_INT >= CPermissionUtil.VERSION_TIRAMISU) {
             CPermissionUtil.openManageAllFileAppSettings(getContext());
         } else {
             multiplePermissionResultLauncher.launch(STORAGE_PERMISSIONS, result -> {
@@ -536,9 +529,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
             signListDialog.show(getChildFragmentManager(), "signListDialog");
         });
         signatureToolBar.initWithPDFView(pdfView);
-        signatureToolBar.getVerifySignButton().setOnClickListener(v -> {
-            verifyDocumentSignStatus();
-        });
+        signatureToolBar.getVerifySignButton().setOnClickListener(v -> verifyDocumentSignStatus());
     }
 
     private void showToolbarMenuDialog(View anchorView) {
@@ -553,21 +544,17 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
             for (ToolbarConfig.MenuAction menuAction : menuActions) {
                 switch (menuAction) {
                     case ViewSettings:
-                        menuWindow.addItem(R.drawable.tools_ic_preview_settings, R.string.tools_view_setting, v1 -> {
-                            showDisplaySettings(pdfView);
-                        });
+                        menuWindow.addItem(R.drawable.tools_ic_preview_settings, R.string.tools_view_setting, v1 -> showDisplaySettings(pdfView));
                         break;
                     case DocumentEditor:
-                        menuWindow.addItem(R.drawable.tools_page_edit, R.string.tools_page_edit_toolbar_title, v1 -> {
-                            showPageEdit(pdfView, true, () -> {
-                                if (curEditMode > CPDFEditPage.LoadNone && pdfToolBar.getMode() == CPreviewMode.Edit) {
-                                    CPDFEditManager editManager = pdfView.getCPdfReaderView().getEditManager();
-                                    if (!editManager.isEditMode()) {
-                                        editManager.beginEdit(curEditMode);
-                                    }
+                        menuWindow.addItem(R.drawable.tools_page_edit, R.string.tools_page_edit_toolbar_title, v1 -> showPageEdit(pdfView, true, () -> {
+                            if (curEditMode > CPDFEditPage.LoadNone && pdfToolBar.getMode() == CPreviewMode.Edit) {
+                                CPDFEditManager editManager = pdfView.getCPdfReaderView().getEditManager();
+                                if (!editManager.isEditMode()) {
+                                    editManager.beginEdit(curEditMode);
                                 }
-                            });
-                        });
+                            }
+                        }));
                         break;
                     case Security:
                         menuWindow.addItem(R.drawable.tools_ic_add_security, R.string.tools_security, v1 -> {
@@ -578,9 +565,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
                             if (document.getPermissions() == CPDFDocument.PDFDocumentPermissions.PDFDocumentPermissionsUser) {
                                 CInputOwnerPwdDialog inputOwnerPwdDialog = CInputOwnerPwdDialog.newInstance();
                                 inputOwnerPwdDialog.setDocument(document);
-                                inputOwnerPwdDialog.setCancelClickListener(v2 -> {
-                                    inputOwnerPwdDialog.dismiss();
-                                });
+                                inputOwnerPwdDialog.setCancelClickListener(v2 -> inputOwnerPwdDialog.dismiss());
                                 inputOwnerPwdDialog.setConfirmClickListener(ownerPassword -> {
                                     document.reload(ownerPassword);
                                     showSettingEncryptionDialog();
@@ -610,18 +595,12 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
                         });
                         break;
                     case DocumentInfo:
-                        menuWindow.addItem(R.drawable.tools_ic_document_info, R.string.tools_document_info, v1 -> {
-                            showDocumentInfo(pdfView);
-                        });
+                        menuWindow.addItem(R.drawable.tools_ic_document_info, R.string.tools_document_info, v1 -> showDocumentInfo(pdfView));
                         break;
                     case Save:
-                        menuWindow.addItem(R.drawable.tools_ic_menu_save, R.string.tools_save, v1 -> {
-                            pdfView.savePDF((filePath, pdfUri) -> {
-                                CToastUtil.showLongToast(getContext(), R.string.tools_save_success);
-                            }, e -> {
+                        menuWindow.addItem(R.drawable.tools_ic_menu_save, R.string.tools_save, v1 -> pdfView.savePDF((filePath, pdfUri) -> CToastUtil.showLongToast(getContext(), R.string.tools_save_success), e -> {
 
-                            });
-                        });
+                        }));
                         break;
                     case Share:
                         menuWindow.addItem(R.drawable.tools_ic_share, R.string.tools_share, v1 -> {
@@ -641,15 +620,9 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
                     case Flattened:
                         menuWindow.addItem(R.drawable.tools_ic_flattened, R.string.tools_flattened, v1 -> {
                             if (CPermissionUtil.hasStoragePermissions(getContext())) {
-                                pdfView.savePDF((filePath, pdfUri) -> {
-                                    flattenedPDF();
-                                }, e -> flattenedPDF());
+                                pdfView.savePDF((filePath, pdfUri) -> flattenedPdf(), e -> flattenedPdf());
                             } else {
-                                requestStoragePermissions(() -> {
-                                    pdfView.savePDF((filePath, pdfUri) -> {
-                                        flattenedPDF();
-                                    }, e -> flattenedPDF());
-                                });
+                                requestStoragePermissions(() -> pdfView.savePDF((filePath, pdfUri) -> flattenedPdf(), e -> flattenedPdf()));
                             }
                         });
                         break;
@@ -662,7 +635,7 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
         menuWindow.showAsDropDown(anchorView);
     }
 
-    private void flattenedPDF() {
+    private void flattenedPdf() {
         CFileDirectoryDialog directoryDialog = CFileDirectoryDialog.newInstance(
                 Environment.getExternalStorageDirectory().getAbsolutePath(),
                 getContext().getString(R.string.tools_select_folder),
@@ -756,7 +729,32 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
     }
 
     private void onDoNext() {
-        multiplePermissionResultLauncher.launch(STORAGE_PERMISSIONS);
+        if (CPermissionUtil.hasStoragePermissions(getContext())) {
+            return;
+        }
+        if (Build.VERSION.SDK_INT >= CPermissionUtil.VERSION_TIRAMISU) {
+            requestManageStoragePermission.launch(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION));
+        } else if (Build.VERSION.SDK_INT >= CPermissionUtil.VERSION_R) {
+            multiplePermissionResultLauncher.launch(STORAGE_PERMISSIONS, result -> {
+                if (CPermissionUtil.hasStoragePermissions(getContext())) {
+                    initDocument(null);
+                } else {
+                    if (!Environment.isExternalStorageManager()) {
+                        requestManageStoragePermission.launch(new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION));
+                    }
+                }
+            });
+        } else {
+            multiplePermissionResultLauncher.launch(STORAGE_PERMISSIONS, result -> {
+                if (CPermissionUtil.hasStoragePermissions(getContext())) {
+                    initDocument(null);
+                } else {
+                    if (!CPermissionUtil.shouldShowRequestPermissionRationale(requireActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+                        showPermissionsRequiredDialog();
+                    }
+                }
+            });
+        }
     }
 
     private void showSettingEncryptionDialog() {
@@ -786,13 +784,13 @@ public class CPDFDocumentFragment extends CBasicPDFFragment {
 
     private void parseConfiguration() {
         if (getArguments() != null && getArguments().containsKey(EXTRA_CONFIGURATION)) {
-            if (Build.VERSION.SDK_INT >= 33) {
+            if (Build.VERSION.SDK_INT >= CPermissionUtil.VERSION_TIRAMISU) {
                 cpdfConfiguration = getArguments().getSerializable(EXTRA_CONFIGURATION, CPDFConfiguration.class);
             } else {
                 cpdfConfiguration = (CPDFConfiguration) getArguments().getSerializable(EXTRA_CONFIGURATION);
             }
         }
-        if (cpdfConfiguration == null){
+        if (cpdfConfiguration == null) {
             cpdfConfiguration = CPDFConfigurationUtils.normalConfig(getContext(), "tools_default_configuration.json");
         }
     }

+ 3 - 0
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CFileUtils.java

@@ -286,6 +286,7 @@ public class CFileUtils {
         intent.setType("application/pdf");
         intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
         return intent;
     }
 
@@ -308,6 +309,8 @@ public class CFileUtils {
     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);
+            context.grantUriPermission(context.getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
         }catch (Exception e){
 
         }

+ 16 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/utils/CPermissionUtil.java

@@ -28,6 +28,10 @@ import com.compdfkit.tools.common.utils.dialog.CAlertDialog;
 
 public class CPermissionUtil {
 
+    public static final int VERSION_TIRAMISU = 33;
+    public static final int VERSION_S_V2 = 32;
+    public static final int VERSION_R = 30;
+
     public final static String[] STORAGE_PERMISSIONS = new String[]{
             android.Manifest.permission.READ_EXTERNAL_STORAGE,
             android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
@@ -37,9 +41,20 @@ public class CPermissionUtil {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
             return true;
         }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+        if (Build.VERSION.SDK_INT >= VERSION_TIRAMISU) {
             return Environment.isExternalStorageManager();
         }
+        if (Build.VERSION.SDK_INT >= VERSION_R) {
+            boolean hasPermission = true;
+            for (String perm : STORAGE_PERMISSIONS) {
+                if (ContextCompat.checkSelfPermission(context, perm)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    hasPermission = false;
+                    break;
+                }
+            }
+            return Environment.isExternalStorageManager() && hasPermission;
+        }
         for (String perm : STORAGE_PERMISSIONS) {
             if (ContextCompat.checkSelfPermission(context, perm)
                     != PackageManager.PERMISSION_GRANTED) {

+ 15 - 1
ComPDFKit_Tools/src/main/java/com/compdfkit/tools/common/views/pdfview/CPDFViewCtrl.java

@@ -10,6 +10,7 @@
 package com.compdfkit.tools.common.views.pdfview;
 
 import android.animation.ObjectAnimator;
+import android.app.Dialog;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.net.Uri;
@@ -25,6 +26,8 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.core.content.ContextCompat;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.interpolator.view.animation.FastOutLinearInInterpolator;
 
@@ -338,6 +341,12 @@ public class CPDFViewCtrl extends ConstraintLayout implements IReaderViewCallbac
     }
 
     public void showWritePermissionsDialog(CPDFDocument document) {
+        if (getContext() instanceof FragmentActivity) {
+            Fragment rwPermissionDialog = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag("rwPermissionDialog");
+            if (rwPermissionDialog != null && rwPermissionDialog instanceof DialogFragment){
+                ((DialogFragment) rwPermissionDialog).dismiss();
+            }
+        }
         CAlertDialog alertDialog = CAlertDialog.newInstance(
                 getContext().getString(R.string.tools_warning),
                 getContext().getString(R.string.tools_repair_pdf_file_mes)
@@ -359,13 +368,17 @@ public class CPDFViewCtrl extends ConstraintLayout implements IReaderViewCallbac
             alertDialog.dismiss();
         });
         if (getContext() instanceof FragmentActivity) {
-            alertDialog.show(((FragmentActivity) getContext()).getSupportFragmentManager(), "alertDialog");
+            alertDialog.show(((FragmentActivity) getContext()).getSupportFragmentManager(), "rwPermissionDialog");
         }
     }
 
     public void savePDF(COnSaveCallback callback, COnSaveError error) {
         CThreadPoolUtils.getInstance().executeMain(() -> {
             cPdfReaderView.pauseAllRenderProcess();
+            cPdfReaderView.removeAllAnnotFocus();
+            if (cPdfReaderView.getContextMenuShowListener() != null) {
+                cPdfReaderView.getContextMenuShowListener().dismissContextMenu();
+            }
             CPDFDocument document = cPdfReaderView.getPDFDocument();
             if (document == null) {
                 if (error != null) {
@@ -385,6 +398,7 @@ public class CPDFViewCtrl extends ConstraintLayout implements IReaderViewCallbac
                     }
                 } catch (CPDFDocumentException e) {
                     e.printStackTrace();
+                    CLog.e("ComPDFKit", "save fail:" + e.getMessage());
                     if (error != null) {
                         error.error(e);
                     }

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

@@ -8,7 +8,6 @@
     <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" />
-
     <application
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"