简体   繁体   中英

Permission Denial with File Provider through intent

I am attempting send a bitmap from the cache directory of my app to the text messaging app. I am using file provider to grant temporary permission to the application that handles the intent. When I try to send the intent and I select the default android text messaging app from the intent chooser my message app crashes and I get this error. I tried selecting other applications from the intent chooser such as email and other messaging apps and it seemed to work fine, only crashes with the default text messaging app.

java.lang.SecurityException: Permission Denial: reading android.support.v4.content.FileProvider uri content://com.example.brandon.emojimms2/shared_images/image.png from pid=9804, uid=10024 requires the provider be exported, or grantUriPermission()

权限拒绝 Here is the code where I share the intent

private void shareImage()
{
    File imagePath = new File(mContext.getCacheDir(), "images");
    File newFile = new File(imagePath, "image.png");
    Uri contentUri = FileProvider.getUriForFile(mContext, "com.example.brandon.emojimms2", newFile);

    if (contentUri != null) {
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file
        shareIntent.setDataAndType(contentUri, mContext.getContentResolver().getType(contentUri));
        shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
        startActivity(Intent.createChooser(shareIntent, "Choose an app"));
    }
}

I am fairly certain I set up the File provider correctly, but here is the manifest in case it is needed. 在此处输入图像描述

Edit: I just did some testing and it seems that the crash with the text messaging app is happening on phones on earlier apis, but is working on new apis such as 7.1. Did either the text messaging app or with the way you were supposed to grant uri read permissions change?

Try this:

List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

For this example

Intent intentShareFile = new Intent(Intent.ACTION_SEND);
File fileWithinMyDir = new File(targetPdf);

if (fileWithinMyDir.exists()) {
    intentShareFile.setType("application/pdf");
    Uri uri = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", fileWithinMyDir);
    intentShareFile.setClipData(ClipData.newRawUri("", uri));
    intentShareFile.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    intentShareFile.putExtra(Intent.EXTRA_STREAM, uri);
    startActivity(Intent.createChooser(intentShareFile, "sending file..."));

}

For images:

Change

intentShareFile.setType("application/pdf");

to

intentShareFile.setType("image/*");

It's work in Android 10, 11, 12

https://developer.android.com/reference/androidx/core/content/FileProvider

Tested on Android 8, 9, 10, 11, 12 (Samsung and Huawei Devices) Audio file

AndroidManifest.xml

<provider android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true" android:name="androidx.core.content.FileProvider">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/sharing_paths" />
</provider>

sharing_paths.xml

<path>
...
 <external-path name="Android/data/${applicationId}/ABC" path="."/>
..
</path>

Example.Java

import androidx.core.content.FileProvider;
...

try {
String mediaUri = "/storage/emulated/0/android/data/****.****.****.****/files/ABC/audiofile_202208180412_7596.m4a";  //for example

 Intent intent = new Intent(Intent.ACTION_SEND);
          File file = new File(mediaUri);
          if (file.exists()) {
          intent.setType("audio/*");
          Uri uri = FileProvider.getUriForFile(this, APPLICATION_ID + ".provider", file);
          intent.setClipData(ClipData.newRawUri("", uri));
          intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
          intent.putExtra(Intent.EXTRA_STREAM, uri);
          startActivity(Intent.createChooser(intent, "Sharing to..."));
          }
          }catch (IllegalArgumentException e) {
             e.printStackTrace();
}
 ...        

It can be Image (.JPG,.PNG) video files too, which can be changed accordingly.

intent.setType("audio/*"); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM