java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.content.GooglePhotosImageProvider

All of the sudden, I started getting the following exception from devices running android 4.3 and above

java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.content.GooglePhotosImageProvider from ProcessRecord{454ca9d0 5914:com.propertymanager/u0a10231} (pid=5914, uid=10231) requires com.google.android.apps.photos.permission.GOOGLE_PHOTOS or com.google.android.apps.photos.permission.GOOGLE_PHOTOS
        at android.os.Parcel.readException(Parcel.java:1431)
        at android.os.Parcel.readException(Parcel.java:1385)
        at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:2896)
        at android.app.ActivityThread.acquireProvider(ActivityThread.java:4755)
        at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2480)
        at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1152)
        at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:759)
        at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:665)
        at android.content.ContentResolver.openInputStream(ContentResolver.java:500)
        at com.myapp.xxxx.determineCorrectScale(SourceFile:148)

My The code causing it is

    public static int determineCorrectScale(Context con, Uri imagUri) {
        int scale = 1;
        InputStream imageStream = null;

                imageStream = con.getContentResolver().openInputStream(imagUri);
.
.
.
    }

Any help??

EDIT: This is how I let the user pick a picture before calling the above method

Intent choosePictureIntent = new Intent(Intent.ACTION_PICK, Images.Media.INTERNAL_CONTENT_URI);
tartActivityForResult(choosePictureIntent, REQUEST_CHOOSE_IMAGE);

Here is the OnActivityResult:

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
        case REQUEST_CHOOSE_IMAGE:

            Uri selectedImage = intent.getData();

            try {

                int scale = CommonFunc.determineCorrectScale(this, selectedImage);

While adding the permission works for this particular content provider it won't work if your data is delivered by other content providers (on Android there's no guarantee you'll get the data by a specific content provider unless you explicitly access that content provider).

The "final" solution to this problem can be found here:

Getting access with temporary permissions

You can access data in a content provider, even if you don't have the proper access permissions, by sending an intent to an application that does have the permissions and receiving back a result intent containing "URI" permissions. These are permissions for a specific content URI that last until the activity that receives them is finished.

http://developer.android.com/guide/topics/providers/content-provider-basics.html

Since version 4.3 Android checks whether the receiving Activity is still running and if not throws the SecurityException. The determineCorrectScale is a static method so I assume it's at least sometimes called outside the Activity life cycle. To fix this once and for all you need to retrieve the data from the content provider while the Activity is running. I don't know the requirements for your app but if there's no heavy lifting involved (like copying images from the content provider) then just do it on the ui thread. If heavy lifting is needed then use an AsyncTask started by the Activity but then you have to make sure the Activity doesn't finish before the data has been retrieved (which might be tricky).

I didn't just add that answer because I think it's the correct one but because other developers might not be aware of this change introduced in 4.3/4.4 and might run into the same issue with other content providers.


you need to add this permission to your manifest:

<uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS"/>

hope this works for you. please give me a feedback