onActivityResult() 在 Android 4.1.2 中捕获图像后给出空值

Posted

技术标签:

【中文标题】onActivityResult() 在 Android 4.1.2 中捕获图像后给出空值【英文标题】:onActivityResult() gives null value after capturing image in Android 4.1.2 【发布时间】:2017-02-09 17:47:52 【问题描述】:

我想捕获图像,将其保存到外部存储并显示在 ImageView 中。成功捕获并保存图像,但在执行onActivityResult() 时未显示在ImageView 中。它给出null 值。

请告诉我为什么它给了我空值。

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    imageView = (ImageView) findViewById(R.id.imageView);

    //camera stuff
    Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

    //folder stuff
    imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
    imagesFolder.mkdirs();

    File image = new File(imagesFolder, "QR_" + timeStamp + ".png");
    uriSavedImage = Uri.fromFile(image);

    imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
    startActivityForResult(imageIntent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);

    try 
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) 
            if (resultCode == RESULT_OK) 
                Toast.makeText(this, "Image saved to:\n", Toast.LENGTH_LONG).show();
                Bitmap bitmap = (Bitmap) data.getExtras().get(MediaStore.EXTRA_OUTPUT);
                imageView.setImageBitmap(bitmap);

             else if (resultCode == RESULT_CANCELED) 
                // User cancelled the image capture
             else 
                // Image capture failed, advise user
            
        
     catch (Exception e) 
        Log.d("onActivityResult", " error "+e.getMessage());
    

日志错误:

10-01 10:57:14.008 18530-18530/com.example.zohaibsiddique.camera D/onActivityResult:  error null

【问题讨论】:

onActivityResult() gives null value。废话。 e.getMessage()Log.d("onActivityResult", " error "+e.getMessage()); 中是 null。您的代码产生了一个问题。 你说的废话是什么意思?请使用道德词@greenapps 查看这个 SO 答案:android-camera-onactivityresult-resets-photo-path-to-null 【参考方案1】:

如果您将额外参数MediaStore.EXTRA_OUTPUT 与相机意图一起传递,那么相机活动会将捕获的图像写入该路径,并且不会在onActivityResult 方法中返回位图。

如果您检查您所传递的路径,那么您将知道实际上相机已将捕获的文件写入该路径。

如需了解更多信息,您可以关注this、this 和this

【讨论】:

那我怎样才能返回位图?【参考方案2】:

您有两个选项来获取图像,从图库和从相机拍摄。如果您将EXTRA_OUTPUT 放入意图中,它不会返回Bitmap。那么你必须使用Uri

用这两种方法startActivityForResult

private void selectFromCamera() 

    try 
        File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "DCIM");
        if (!file.exists()) 
            file.mkdirs();
        

        File localFile = new File(file + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        imageUri = Uri.fromFile(localFile);

        Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");

        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) 
            cameraIntent.setClipData(ClipData.newRawUri(null, Uri.fromFile(localFile)));
        

        startActivityForResult(cameraIntent, REQUEST_CAMERA);
     catch (Exception localException) 
        Toast.makeText(ActivityAddMemory.this, "Exception:" + localException, Toast.LENGTH_SHORT).show();
    


private void selectFromGallery() 
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    intent.setType("image/*");
    startActivityForResult(Intent.createChooser(intent, "Select File"), SELECT_FILE);

现在在onActivityForResult里面

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) 
    super.onActivityResult(requestCode, resultCode, intent);

    if(resultCode == RESULT_OK) 
        String path=null;
        Uri uri;
        if (intent == null || intent.getData() == null)
            uri = this.imageUri;
        else
            uri = intent.getData();

        if(requestCode == SELECT_FILE) 
            path = getRealPathFromURI(uri);
         else if(requestCode == REQUEST_CAMERA)
            path = uri.getEncodedPath();
        

    imageView.setImageBitmap(BitmapFactory.decodeFile(path));

下面是getRealPathFromUri

public String getRealPathFromURI(Uri uri)
    String filePath = "";
    String[] filePahColumn = MediaStore.Images.Media.DATA;
    Cursor cursor = getContentResolver().query(uri, filePahColumn, null, null, null);
    if (cursor != null) 
        if(cursor.moveToFirst())
            int columnIndex = cursor.getColumnIndex(filePahColumn[0]);
            filePath = cursor.getString(columnIndex);
        
        cursor.close();
    
    return filePath;

【讨论】:

【参考方案3】:

在 onCreate() 中调用这个方法

public void startCameraIntent() 
        File imageFile = new File("YOUR PATH");
        Uri imageFileUri = Uri.fromFile(imageFile); // convert path to Uri

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);   // set the image file name
        startActivityForResult(intent, 02);
    

