Android 电子邮件 Intent 不附加具有某些后缀(例如 .xml)的文件,抛出 java.lang.SecurityException

问题描述 投票:0回答:1

我尝试将文件附加到电子邮件 Intent,但在 Logcat 中收到 SecurityException,并且电子邮件客户端 (gmail) 报告“无法附加文件”:

java.lang.SecurityException: Permission Denial: reading com.pentad.bridge.FileProvider uri content://com.pentad.bridge.FileProvider/app_root/Android/data/com.pentad.bridge/files/Demo1.xml from pid=18762, uid=10199 requires the provider be exported, or grantUriPermission()

这似乎只发生在某些文件后缀上。后缀“.brf”或“.txt”工作正常,“.xml”报告上述错误。

我的摩托罗拉 G8 (Android 11) 上会出现这种情况,但摩托罗拉 G6 (Android 9) 工作得很好。 对于 G8,我不得不添加一些通知代码,并怀疑这就是故障所在。

错误消息表明我应该导出我的 FileProvider,但是当我在清单中尝试时,我得到:

Caused by: java.lang.SecurityException: Provider must not be exported

AndroidManifest.xml:

        <provider
            android:name="com.pentad.bridge.FileProvider"
            android:authorities="com.pentad.bridge.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                       android:resource="@xml/file_provider_paths" />
        </provider>

文件提供者路径:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="app_root" path="."/>
</paths>

代码 FileProvider 扩展了 androidx.core.content.FileProvider:

            // Build email Intent
            Uri    mailToUri   = Uri.fromParts("mailto", "", null);
            Intent emailIntent = new Intent(Intent.ACTION_SEND, mailToUri);
            emailIntent.setType("text/plain");
            emailIntent.putExtra(Intent.EXTRA_SUBJECT, aSubject);
            emailIntent.putExtra(Intent.EXTRA_EMAIL, aStringArrayOfEmailAddress);
            emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            emailIntent.putExtra(Intent.EXTRA_TEXT, aMessage);

            // Build the attachment URI
            File attachFile = new File(baseDirectory, aFileName);
            Uri attachmentUri = androidx.core.content.FileProvider.getUriForFile(bridgeScorer, FileProvider.class.getCanonicalName(), attachFile);

            emailIntent.putExtra(Intent.EXTRA_STREAM, attachmentUri);

            // Try some other flags (which don't fix the problem).
            // emailIntent.setClipData(ClipData.newRawUri("", attachmentUri));
            // emailIntent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
            // emailIntent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
            // emailIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

            // Start the email activity
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)          // Earlier version can start e-mail Intent directly.
            {
                bridgeScorer.startActivity(emailIntent);
            }
            else
            {
                // Can't start e-mail directly, create a notification to do it.
                // Create the NotificationChannel if on API 26+.
                // Channel becomes permanently attached to the app (until the app is deleted).
                // Change CHANNEL_ID if new parameters required.
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                {
                    NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                                                                          NOTIFICATION_CHANNEL_NAME,
                                                                          NotificationManager.IMPORTANCE_HIGH);
                    channel.setDescription("BridgeScorer E-mail request");
                    NotificationManager notificationManager = bridgeScorer.getSystemService(NotificationManager.class);
                    notificationManager.createNotificationChannel(channel);
                }

                PendingIntent pendingIntent = PendingIntent.getActivity(bridgeScorer,       // Context
                                                                        0,                  // A unique ID (within this app).
                                                                        emailIntent,        // Intent to start.
                                                                        PendingIntent.FLAG_UPDATE_CURRENT);

                NotificationCompat.Builder builder = new NotificationCompat.Builder(bridgeScorer, NOTIFICATION_CHANNEL_ID)
                    .setCategory(Notification.CATEGORY_ALARM)                               // Try to over-ride DND.
                    .setSmallIcon(R.drawable.bridgescorer)
                    .setContentTitle(Config.getMessage("headingAppNotifyEmail"))
                    .setContentText(Config.getMessage("promptShareFile") + " " + aFileName)
                    .setLargeIcon(BitmapFactory.decodeResource(bridgeScorer.getResources(), R.drawable.bridgescorer))
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    .setTimeoutAfter(NOTIFICATION_TIMEOUT)
                    .setAutoCancel(true)
                    .setFullScreenIntent(pendingIntent, false);

                NotificationManagerCompat.from(bridgeScorer).notify(NOTIFICATION_ID, builder.build());
            }
java android email-attachments android-fileprovider securityexception
1个回答
0
投票
            emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

您的

setFlags()
调用 replaces 所有现有标志,包括您使用
addFlags()
在上面添加的行。您可以颠倒这些行的顺序来帮助解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.