Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Intent FLAG_GRANT_READ_URI_PERMISSION Using FileProvider in Gingerbread

I have an issue where I'm trying to attach multiple files from my internal storage to an email intent by providing them using a FileProvider declared in my manifest and granting the read uri permissions. Here is my code.

Manifest

         <provider 
             android:name="android.support.v4.content.FileProvider"
             android:authorities="com.company.example.logprovider"
             android:exported="false"
             android:grantUriPermissions="true">
             <meta-data
                 android:name="android.support.FILE_PROVIDER_PATHS"
                 android:resource="@xml/provider_paths"/>
         </provider> 

Intent Creation

        emailIntent = new Intent(android.content.Intent.ACTION_SEND_MULTIPLE);
        emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[] {"randomemailaddress"});

    ArrayList<Uri> uris = new ArrayList<Uri>();
    File directory = getFilesDir();
    File[] list = directory.listFiles();
    for (File f : list) {
        if (f.getName().contains("log") && f.getName().contains(".txt"))
            uris.add(FileProvider.getUriForFile(this, "com.company.example.logprovider",f));
    }

    emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);

The Issue

This works fine on two devices running Jelly Bean however it does not work for two devices running gingerbread.

The exception I am getting is as follows.

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.google.android.gm/com.google.android.gm.ComposeActivity}: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{40b2db08 3885:com.google.android.gm/10110} (pid=3885, uid=10110) requires null or null
E/AndroidRuntime( 3885):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1659)
E/AndroidRuntime( 3885):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1675)
E/AndroidRuntime( 3885):    at android.app.ActivityThread.access$1500(ActivityThread.java:121)
E/AndroidRuntime( 3885):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
E/AndroidRuntime( 3885):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 3885):    at android.os.Looper.loop(Looper.java:138)
E/AndroidRuntime( 3885):    at android.app.ActivityThread.main(ActivityThread.java:3701)
E/AndroidRuntime( 3885):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 3885):    at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 3885):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
E/AndroidRuntime( 3885):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
E/AndroidRuntime( 3885):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 3885): Caused by: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{40b2db08 3885:com.google.android.gm/10110} (pid=3885, uid=10110) requires null or null
E/AndroidRuntime( 3885):    at android.os.Parcel.readException(Parcel.java:1322)
E/AndroidRuntime( 3885):    at android.os.Parcel.readException(Parcel.java:1276)
E/AndroidRuntime( 3885):    at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:1882)
E/AndroidRuntime( 3885):    at android.app.ActivityThread.getProvider(ActivityThread.java:3365)
E/AndroidRuntime( 3885):    at android.app.ActivityThread.acquireProvider(ActivityThread.java:3390)
E/AndroidRuntime( 3885):    at android.app.ContextImpl$ApplicationContentResolver.acquireProvider(ContextImpl.java:1728)
E/AndroidRuntime( 3885):    at android.content.ContentResolver.acquireProvider(ContentResolver.java:754)
E/AndroidRuntime( 3885):    at android.content.ContentResolver.query(ContentResolver.java:262)
E/AndroidRuntime( 3885):    at com.google.android.gm.ComposeArea.addAttachment(ComposeArea.java:736)
E/AndroidRuntime( 3885):    at com.google.android.gm.ComposeArea.initFromExtras(ComposeArea.java:699)
E/AndroidRuntime( 3885):    at com.google.android.gm.ComposeActivity.initFromExtras(ComposeActivity.java:1482)
E/AndroidRuntime( 3885):    at com.google.android.gm.ComposeActivity.finishOnCreateAfterAccountSelected(ComposeActivity.java:1020)
E/AndroidRuntime( 3885):    at com.google.android.gm.ComposeActivity.onCreate(ComposeActivity.java:259)
E/AndroidRuntime( 3885):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime( 3885):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1623)
E/AndroidRuntime( 3885):    ... 11 more

My Thoughts

So somewhere down the line, the FLAG_GRANT_READ_URI_PERMISSION flag I am adding to the intent is not working?

I also believe the issue may be because I am attaching the uris to the intent as an EXTRA_STREAM and for some reason, older Android versions don't pick this up? (have not found any documentation on this yet).

Any help is appreciated.

like image 651
StuStirling Avatar asked Feb 10 '14 15:02

StuStirling


1 Answers

context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

//revoke permisions
context.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

As a last resort, if you can't provide package name you can grant the permission to all apps that can handle specific intent:

//grant permisions for all apps that can handle given intent
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
...
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);
}
like image 188
Digvesh Patel Avatar answered Sep 26 '22 12:09

Digvesh Patel