Random crash on capturing image on lower android v

2019-09-04 01:47发布

问题:

In my application i capture image from camera, on marshmallow it works fine, but on lower version it gives random crash. Sometimes it works fine, sometimes it not . Here is code which i am using in my app

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String photoName = "Image_" + timeStamp + ".jpg";
        String imageFile = new File(extStorageDirectory, photoName);
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
            // Create the File where the photo should go
            try {
                SingleTon.getInstance().imageFile.createNewFile();
            } catch (IOException ex) {
                // Error occurred while creating the File
                ex.printStackTrace();
            }

            // Continue only if the File was successfully created
            if ( SingleTon.getInstance().imageFile != null) {
                Log.e("Check1 ", SingleTon.getInstance().imageFile+";");
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(SingleTon.getInstance().imageFile));
                ((Activity)context).startActivityForResult(takePictureIntent, Constant.CAMERA_PIC_REQUEST);
            }
        }

onActivity Result I am doing this :

 Uri imagePathUri = Uri.parse(SingleTon.getInstance().imageFile.getPath());
        String picturePath =    compressImage(context, imagePathUri);

For compressing image

      public static String compressImage(Context context, Uri imageUri) {
    String filePath = getRealPathFromURI(context, imageUri);

    Bitmap scaledBitmap = null;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    Bitmap bmp = BitmapFactory.decodeFile(filePath,options);

    int actualHeight = options.outHeight;//2988
    int actualWidth = options.outWidth; //5312

    float maxHeight = 1200.0f;
    float maxWidth = 1200.0f;
    /*float maxHeight = 816.0f;
    float maxWidth = 612.0f;*/
    float imgRatio = actualWidth / 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(filePath,options);
    }
    catch(OutOfMemoryError exception){
        exception.printStackTrace();

    }
    try{
        scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
    }
    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));


    ExifInterface exif;
    try {
        exif = new ExifInterface(filePath);

        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
        Log.d("EXIF", "Exif: " + orientation);
        Matrix matrix = new Matrix();
        if (orientation == 6 || orientation == 0) {
            matrix.postRotate(90);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 3) {
            matrix.postRotate(180);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 8) {
            matrix.postRotate(270);
            Log.d("EXIF", "Exif: " + orientation);
        }
        scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
    } catch (IOException e) {
        e.printStackTrace();
    }
    FileOutputStream out = null;
    String filename = getFilename();
    try {
        out = new FileOutputStream(filename);
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);

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

    return filename;

}

Kindly suggest what is wrong here. I need picture path(compressed and rotated). Sometimes it works perfectly fine and other times on saving image it goes back to app and restart calling activity.

回答1:

This is because app gets restarted and its path gets null value because path is set only when i open camera

Most likely, your process is being terminated while it is in the background. This is perfectly normal behavior. You will also have similar symptoms if the user rotates the screen.

Save your path in the saved instance state Bundle via onSaveInstanceState(). Restore it from the saved instance state Bundle in onCreate() or onRestoreInstanceState(). Then, you will have your path when control returns to you via onActivityResult(). This sample app demonstrates the process, specifically with ACTION_IMAGE_CAPTURE.