Android - file provider - permission denial

隐身守侯 提交于 2019-11-26 22:01:41

Turns out the only way to solve this is to grant permissions to all of the packages that might need it, like 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);
}

First, I would try switching away from grantUriPermission() and simply put the FLAG_GRANT_READ_URI_PERMISSION on the Intent itself via addFlags() or setFlag().

If for some reason that does not work, you could try moving your getCallingUid() logic into onCreate() instead of wherever you have it, and see if you can find out the actual "caller" there.

Android <= Lollipop (API 22)

There's a great article by Lorenzo Quiroli that solves this issue for older Android versions.

He discovered that you need to manually set the ClipData of the Intent and set the permissions for it, like so:

if ( Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP ) {
    takePictureIntent.setClipData( ClipData.newRawUri( "", photoURI ) );
    takePictureIntent.addFlags( Intent.FLAG_GRANT_WRITE_URI_PERMISSION|Intent.FLAG_GRANT_READ_URI_PERMISSION );
}

I tested this on API 17 and it worked great. Couldn't find a solution anywhere that worked.

RamiReddy

Just add setData(contentUri); and based on requirement add addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); or addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

This solves the java.lang.SecurityException: Permission Denial

Verified.

This is done as per https://developer.android.com/reference/android/support/v4/content/FileProvider.html#Permissions

How you can capture image using camera on Nougat using File Provider.

To read about about file provider follow this link File Provider

,and kit kat and marshmallow follow these steps. First of all ad tag provider under application tag in MainfestFile.

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

create a file name with (provider_paths.xml) under res folder

<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>

I have solved this issue it comes on kit kitkat version

private void takePicture() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        Uri photoURI = null;
        try {
            File photoFile = createImageFileWith();
            path = photoFile.getAbsolutePath();
            photoURI = FileProvider.getUriForFile(MainActivity.this,
                    getString(R.string.file_provider_authority),
                    photoFile);

        } catch (IOException ex) {
            Log.e("TakePicture", ex.getMessage());
        }
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
            takePictureIntent.setClipData(ClipData.newRawUri("", photoURI));
            takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION|Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        startActivityForResult(takePictureIntent, PHOTO_REQUEST_CODE);
    }
}

  private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_DCIM), "Camera");
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = "file:" + image.getAbsolutePath();
    return image;
}

I solved the problem that way:

        Intent sIntent = new Intent("com.appname.ACTION_RETURN_FILE").setData(uri);
        List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(sIntent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            activity.grantUriPermission(FILE_PROVIDER_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        sIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        activity.setResult(RESULT_OK, sIntent);
Jake

Thanks, @CommonsWare for this advice.

My problem was with the calling package. For some reason, Binder.callingUid() and getPackageManager().getNameForUid(uid) was giving me package name of App2 instead of App1.

I tried calling it in App2's onCreate as well as onResume, but no joy.

I used the following to solve it :

getApplicationContext().grantUriPermission(getCallingPackage(), 
          contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);

Turns out, activity has dedicated API for this. See here.

You need to set permission of specific package name, after that you can able to access it..

context.grantUriPermission("com.android.App1.app", fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!