В Android 6.0 получение исключения разрешения безопасности при повторном доступе к изображению из галереи

Я новичок в Android, и я работаю в существующем проекте Android. Приложение дает сбой на версии Android> 6.0, за исключением ниже. В основном приложение выбирает фотографию из галереи, которая работает нормально в первый раз и во второй раз. приложение аварийно завершает работу, создавая исключение отказа в разрешении.

java.lang.SecurityException: отказ в разрешении: чтение 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 требует экспорта провайдера или GrantUriPermission()

Я просмотрел несколько ссылок и проверил, что Android вводит разрешения во время выполнения, и я использовал приведенный ниже код для проверки разрешения во время выполнения.

То, что я пробовал до сих пор ...

  1. Добавлено разрешение в манифест.

2.Проверка разрешения времени выполнения из кода.

@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();
}

}

И строка, где он падает: -

if (checkAndRequestPermission()){

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

Ниже приведены разрешения, используемые в 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" />

person reetu    schedule 06.07.2016    source источник
comment
попробуйте эту ссылку.   -  person Aman Jain    schedule 06.07.2016
comment
Могу ли я увидеть ваш файл манифеста ??   -  person Janki Gadhiya    schedule 07.07.2016
comment
@jankigadhiya Я добавил свои списки разрешений манифеста в свой вопрос.   -  person reetu    schedule 07.07.2016


Ответы (4)


Проблема не в ваших разрешениях манифеста, а в используемом URI. Как вы получили URI? Выходные данные logcat говорят вам, что URI предназначен для поставщика контента, который не был экспортирован, или что URI не был предоставлен в Intent, который предоставил временный доступ к ContentProvider.

person Larry Schiefer    schedule 07.07.2016
comment
Привет, @Larry, я только что узнал, что этого исключения я не получаю в 6.0 (что также является Mashmello). Итак, как вы сказали, это не исключение для разрешений во время выполнения. Но так как я очень новичок в Android, я не могу понять ваше предложение, не могли бы вы сообщить мне, могу ли я поделиться какой-то частью моего кода, которая поможет вам указать мне на проблему. - person reetu; 11.07.2016
comment
Где вы взяли Ури? - person Larry Schiefer; 11.07.2016
comment
Я знаю, что это немного запоздалый ответ на ваш вопрос, так как моя работа переключается между iOS и Android. На ваш вопрос: существует несколько действий, и PhotoDetailsActivity получает URi из OnactivityResult URi = data.getDta(); И когда они передают сохраненный URI из общего предпочтения в другую активность, происходит сбой. Таким образом, проблема в том, что URi недоступен для других действий. И я проверил, выбирая изображение из приложения галереи, мое приложение не падает, но если пользователь выбирает изображение из приложения для фотографий, оно падает. - person reetu; 14.02.2017

После долгих исследований я смог исправить проблему. Ошибка была вызвана тем, что для фотографий Google требуется постоянный URI изображений, даже если у вас есть все коды для разрешения времени выполнения и флаги в файле манифеста.

С помощью приведенного ниже ответа я исправил свою проблему. https://stackoverflow.com/a/29588566/1842304

person reetu    schedule 24.03.2017

Запишите все ваши разрешения, которые работают в манифесте ниже Android M. Нам не нужны дополнительные разрешения для Android M. Мы должны просто запросить во время выполнения.

И запросите ваше разрешение, как это. Измените свое разрешение (только опасные разрешения), поскольку они указаны в манифесте. Поместите это в onCreate

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

И в классе добавьте эти

    ///////////////////////   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;
    }
}

////////////////////////////////////////////////////////////////////////
person Shahbaz Hashmi    schedule 06.07.2016
comment
Привет, Хашми. Я пытался использовать Manifest.permission.READ_USER_DICTIONARY в моем разрешении времени выполнения, но оно не может его распознать. Это может показаться глупым вопросом, но нужно ли мне что-либо импортировать, чтобы класс распознал это разрешение. Где, как я смог добавить разрешение READ_USER_DICTIONARY в манифест. - person reetu; 06.07.2016
comment
Странная проблема, как тогда работают ваши другие разрешения. попробуйте добавить этот «импорт android.Manifest» - person Shahbaz Hashmi; 06.07.2016
comment
исключение безопасности возникает, когда разрешение отсутствует. Итак, попробуйте отследить ошибку. Если манифест имеет такое же разрешение и работает ниже Android M. Ваш код для разрешения времени выполнения не работает должным образом. Смотрите редактирование. - person Shahbaz Hashmi; 07.07.2016

Попробуйте это решение

в вашем методе OnCreate()

@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.");
 }
}

в AndroidManifest.xml

добавить эти разрешения

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

и targetSdkVersion должно быть 23

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

Создайте свой проект с

Version : Android 6.0

и, наконец, в project.properties цель должна быть 23

target=android-23

это работает для меня

person Srikanth M    schedule 07.02.2017
comment
Я попробовал вышеописанное, но все равно вылетает с тем же исключением. И я использую WRITE_EXTERNAL_STORAGE и READ_EXTERNAL_STORAGE также для разрешения доступа к изображениям галереи во время выполнения или мне нужно какое-то другое разрешение во время выполнения для доступа к фотографиям? - person reetu; 07.02.2017