我正在使用系统默认相机拍照并将图像保存到 SD 卡中。
该应用程序在装有 Android 6.0 的 Nexus 5 上运行良好。 但是在装有 Android 5.0.1 的三星 Galaxy S4 上,当我按“保存”时应用程序崩溃了:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jublikon.example/com.jublikon.example.ReviewMaschine.ReviewActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
为什么相机 Activity 会尝试启动另一个 Activity? 它应该只保存图像和 finish() 本身。
我的捕获图像方法如下所示:
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
代码生成的fileUri:
file:///storage/emulated/0/Pictures/ImageDokumentation/IMG_20151214_214131.jpg
我注意到该应用程序将图像保存在本地 Samsung Galaxy S4 上,而不是保存在 SD 卡上。也许这是我犯的错误? 我意识到有时图片会被保存,有时不会。应用程序在每种情况下都会停止。
应用程序没有运行到 onActivityResult 就崩溃了。
我真的不明白我做错了什么。该应用程序可以在物理 Nexus 设备上正常运行。
编辑:因为这似乎是一个更复杂的问题,这里是 fragment 的缩短代码:
public class FragmentReview extends Fragment {
// some initialization (...)
private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
private static final String IMAGE_DIRECTORY_NAME = "ImageDokumentation";
private Uri fileUri; // file url to store image/video
// Permission Strings
private static final String PERMISSION_HARDWARE_CAMERA = "android.permission.CAMERA";
private static final String PERMISSION_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE";
private static final String IMAGE_URI_BUNDLE = "fileUri";
public FragmentReview() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Adding some data
setRetainInstance(true);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(IMAGE_URI_BUNDLE, fileUri);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
List<ReviewItem> currentData = mAdapter.getCurrentData();
DatabaseHandler db = new DatabaseHandler(getActivity());
Maschine updateMaschine = new Maschine();
updateMaschine = db.getMaschineForKeyMaschineAndAnlage(getIdForSelectedAnlage(), getIdForSelectedMaschine());
switch (item.getItemId()) {
case R.id.action_save:
//saving some data
return true;
case R.id.action_photo:
if (isDeviceSupportCamera()) {
boolean checkcamera = hasPermission(PERMISSION_HARDWARE_CAMERA);
boolean checkstorage = hasPermission(PERMISSION_WRITE_EXTERNAL_STORAGE);
if(hasPermission(PERMISSION_HARDWARE_CAMERA) == true && hasPermission(PERMISSION_WRITE_EXTERNAL_STORAGE)){
try {
captureImage();
} catch (Exception e) {
new MaterialDialog.Builder(getActivity())
.title("Berechtigungen nicht aktiviert")
.content("Bitte lassen Sie in den Einstellungen die notwendigen Berechtigungen zu")
.positiveText("OK")
.show();
}
} else {
new MaterialDialog.Builder(getActivity())
.title("Berechtigungen nicht aktiviert")
.content("Bitte lassen Sie in den Einstellungen die notwendigen Berechtigungen zu")
.positiveText("OK")
.show();
}
} else {
new MaterialDialog.Builder(getActivity())
.title("Fehler")
.content("Kamera konnte nicht geöffnet werden")
.positiveText("OK")
.show();
}
return false;
case R.id.action_gallery:
// starting gallery activity
return true;
default:
break;
}
return false;
}
private boolean isDeviceSupportCamera() {
if (getActivity().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
public Uri getOutputMediaFileUri(int type) {
return Uri.fromFile(getOutputMediaFile(type));
}
private static File getOutputMediaFile(int type) {
File mediaStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
if (!mediaStorageDir.mkdirs()) {
Log.d(IMAGE_DIRECTORY_NAME, "Fehler beim Erstellen der Datei: "
+ IMAGE_DIRECTORY_NAME + " directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
} else {
return null;
}
return mediaFile;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
try{
// if the result is capturing Image
if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
DatabaseHandler db = new DatabaseHandler(getActivity());
db.addImage(getIdForSelectedAnlage(), getIdForSelectedMaschine(), fileUri.toString());
Toast.makeText(getActivity(),
"Bild wurde gespeichert" + fileUri.toString(), Toast.LENGTH_SHORT)
.show();
//previewCapturedImage();
} else if (resultCode == Activity.RESULT_CANCELED) {
// user cancelled Image capture
/* Toast.makeText(getActivity(),
"User cancelled image capture", Toast.LENGTH_SHORT)
.show(); */
} else {
// failed to capture image
/* Toast.makeText(getActivity(),
"Sorry! Failed to capture image", Toast.LENGTH_SHORT)
.show(); */
}
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getActivity(),
"Datei konnte nicht in Datenbank gespeichert werden", Toast.LENGTH_SHORT)
.show();
}
}
public boolean hasPermission(String permission)
{
try {
PackageInfo info = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), PackageManager.GET_PERMISSIONS);
if (info.requestedPermissions != null) {
for (String p : info.requestedPermissions) {
if (p.equals(permission)) {
return true;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
最佳答案
我遇到过这个问题。 带有 os 5.0.1 的 Samsung Galaxy S4 有特定问题,当相机流打开时,屏幕方向多次更改,我们的 Activity 正在重新创建,这是根本原因。
尝试保存和恢复imageUri:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
imageUri = savedInstanceState.getParcelable(IMAGE_URI_BUNDLE);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(IMAGE_URI_BUNDLE, imageUri);
}
你应该在启动相机 Intent 之前初始化 imageUri
private void captureImage() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri );
// start the image capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
}
在 fragment 中从相机捕获图像时要小心,在这种情况下,您还应该在 fragment 中保存和恢复 imageUri 并添加到 Activity 中:
fragment.setRetainInstance(true);
关于Android 默认相机崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34276274/