OnActivityResult возвращает Intent data.getData(); всегда Null Только в Зефир и Lollipop

Прочитайте весь мой код. Он отлично работает на каждом телефоне, кроме Marshmallow и Lollipop. В телефонах Marshmallow и Lollipop В data.getData() возвращается data.getData() только null только в случае Захваченного изображения. Он работает нормально, если я захватил Видео. У меня 4 случая -

  • Выбор изображения из галереи и отображение его миниатюры в Imageview - Работа в порядке.

  • Захват изображения с камеры и его миниатюра в Imageview - НЕ РАБОТАЕТ в Marshmallow и Lollipop.

  • Выбор видео из галереи и показать его миниатюру в Imageview - Работаем хорошо.

  • 3. Захват видео с камеры и отображение его миниатюры в Imageview - Работает нормально.

Теперь есть много решений, но ни один из них не выглядит удовлетворительным. Если код работает нормально в случае захвата видео, то почему его НЕ работает для захвата изображений? Это ошибка или я что-то делаю неправильно?

Вот мой код. Я прокомментировал строку, где происходит сбой -

 @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      int THUMBSIZE = 120;
      switch (requestCode){


        case RESULT_LOAD_IMAGE:


            if (resultCode==RESULT_OK){
                String column_Name= MediaStore.Images.Media.DATA;
                String picturePath=getPath(column_Name,data.getData());
                Bitmap orientedBitmap = ExifUtil.rotateBitmap(picturePath, BitmapFactory.decodeFile(picturePath));
                Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.extractThumbnail(orientedBitmap, THUMBSIZE, THUMBSIZE));
                thumbnailview.setBackground(fullpic);
                editText.setText(picturePath);
                picker.setVisibility(View.VISIBLE);
                thumbnailview.setClickable(false);

            }
            break;

        case REQUEST_IMAGE_CAPTURE:

            if (resultCode==RESULT_OK){
                String picturePath="";
                String column_Name=MediaStore.Images.Media.DATA;

                picturePath=getPath(column_Name,data.getData());

                    //My app Crashes here because in Marshmallow data.getData() is always null.

                Bitmap orientedBitmap = ExifUtil.rotateBitmap(picturePath, BitmapFactory.decodeFile(picturePath));
                Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.extractThumbnail(orientedBitmap, THUMBSIZE, THUMBSIZE));
                thumbnailview.setBackground(fullpic);
                editText.setText(picturePath);
                picker.setVisibility(View.VISIBLE);
                thumbnailview.setClickable(false);


            }
            break;

        case RESULT_LOAD_VIDEO:

            if (resultCode==RESULT_OK){
                String column_Name=MediaStore.Video.Media.DATA;
                String videoPath=getPath(column_Name,data.getData());
                Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.createVideoThumbnail(videoPath,MediaStore.Video.Thumbnails.MINI_KIND));
                thumbnailview.setBackground(fullpic);
                editText.setText(videoPath);
                picker.setVisibility(View.VISIBLE);
                thumbnailview.setClickable(false);


            }
            break;

        case REQUEST_VIDEO_CAPTURE:

            if (resultCode==RESULT_OK){
                String column_Name=MediaStore.Video.Media.DATA;
                String videoPath=getPath(column_Name,data.getData());
                Drawable fullpic=new BitmapDrawable(getResources(),ThumbnailUtils.createVideoThumbnail(videoPath,MediaStore.Video.Thumbnails.MINI_KIND));
                thumbnailview.setBackground(fullpic);
                editText.setText(videoPath);
                picker.setVisibility(View.VISIBLE);
                thumbnailview.setClickable(false);


            }
            break;
    }

    if (picker != null) {
        picker.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                OpenDialog();
            }
        });
    }

}


private String getPath(String column_Name,Uri uri){

    String[] projection = {column_Name};
    String path = "";
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    int column_index_data ;
    if (cursor != null) {
        column_index_data = cursor.getColumnIndexOrThrow(column_Name);
        cursor.moveToFirst();
        path = cursor.getString(column_index_data);
        cursor.close();
    }

    return path;
}

