使用Android相机应用程序以不同方向拍照后,应用程序崩溃

时间:2018-05-22 12:47:23

标签: android

我的应用程序具有简单的拍照功能。用户按下按钮,应用程序通过MediaStore.ACTION_IMAGE_CAPTURE意图启动相机应用程序。用户捕获新照片,完成按下,重新启动应用程序,调整图像大小并分配给ImageView。除了一个案例之外,一切似乎都工作正常:如果用户在拍摄新照片的过程中更改了手机方向。例如,如果用户以纵向模式进入相机应用程序,旋转设备,以横向模式拍照,然后在相机应用程序中按完,我的应用程序崩溃:

 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference

这是导致崩溃的方法:

 takenImage = BitmapScaler.scaleToFitWidth
                    (fullSizeImage, mProductImageView.getWidth() / 100 * 50);

BitmapScaler.java

public static Bitmap scaleToFitWidth(Bitmap b, int width)
    {
        float factor = width / (float) b.getWidth();
        return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
    }

同时,如果用户以不同的方向拍摄照片,但在按完之前返回原始方向,则应用程序将正确恢复。当用户从库中选择现有图像而不是拍摄新照片时,同样的问题也适用。

这是处理上述功能的一堆代码:

    @NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
public void pickPhotoFromGallery(){
    Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    if (intent.resolveActivity(getPackageManager()) != null){
        startActivityForResult(intent, PICK_PHOTO_CODE);
    }
}

@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
public void onLaunchCamera(){
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    photoFileName = String.valueOf(System.currentTimeMillis()) + ".jpg";
    photoFile = getPhotoFileUri(photoFileName);

    mPicUri = FileProvider.getUriForFile(this,
            ProductContract.CONTENT_AUTHORITY + ".fileprovider", photoFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, mPicUri);

    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }
}

public File getPhotoFileUri(String fileName){
    File mediaStorageDir = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), APP_TAG);
    if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){
        Log.d(APP_TAG, "failed to create directory");
    }
    return new File(mediaStorageDir.getPath() + File.separator + fileName);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    /* User chose to take a new photo */
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            File takenPhoto = getPhotoFileUri(photoFileName);
            Bitmap fullSizeImage = BitmapFactory.decodeFile(takenPhoto.getAbsolutePath());
            // RESIZE BITMAP
            takenImage = BitmapScaler.scaleToFitWidth
                    (fullSizeImage, mProductImageView.getWidth() / 100 * 50);
        } else { // Result was a failure
            Toast.makeText(this, getString(R.string.no_picture_taken),
                    Toast.LENGTH_SHORT).show();
        }
    }

    /* User chose to take an an existing photo from the gallery */
    else if (requestCode == PICK_PHOTO_CODE){
        if (resultCode == RESULT_OK) {
            mPicUri = data.getData();
            try {
                Bitmap fullSizeImage = MediaStore.Images.Media.getBitmap
                        (getContentResolver(), mPicUri);

                takenImage = BitmapScaler.scaleToFitWidth
                        (fullSizeImage, mProductImageView.getWidth() / 100 * 60);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    mProductImageView.setImageBitmap(takenImage); }

1 个答案:

答案 0 :(得分:1)

在配置更改时,默认情况下,如果您的活动可见,则会销毁并重新创建您的活动。那么,你的场景中会发生什么:

  • 您的活动以纵向方式存在
  • 您使用startActivityForResult() ACTION_IMAGE_CAPTURE
  • 致电Intent
  • 相机应用程序的活动出现在前台
  • 用户将屏幕旋转为横向,但您的活动尚未受影响,因为它不可见
  • 用户使用处理Intent
  • 的相机应用拍摄照片
  • 用户确认图片(假设相机应用程序提供了这样的确认步骤)
  • 相机活动被破坏
  • 您的活动变得可见且方向已更改(纵向到横向),因此您的活动将被销毁并重新创建
  • 您的onActivityResult()正在被调用

此时,您的崩溃是因为mProductImageViewnull。您需要确保在尝试使用此字段之前初始化该字段。因此,例如,您可以在活动的onCreate()中初始化它。