23

My app allows users to import their photos and videos from other apps. Now that Google replaced Google+ Photos with Google Photos, couple of things broke for me. One of these things is re-using imported files after app restart. I have a feeling they've tightened up the permissions given out when Google Photos returns the intent with the image URI, so after my app gets killed it no longer has the permission to access the uploaded file. I'm getting the Security expection:

java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.MediaContentProvider from ProcessRecord{2c17ab9e 2124:com.myapp.myapp/u0a436} (pid=2124, uid=10436) that is not exported from uid 10427

EDIT:

I'm also getting the same problem with reusing files provided by com.google.android.apps.docs.sync.filemanager.FileProvider

Any suggestions/workaround? I know I can read the file before I lost permission so in theory I could copy it but I can't say I like this very much..

vkislicins
  • 3,331
  • 3
  • 32
  • 62

6 Answers6

28

Yep, this is by design, as described on Android Developer site.

For security reasons, the permissions are temporary, so once the client app's task stack is finished, the file is no longer accessible. You must get the file data when you receive the intent answer, in the onActivityResult method. Store a copy of the file data, because the file won't be available anymore when onActivityResult returns.

Dazzibao
  • 590
  • 3
  • 7
  • This was my conclusion as well so I'll choose your answer as the answer. Thanks – vkislicins Jul 08 '15 at 09:35
  • 1
    It looks like antipattern. Make a copy of the file in main thread? – tse Feb 28 '16 at 18:02
  • @tse You have access from any thread for as long as your activity that was targeted by the intent isn't stopped – Adrien Aubel May 18 '16 at 00:01
  • 3
    i had a similar issue and i was able to fix it by using ACTION_OPEN_DOCUMENT instead of ACTION_PICK. i believe ACTION_OPEN_DOCUMENT grants persisting permission and is not as strict as ACTION_PICK. When i was using ACTION_PICK, i lost permission when i got the URI in one activity and went to a different activity to display the image, Just as the developer docs say. – onusopus Nov 09 '17 at 23:46
  • @onusopus thanks, your answer should be the accepted answer. – ralphgabb Nov 05 '20 at 13:23
  • @onusopus Still applicable, thank you. However, the issue remains that the permissions are lost on reboot. – Prof May 23 '21 at 16:04
13
  1. You can reproduce this SecurityException Log when you use the "Google Photo" app.

  2. Main cause of this problem is "Google Photo" shares ContentUri with fixed string like "content://com.google.android.apps.photos.contentprovider/1/1" and connect it with a static temporary values. "Google Photo" does not provide the file path when the actual Activity or Context which receives Intent.ACTION_SEND. Maybe, it is the policy of "Google Photo", not to expose the private image file to other app.

  3. For example, you defines 2 Activity in Manifest file, Actvity A and Activity B. Activity A for receives the Intent.ACTION_SEND. Activity B for processing the image file. Activity A forward the intent to Activity B. Then Activity B is not the correct Activity to "Google Photo", you encounters the SecurityException.

So, I recommend you to save the file temporarily on Activity A and use the temporary file path on Activity B

BlueMist
  • 226
  • 1
  • 7
3

maybe you can try adding this user-permission into your manifest file.

<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
Zephyr
  • 6,123
  • 34
  • 33
2

Looks like this question is simular

I think when activity (not fragment) dies - all retrieved by it URI become invalidated

I also have the same problem - trying to upload picture in background. But user in UI thread may change activity and URI becomes invalid

Community
  • 1
  • 1
Art
  • 903
  • 9
  • 20
  • Yes it does look similar, but I think the permission changed for the new Photos app content provider as I have a feeling I tried that permission before with no luck. I ended up copying files into my territory and registering them in my content provider to retain access. Let me know if you find a better solution! – vkislicins Jun 04 '15 at 00:21
1

You need to set permissions explicitly to all packages match your intent. It happens in Android 4.4 usually.

you can use this utility to do that :

List<ResolveInfo> resInfoList = getContext().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            getContext().grantUriPermission(packageName, imageFileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
Maher Abuthraa
  • 17,493
  • 11
  • 81
  • 103
0

I have same issue with this, and you and try the follow work around methods:

  1. Android 5.1.1 lollipop return null file path if image chosen from gallery

  2. https://gist.github.com/alexzaitsev/75c9b36dfcffd545c676

  3. Choosing photo using new Google Photos app is broken

Community
  • 1
  • 1
jtxyz0804
  • 54
  • 3
  • My problem is not the initial get call - it's the permission retention. After getting access to the file, the access is revoked if the app is suspended or the user moves away from the app – vkislicins Jun 09 '15 at 16:27
  • Please include the answer here, rather than just links. See http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers – Nicolas Raoul Jul 20 '16 at 08:55