private void OpenDialog(){
    dialogBox.setTitle("Select an Action");
    dialogBox.setMessage("Choose Picture or Video");

    dialogBox.setPositiveButton("Picture", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (check_Permissions()){
                OpenCameraDialog();
            }
            else {
                request_Permissions();
                CAMERA_DIALOG_PERMISSION=1;

            }
        }
    });

    dialogBox.setNegativeButton("Video", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            if (check_Permissions()){
                OpenVideoDialog();
            }
            else {
                request_Permissions();
                VIDEO_DIALOG_PERMISSION=1;
            }

        }
    });

    dialogBox.show();

}



private void OpenCameraDialog(){

    dialogBox.setTitle("Select an Action");
    dialogBox.setMessage("Choose Picture From");

    dialogBox.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            final Intent galleryintent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(galleryintent, RESULT_LOAD_IMAGE);
        }
    });

    dialogBox.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {

            final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);

        }
    });

    dialogBox.show();

}

private void OpenVideoDialog(){

    dialogBox.setTitle("Select an Action");
    dialogBox.setMessage("Choose Video From");

    dialogBox.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            final Intent galleryintent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(galleryintent, RESULT_LOAD_VIDEO);
        }
    });

    dialogBox.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {

            final Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

            if (takeVideoIntent.resolveActivity(getPackageManager()) != null) {
                startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE);
            }
        }
    });
    dialogBox.show();

}

private boolean check_Permissions(){

    boolean GRANTED;

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) +
            ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE) +
            ContextCompat.checkSelfPermission(this,Manifest.permission.RECORD_AUDIO) +
            ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
        GRANTED=false;

    }
    else {
        GRANTED=true;
    }
    return GRANTED;
}

private void request_Permissions(){
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO},
            REQUEST_FOR_PERMISSION);

}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){

        case REQUEST_FOR_PERMISSION:

            if ((grantResults.length>0)&& (grantResults[0] +grantResults[1]+grantResults[2]+grantResults[3]== PackageManager.PERMISSION_GRANTED)){

                if (CAMERA_DIALOG_PERMISSION==1){
                    OpenCameraDialog();
                    CAMERA_DIALOG_PERMISSION=0;
                }
                else if (VIDEO_DIALOG_PERMISSION==1){
                    OpenVideoDialog();
                    VIDEO_DIALOG_PERMISSION=0;
                }

            }
            else {
                Toast.makeText(this, "Please GRANT Permissions", Toast.LENGTH_SHORT).show();
            }

    }

}

Ответ 1

Как, предложенный @CommonsWare -

Приложению камеры не нужно возвращать uri.

Кроме того,

Вам нужно указать приложение "Камера", где можно записать изображение.

Итак, я заменил свой код на

 final Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            pictureUri=getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,pictureUri);
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);

и в onActivityResult -

 case REQUEST_IMAGE_CAPTURE:

            if (resultCode==RESULT_OK){
                String picturePath="";
                String column_Name= MediaStore.Images.Media.DATA;
                if (data!=null){
                if (data.getData()!=null){
                picturePath=getPathfromUri(column_Name,data.getData());}

                else {
                    picturePath= pictureUri.getPath();

                }
                }
                else {
                    picturePath= pictureUri.getPath();

                }}

Ответ 2

Он отлично работает на каждом телефоне, кроме Marshmallow и Lollipop

Нет, это не так. Он будет терпеть неудачу во многих версиях Android, когда пользователь выбирает хорошо написанное приложение для камеры, чтобы обрабатывать ваш запрос ACTION_IMAGE_CAPTURE.

Ваша проблема здесь:

            if (data.getData()!=null){
            picturePath=getPath(column_Name,data.getData());}
            else {
                //My app Crashes here because in Marshmallow data.getData() is always null.
            }

Здесь есть как минимум два недостатка.

Большая считается, что вы возвращаете Uri из ACTION_IMAGE_CAPTURE. Это не документировано, а приложениям камер не нужно возвращать Uri. В частности, в вашей структуре вы получите только миниатюру, через getExtra("data"). Если вы хотите полноразмерное изображение, используйте EXTRA_OUTPUT на вашем Intent, и в этом случае вы знаете, где хранится изображение;— это где вы указываете в EXTRA_OUTPUT.

Другим является то, что вы предполагаете, что возвращаемый Uri находится из MediaStore или иначе имеет столбец MediaStore.Video.Media.DATA. Приложениям не только не нужно возвращать Uri, но нет требования, чтобы Uri был из MediaStore или имел такой столбец.