4

I am new to android and I am working in an android existing project.The app is crashing on android version >6.0, with below exception.Basically app is selecting photo from gallery which is working fine for the first time and on second time onwards the app is crashing giving permission denial exception.

java.lang.SecurityException: Permission Denial: reading com.google.android.apps.photos.contentprovider.MediaContentProvider uri content://com.google.android.apps.photos.contentprovider/0/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F1022/ORIGINAL/NONE/256350537 from pid=7789, uid=10145 requires the provider be exported, or grantUriPermission()

I have gone through few links and checked that android has introduce run time permissions and I have used below code to check the runtime permission.

The things I have tried so far...

  1. Added permission in manifest.

2.Checking the runtime permission from code.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    Log.d("Enter", "onRequestPermissionsResult: ");

    switch (requestCode){
        case REQUEST_CODE_PERMISSION:{
            Map<String,Integer> perms = new HashMap<>();
            //Initialize the map with the permissions
            perms.put(Manifest.permission.ACCESS_COARSE_LOCATION,PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.CAMERA,PackageManager.PERMISSION_GRANTED);
            perms.put(Manifest.permission.READ_EXTERNAL_STORAGE,PackageManager.PERMISSION_GRANTED);
           // perms.put(Manifest.permission.READ_USER_DICTIONARY,PackageManager.PERMISSION_GRANTED);

            //Fill with actual results from user
            if (grantResults.length > 0){
                for (int i = 0 ; i < permissions.length ; i++){
                    perms.put(permissions[i],grantResults[i]);
                    //check for all permissions
                    if (perms.get(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
                            && perms.get(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){

                        Log.d("Permission Granted", "onRequestPermissionsResult: ");

                    }else{
                        Log.d("Some", "onRequestPermissionsResult: ");
                        //if (perms.get(Manifest.permission.ACCESS_COARSE_LOCATION))
                        if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_COARSE_LOCATION)
                                || ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_EXTERNAL_STORAGE)){

                            new DialogInterface.OnClickListener(){
                                @Override
                                public void onClick (DialogInterface dialog, int which){
                                    switch (which){
                                        case DialogInterface.BUTTON_POSITIVE:
                                            checkAndRequestPermission();
                                            break;
                                        case DialogInterface.BUTTON_NEGATIVE:
                                            break;
                                    }
                                }
                            };

                        }else{
                            Toast.makeText(this,"Go to Settings and enable Permissions",Toast.LENGTH_LONG).show();
                        }

                    }

                }
            }
        }
    }
}

private  void showDialogOK(String message, DialogInterface.OnClickListener okListener){
    new AlertDialog.Builder(this)
            .setMessage(message)
            .setPositiveButton("OK",okListener)
            .setNegativeButton("Cancel",okListener)
            .create()
            .show();
}

}

And the line where it is crashing is :-

if (checkAndRequestPermission()){

        InputStream fis = getContentResolver().openInputStream(Uri.parse(url)); //Crashing Line
        BitmapFactory.decodeStream(fis, null, o);
        fis.close();
    }

Below are the permissions used in My Manifest:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_USER_DICTIONARY"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
<uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS"/>
<!--  <uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS"/>-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<!-- The following two permissions are not required to use
     Google Maps Android API v2, but are recommended. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<uses-permission android:name="com.google.android.apps.photos.permission.GOOGLE_PHOTOS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-feature android:name="android.hardware.location" android:required="true" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
reetu
  • 313
  • 3
  • 11

4 Answers4

2

The problem is not with your manifest permissions, but rather the URI being used. How did you get the URI? The logcat output tells you that the URI is for a content provider which was not exported or that the URI was not provided in an Intent which granted temporary access to the ContentProvider.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • Hi @Larry I just found out that this exception I am not getting in 6.0 (Which is also Mashmello). So as you said this is not a runtime permission exception. But since am very new to android I am not able to understand your suggestion can u please let me know if I can share some part of my code which will help u to point me the issue. – reetu Jul 11 '16 at 19:15
  • Where did you get the Uri? – Larry Schiefer Jul 11 '16 at 20:20
  • I know its a bit late response to your question Since my work is switching between iOS and android. To your question-:there are multiple Activities and PhotoDetailsActivity gets the URi from OnactivityResult URi = data.getDta(); And when they are passing the stored URi from shared preference to other activity it is crashing. So the issue is for the URi not being accessible to other Activities. And I did test with selecting image from gallery app my app is not crashing but if user selects image from photos app it is crashing. – reetu Feb 13 '17 at 21:04
1

