我尝试将文件附加到电子邮件 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());
}
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
您的
setFlags()
调用 replaces 所有现有标志,包括您使用 addFlags()
在上面添加的行。您可以颠倒这些行的顺序来帮助解决您的问题。