【问题标题】:onActivityResult returning Intent data.getData(); always Null Only in Marshmallow and LollipoponActivityResult 返回 Intent data.getData();仅在棉花糖和棒棒糖中始终为空
【发布时间】:2017-01-28 11:39:29
【问题描述】:

阅读我的完整代码。它在除MarshmallowLollipop 之外的所有电话上都能完美运行。在MarshmallowLollipop 电话中,只有在图片已捕获 的情况下data.getData() 返回null 才会出现问题。如果我捕获 视频 就可以正常工作。我有 4 个案例 -

  1. 从图库中选择图片并在 Imageview 中显示其缩略图 - 工作正常。

  2. 从相机捕获图片并在Imageview 中显示其缩略图 - 在MarshmallowLollipop不工作

  3. 从图库中选择视频并在 Imageview 中显示其缩略图 - 工作正常。

  4. 3.Capturing Video from Camera and show its thumbnail in 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();
            }

    }

}

【问题讨论】:

    标签: android camera android-camera-intent onactivityresult


    【解决方案1】:

    你可以从 Bitmap 中获取 Uri

    private Uri getImageUri(Context applicationContext, Bitmap bitmapImage) {
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            photo.compress(Bitmap.CompressFormat.PNG, 100, bytes);
            String path = MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(), bitmapImage, "Some Title", null);
            return Uri.parse(path);
        }
    
    
    
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                if (requestCode==CAPTURE_IMAGE_CODE){
    
                    Bitmap bitmapImage = (Bitmap) data.getExtras().get("data");
                    //ImageView.setImageBitmap(photo);
    
                    Uri inputImageUri = getImageUri(getApplicationContext(),bitmapImage); 
                }
            }
        }
    

    并添加调用这个 onClick

    private void takeImage(){
    
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (intent.resolveActivity(getPackageManager()) != null) {
                startActivityForResult(intent, CAPTURE_IMAGE_CODE);
            }
    
        }
    

    【讨论】:

      【解决方案2】:

      当我们将在 android 中从相机捕获图像时,Uridata.getdata() 为空。我们有两种解决方案来解决这个问题。

      1. 我们可以从Bitmap Image中获取Uri路径
      2. 我们可以从光标处获取 Uri 路径。

      我将在这里实现所有方法,请仔细阅读:-

      首先我将讲述如何从位图图像中获取 Uri: 完整代码为:

      首先,我们将通过 Intent 捕获图像,这两种方法都相同,所以这段代码我只在这里写一次:

       // Capture Image
              captureImg.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View view) {
                      Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                      if (intent.resolveActivity(getPackageManager()) != null) {
                          startActivityForResult(intent, reqcode);
                      }
      
                  }
              });
      

      现在我们将实现 OnActivityResult :-(这对于上述两种方法都是一样的):-

      @Override
          protected void onActivityResult(int requestCode, int resultCode, Intent data) {
              super.onActivityResult(requestCode, resultCode, data);
      
      
              if(requestCode==reqcode && resultCode==RESULT_OK)
              {
      
      Bitmap photo = (Bitmap) data.getExtras().get("data");
      ImageView.setImageBitmap(photo);
      
                  // CALL THIS METHOD TO GET THE URI FROM THE BITMAP
                  Uri tempUri = getImageUri(getApplicationContext(), photo);
      
                  \\ Show Uri path based on Image
                  Toast.makeText(LiveImage.this,"Here "+ tempUri, Toast.LENGTH_LONG).show();
      
                 \\ Show Uri path based on Cursor Content Resolver
                  Toast.makeText(this, "Real path for URI : "+getRealPathFromURI(tempUri), Toast.LENGTH_SHORT).show();
      }
              else
              {
                  Toast.makeText(this, "Failed To Capture Image", Toast.LENGTH_SHORT).show();
              }
          }
      

      \现在我们将创建上述所有方法,通过类从 Image 和 Cursor 方法创建 Uri:

      现在位图图像的 URI 路径

        private Uri getImageUri(Context applicationContext, Bitmap photo) {
              ByteArrayOutputStream bytes = new ByteArrayOutputStream();
              photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
              String path = MediaStore.Images.Media.insertImage(LiveImage.this.getContentResolver(), photo, "Title", null);
              return Uri.parse(path);
          }
      

      \Uri from Real path of saved image

        public String getRealPathFromURI(Uri uri) {
              Cursor cursor = getContentResolver().query(uri, null, null, null, null);
              cursor.moveToFirst();
              int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
              return cursor.getString(idx);
          }
      

      亲爱的朋友复制并粘贴此代码,然后尝试理解。 如果您正在制作企业应用程序,我 100% 肯定这对您来说会更好。 如果你喜欢我的代码,那就投票给我吧......

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

          它在除棉花糖和棒棒糖之外的所有手机上都能完美运行

          不,不是。当用户选择一个编写良好的相机应用程序来处理您的ACTION_IMAGE_CAPTURE 请求时,它会在许多 Android 版本上失败。

          你的问题在这里:

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

          这里至少有两个缺陷。

          最重要的是假设您从ACTION_IMAGE_CAPTURE 收到UriThat is not documented,相机应用不需要返回Uri。特别是,在您的结构中,您只能通过getExtra("data") 获得缩略图。如果您想要全尺寸图片,请在您的Intent 上使用EXTRA_OUTPUT,在这种情况下您知道图片的存储位置——它就是您在EXTRA_OUTPUT 中指示的位置。

          另一个是您假设您返回的Uri 来自MediaStore 或者具有MediaStore.Video.Media.DATA 列。不仅相机应用不必返回Uri,而且不要求Uri 来自MediaStore 或有这样的列。

          【讨论】:

          • 现在看到我已经更新了我的代码我没有使用 if else .. 我发错了对不起
          • 我应该在 putExtra 和 EXTRA OUTPUT 中传递什么? @CommonsWare
          • @KarandeepAtwal:理想情况下,使用由ContentProvider 支持的Uri。您可以使用 file: Uri,但这不适用于具有 24+ 的 targetSdkVersion 的 Android 7.0+。有关示例,请参见 this sample project
          • 你能解释一下吗?只是我想获取我捕获的图像的路径。如果路径已知,我知道如何获取缩略图。
          • @KarandeepAtwal:“我只想获取我捕获的图像的路径”——然后您必须通过EXTRA_OUTPUT 提供您希望相机应用程序使用的Uri。这在the documentationbooks 等中都有介绍。但是,请记住ACTION_IMAGE_CAPTURE is not reliable,因为相机应用程序开发人员似乎没有对它进行太多测试。
          猜你喜欢
          • 2016-07-30
          • 1970-01-01
          • 1970-01-01
          • 2016-09-26
          • 2016-05-02
          • 1970-01-01
          • 1970-01-01
          • 2016-10-17
          相关资源
          最近更新 更多