将这些行放在 onActivityResult() 中

new ImageCompression(this).execute("PATH");

创建类:

public class ImageCompression extends AsyncTask<String, Void, String> 

        private Context context;
        private static final float maxHeight = 1280.0f;
        private static final float maxWidth = 1280.0f;


        public ImageCompression(Context context) 
            this.context = context;
        

        @Override
        protected String doInBackground(String... strings) 
            if (strings.length == 0 || strings[0] == null)
                return null;

            return compressImage(strings[0]);
        

        protected void onPostExecute(String imagePath) 
            // imagePath is path of new compressed image.
            imageView.setImageBitmap(BitmapFactory.decodeFile(new File(imagePath).getAbsolutePath()));
        


        public String compressImage(String imagePath) 
            Bitmap scaledBitmap = null;

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            Bitmap bmp = BitmapFactory.decodeFile("YOUR PATH", options);

            int actualHeight = options.outHeight;
            int actualWidth = options.outWidth;

            float imgRatio = (float) actualWidth / (float) actualHeight;
            float maxRatio = maxWidth / maxHeight;

            if (actualHeight > maxHeight || actualWidth > maxWidth) 
                if (imgRatio < maxRatio) 
                    imgRatio = maxHeight / actualHeight;
                    actualWidth = (int) (imgRatio * actualWidth);
                    actualHeight = (int) maxHeight;
                 else if (imgRatio > maxRatio) 
                    imgRatio = maxWidth / actualWidth;
                    actualHeight = (int) (imgRatio * actualHeight);
                    actualWidth = (int) maxWidth;
                 else 
                    actualHeight = (int) maxHeight;
                    actualWidth = (int) maxWidth;

                
            

            options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
            options.inJustDecodeBounds = false;
            options.inDither = false;
            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inTempStorage = new byte[16 * 1024];

            try 
                bmp = BitmapFactory.decodeFile(imagePath, options);
             catch (OutOfMemoryError exception) 
                exception.printStackTrace();

            
            try 
                scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565);
             catch (OutOfMemoryError exception) 
                exception.printStackTrace();
            

            float ratioX = actualWidth / (float) options.outWidth;
            float ratioY = actualHeight / (float) options.outHeight;
            float middleX = actualWidth / 2.0f;
            float middleY = actualHeight / 2.0f;

            Matrix scaleMatrix = new Matrix();
            scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

            Canvas canvas = new Canvas(scaledBitmap);
            canvas.setMatrix(scaleMatrix);
            canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

            if (bmp != null) 
                bmp.recycle();
            

            ExifInterface exif;
            try 
                exif = new ExifInterface(imagePath);
                int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
                Matrix matrix = new Matrix();
                if (orientation == 6) 
                    matrix.postRotate(90);
                 else if (orientation == 3) 
                    matrix.postRotate(180);
                 else if (orientation == 8) 
                    matrix.postRotate(270);
                
                scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
             catch (IOException e) 
                e.printStackTrace();
            
            FileOutputStream out = null;
            String filepath = getFilename();
            try 
                new File("YOUR PATH").delete();
                out = new FileOutputStream(filepath);

                //write the compressed bitmap at the destination specified by filename.
                scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
/*

                Uri uri = Uri.parse(filepath + "/tmp.x");
                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));

*/
             catch (FileNotFoundException e) 
                e.printStackTrace();
            

            return filepath;
        

        public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) 
            final int height = options.outHeight;
            final int width = options.outWidth;
            int inSampleSize = 1;

            if (height > reqHeight || width > reqWidth) 
                final int heightRatio = Math.round((float) height / (float) reqHeight);
                final int widthRatio = Math.round((float) width / (float) reqWidth);
                inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
            
            final float totalPixels = width * height;
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) 
                inSampleSize++;
            

            return inSampleSize;
        
    

比活动类中的创建方法:

public String getFilename() 
    File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
            + "/Tax Images");

    MediaScannerConnection.scanFile(this, new String[]mediaStorageDir.toString(), null, null);
    // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) 
        mediaStorageDir.mkdirs();
    


    String uriString = (mediaStorageDir.getAbsolutePath() + "/" + "IMAGE_NAME");

    return uriString;

【讨论】:

以上是关于onActivityResult() 在 Android 4.1.2 中捕获图像后给出空值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 onActivityResult 中调用 startActivityForResult?

OnActivityResult 没有被调用

关于片段生命周期,何时调用片段的 onActivityResult?

onActivityResult() 没有在 DialogFragment 中执行

谈谈Fragment中的onActivityResult

onActivityResult 没有在活动之间调用