У меня есть фрагмент. В этом фрагменте я использую onActivityResult () , чтобы поймать намерение, когда пользователь выбирает фотографию и импортирует ее в мое приложение:

Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CAMERA) {
        if (resultCode == Activity.RESULT_OK) {
            Uri takenPhotoUri = ImageUtils.getInstance().getPhotoFileUri(getContext(), imageFileName);
            actionsListener.onSignalPhotoSelected(takenPhotoUri.getPath());
        }
    }

    if (requestCode == REQUEST_GALLERY && resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {

        Uri fileUri = data.getData();
        String path = null;
        File photoFile = new File(fileUri.toString());

        // Differentiate between SDK versions
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            // Code for Android 6 and > goes here
            if(getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                //showPermissionDialog(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
                ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);
            }
            try {
                ParcelFileDescriptor parcelFileDesc = getActivity().getContentResolver().openFileDescriptor(fileUri, "r");
                FileDescriptor fileDesc = parcelFileDesc.getFileDescriptor();
                Bitmap photo = BitmapFactory.decodeFileDescriptor(fileDesc);
                path = MediaStore.Images.Media.insertImage(getContext().getContentResolver(), photo, "temp", null);
                parcelFileDesc.close();

                // DRY!!
                photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), Uri.parse(path));

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        else {
            // DRY!!
            photoFile = ImageUtils.getInstance().getFromMediaUri(getContext(), getContext().getContentResolver(), data.getData());
        }
        if(photoFile != null) {
            actionsListener.onSignalPhotoSelected(Uri.fromFile(photoFile).getPath());
        }
    }

    if (requestCode == REQUEST_SIGNAL_DETAILS) {
        if (resultCode == Activity.RESULT_OK) {
            Signal signal = data.getParcelableExtra("signal");
            if (signal != null) {
                actionsListener.onSignalStatusUpdated(signal);
            }
        }
    }
}

Моя проблема заключается в следующем: когда пользователь выбирает фотографию из Google Фото (фотография, которая существует только в облаке и не была загружена локально), мое приложение вылетает со следующей ошибкой:

E / MediaStore: не удалось вставить изображение java.lang.SecurityException: отказ в разрешении: запись com.android.providers.media.MediaProvider uri content: // media / external / images / media from pid = 9851, uid = 10091 требуется android. permission.WRITE_EXTERNAL_STORAGE или grantUriPermission () в android.os.Parcel.readException (Parcel.java:1943) в android.database.DatabaseUtils.readExceptionFromParcel (DatabaseUtils.java:183) в android.database.DatabaseUtils.readExceptionFromParcel (DatabaseUtils. : 135) в android.content.ContentProviderProxy.insert (ContentProviderNative.java:476) в android.content.ContentResolver.insert (ContentResolver.java:1539) в android.provider.MediaStore $ Images $ Media.insertImage (MediaStore.java: 984) в org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult (SignalsMapFragment.java:738) в android.support.v4.app.FragmentActivity.onActivityResult (FragmentActivity.java:151) в android.app.Activity.dispatchActivityResult (Activity.java:7235) в android.app.ActivityThread.deliverResults (ActivityThread.java:4320) в android.app.ActivityThread.handleSendResult (ActivityThread.java:4367) в android.app. ActivityThread.-wrap19 (Неизвестный источник: 0) в android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1649) в android.os.Handler.dispatchMessage (Handler.java:105) в android.os.Looper.loop (Looper.java:164) в android.app.ActivityThread.main (ActivityThread.java:6541) в java.lang.reflect.Method.invoke (собственный метод) в com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:240) в com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767) D / AndroidRuntime: выключение виртуальной машины E / AndroidRuntime: FATAL EXCEPTION: main Process: org.helpapaw.helpapaw, PID : 9851 java.lang.RuntimeException: Ошибка доставки результата ResultInfo {who = null, request = 196611, result = -1, data = Intent {dat = content: //com.google.android.apps.photos.contentprovider/0/1/mediakey: / local% 3Aabc88a06-d518-4fae-b85d-73f727595a90 / ORIGINAL / NONE / 1144559444 flg = 0x1 clip = {text / uri-list U: content: //com.google.android.apps.photos.contentprovider/0/1/mediakey%3A%2Flocal%253Aabc88a06-d518-4fae- b85d-73f727595a90 / ORIGINAL / NONE / 1144559444}}} к действию {org.helpapaw.helpapaw / org.helpapaw.helpapaw.signalsmap.SignalsMapActivity}: java.lang.NullPointerException: uriString at android.app.ActivityThread java: 4324) в android.app.ActivityThread.handleSendResult (ActivityThread.java:4367) в android.app.ActivityThread.-wrap19 (неизвестный источник: 0) в android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1649 ) в android.os.Handler.dispatchMessage (Handler.java:105) в android.os.Looper.loop (Looper.java:164) в android.app.ActivityThread.main (ActivityThread.java:6541) в java.lang.reflect.Method.invoke (собственный метод) в com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:240) в com.android.internal.os.ZygoteInit.main (ZygoteInit. java: 767) Вызвано: java.lang.NullPointerException: uriString на android.net.Uri $ StringUri. (Uri.java:476) на android.net.Uri $ StringUri. (Неизвестный источник: 0) на android.net. Uri.parse (Uri.java:438) в org.helpapaw.helpapaw.signalsmap.SignalsMapFragment.onActivityResult (SignalsMapFragment.java:742) в android.support.v4.app.FragmentActivity.onActivityResult (Fragment151) в android.java .app.Activity.dispatchActivityResult (Activity.java:7235) в android.app.ActivityThread.deliverResults (ActivityThread.java:4320) в android.app.ActivityThread.handleSendResult (ActivityThread.java:4367) в android.app.ActivityThread. -wrap19 (Неизвестный источник: 0) в android.app.ActivityThread $ Hh andleMessage (ActivityThread.java:1649) в android.os.Handler.dispatchMessage (Handler.java:105) в android.os.Looper.loop (Looper.java:164) в android.app.ActivityThread.main (ActivityThread.java : 6541) в java.lang.reflect.Method.invoke (собственный метод) в com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:240) в com.android.internal.os.ZygoteInit.main (ZygoteInit.java:767)