After a lot of research I was able to fix the issue.The error was causing since the google photos needs a persistable URI of images,even if you have all codes for runtime permission and flags in Manifest file.

With the help of below answer I have fixed my issue. https://stackoverflow.com/a/29588566/1842304

Community
  • 1
  • 1
reetu
  • 313
  • 3
  • 11
0

Note down all your permission that are working in manifest below android M. We dont need any additional permission for android M. We have to just request at runtime.

And request your permission like this. Change your permission(only dangerous permissions) as they are in manifest. Put this in onCreate

///  granting permission  ////
    if(!checkPermission())
    {
        requestPermission();
    }
 /////////////////////////////

And in class add these

    ///////////////////////   permission for marshmallow  ///////////////////

private boolean checkPermission(){
    int result1 = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
    int result2 = ContextCompat.checkSelfPermission(this, Manifest.permission.MODIFY_PHONE_STATE);
    int result3 = ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_OUTGOING_CALLS);
    int result4 = ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_INCOMING_CALLS);
    int result5   = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);

    if (result1 == PackageManager.PERMISSION_GRANTED && result2 == PackageManager.PERMISSION_GRANTED &&
            result3 == PackageManager.PERMISSION_GRANTED && result4 == PackageManager.PERMISSION_GRANTED
            && result5 == PackageManager.PERMISSION_GRANTED){

        return true;

    } else {

        //Toast.makeText(this,"You don't have permission to use further features",Toast.LENGTH_LONG).show();
        return false;

    }
}

private void requestPermission(){

    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE) &&
            ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.MODIFY_PHONE_STATE) &&
            ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.PROCESS_OUTGOING_CALLS)  &&
            ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.PROCESS_INCOMING_CALLS) &&
                    ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)){

        Toast.makeText(this,"Application needs permission to use your camera, calls, storage and location.",Toast.LENGTH_LONG).show();

    } else {

        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_PHONE_STATE,
                 Manifest.permission.MODIFY_PHONE_STATE, Manifest.permission.PROCESS_OUTGOING_CALLS,
                Manifest.permission.PROCESS_INCOMING_CALLS, Manifest.permission.CALL_PHONE},1);

    }
}


@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[2] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[3] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[4] == PackageManager.PERMISSION_GRANTED) {

                Toast.makeText(this,"Permission Granted.",Toast.LENGTH_LONG).show();

            } else {

                Toast.makeText(this,"Permission Denied.",Toast.LENGTH_LONG).show();

            }
            break;
    }
}

////////////////////////////////////////////////////////////////////////
Shahbaz Hashmi
  • 2,631
  • 2
  • 26
  • 49
  • Hi Hashmi. I have tried to use Manifest.permission.READ_USER_DICTIONARY in my runtime permission but it is not able to recognize it. It might look silly question but do I need to import anything so that the class will recognize this permission. Where as I was able to add READ_USER_DICTIONARY permission in manifest. – reetu Jul 06 '16 at 19:23
  • Strange issue, how your other permissions are working then. try adding this 'import android.Manifest' – Shahbaz Hashmi Jul 06 '16 at 19:29
  • security exception arises when permission is missing. So try to trace the bug. If manifest has the same permission and its working below android M. Your code for runtime permission is not working properly. See the edit. – Shahbaz Hashmi Jul 07 '16 at 06:42
0

Try this Solution

in your OnCreate() method

@Override
    protected void onCreate(Bundle savedInstanceState)
     {

       // your code
       .................

       // call dynamic permission
       check_SD_CARD_Permissions();
    }

public void check_SD_CARD_Permissions()  
{

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

       int permissionCheck = this.checkSelfPermission("Manifest.permission.WRITE_EXTERNAL_STORAGE");
            permissionCheck += this.checkSelfPermission("Manifest.permission.READ_EXTERNAL_STORAGE");
            if (permissionCheck != 0) {
                this.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1001); //Any number
            }
        }else{
        Log.d(TAG, "checkBTPermissions: No need to check permissions. SDK version < LOLLIPOP.");
 }
}

in AndroidManifest.xml

add these permissions

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

and targetSdkVersion must be 23

<uses-sdk
        android:minSdkVersion="13"
        android:targetSdkVersion="23" />

Build your project with

Version : Android 6.0

and finally in project.properties target must be 23

target=android-23

it's working for me

Srikanth M
  • 59
  • 1
  • 3
  • I tried the above still crashing with the same exception.And I am using WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE also for gallery image access runtime permission or do I need some different runtime permission for photo access? – reetu Feb 07 '17 at 14:57