我的应用程序具有简单的拍照功能。用户按下按钮,应用程序通过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); }
答案 0 :(得分:1)
在配置更改时,默认情况下,如果您的活动可见,则会销毁并重新创建您的活动。那么,你的场景中会发生什么:
startActivityForResult()
ACTION_IMAGE_CAPTURE
Intent
Intent
onActivityResult()
正在被调用此时,您的崩溃是因为mProductImageView
是null
。您需要确保在尝试使用此字段之前初始化该字段。因此,例如,您可以在活动的onCreate()
中初始化它。