Первая строка этой ошибки заставляет меня думать об ошибке разрешения WRITE_TO_EXTERNAL:

E / MediaStore: не удалось вставить изображение java.lang.SecurityException: отказ в разрешении: запись com.android.providers.media.MediaProvider uri content: // media / external / images / media from pid = 9851, uid = 10091 требуется android. разрешение.WRITE_EXTERNAL_STORAGE или grantUriPermission ()

Поэтому я проверяю, требуется ли для этой версии API разрешение «во время выполнения» (как вы можете видеть в приведенном выше коде) и строка:

ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_STORAGE_FOR_CLOUDE);

Получает удар, но на экране не появляется диалоговое окно подтверждения. Еще один интересный факт: ошибка возникает только при первом запуске приложения (на API 8.0) и отлично работает на 5.1, 6.0, 7.1 и 8.1, но вылетает на 8.0 (эмулятор). Что мне не хватает?

2
Nactus 22 Ноя 2018 в 22:51

1 ответ

Лучший ответ

Для тех, кто борется с чем-то подобным; ключ состоит в том, чтобы запросить все необходимые разрешения сразу, используя (в моем случае) метод Fragment.requestPermissions(String[] permissions, int requestCode);. Этот метод позволяет передать массив разрешений в свой первый параметр:

    String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};
        if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(permissions, READ_WRITE_EXTERNAL_STORAGE_FOR_GALLERY);
}
  • Что бы я хотел знать:

    как только новое действие вызывается намерением, будь то камера или фотогалерея; попытки запросить разрешения у пользователя больше не работают; Это означает, что при открытии камеры или фотогалереи мы теряем контекст нашего собственного приложения и, следовательно, больше не можем запрашивать разрешения у пользователя. Крайне важно, чтобы все разрешения запрашивались до того, как пользователь покинет наше приложение (в моем случае использование массива было необходимо для запроса разрешений как на чтение, так и на запись во внешнее хранилище. Спросите все необходимые разрешения в то же время, прежде чем пользователь покинет текущий контекст, затем перенаправить на новое действие через намерение.

Я надеюсь, что это помогает кому-то.

0
Nactus 11 Дек 2018 в 05:18