我发布了一个应用程序,其中一个基本功能是允许用户拍照,然后将该照片保存在外部存储的特定文件夹中。
一切似乎都运转良好,但我现在已经收到两份报告声称在拍照后点击“完成”退出相机(然后返回活动),应用程序被强制关闭,将用户带回主屏幕。
这发生在Samsung Nexus S和Galaxy Tab上。下面我发布了我的代码,以显示我设置我的意图以及如何在onActivityResult()中处理保存和显示照片。任何关于在点击“完成”退出相机应用程序后可能导致崩溃的指导,将不胜感激!
同样,这似乎在大多数设备上运行良好,但我想知道它们是否是一种更有效,更普遍的方法,我应该采取。谢谢
我是如何解雇相机意图
case ACTION_BAR_CAMERA:
// numbered image name
fileName = "image_" + String.valueOf(numImages) + ".jpg";
output = new File(direct + File.separator + fileName); // create
// output
while (output.exists()) { // while the file exists
numImages++; // increment number of images
fileName = "image_" + String.valueOf(numImages) + ".jpg";
output = new File(outputFolder, fileName);
}
camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
uriSavedImage = Uri.fromFile(output); // get Uri of the output
camera.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage); //pass in Uri to camera intent
startActivityForResult(camera, 1);
break;
default:
return super.onHandleActionBarItemClick(item, position);
}
return true;
}
我如何设置onActivityResult()
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) { // If data was passed successfully
Bundle extras = data.getExtras();
//Bundle extras = data.getBundleExtra(MediaStore.EXTRA_OUTPUT);
/*ad = new AlertDialog.Builder(this).create();
ad.setIcon(android.R.drawable.ic_menu_camera);
ad.setTitle("Save Image");
ad.setMessage("Save This Image To Album?");
ad.setButton("Ok", this);
ad.show();*/
bmp = (Bitmap) extras.get("data"); // Set the bitmap to the bundle
// of data that was just
// received
image.setImageBitmap(bmp); // Set imageview to image that was
// captured
image.setScaleType(ScaleType.FIT_XY);
}
}
答案 0 :(得分:35)
首先让我们说清楚 - 我们有两个选项可以从相机的onActivityResult中获取图像数据:
1。 通过传递您要保存的图像的确切位置Uri来启动相机。
2。 刚启动相机不会传递任何Loaction Uri。
1。在第一种情况下:
通过将图像Uri传递到要保存的位置来启动相机:
String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/picture.jpg";
File imageFile = new File(imageFilePath);
Uri imageFileUri = Uri.fromFile(imageFile); // convert path to Uri
Intent it = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
it.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);
startActivityForResult(it, CAMERA_RESULT);
在onActivityResult中接收图像:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (RESULT_OK == resultCode) {
iv = (ImageView) findViewById(R.id.ReturnedImageView);
// Decode it for real
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = false;
//imageFilePath image path which you pass with intent
Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
// Display it
iv.setImageBitmap(bmp);
}
}
2。在第二种情况下:
如果要在Intent(数据)中接收图像,请启动相机而不传递图像Uri:
Intent it = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(it, CAMERA_RESULT);
在onActivityResult中将图片恢复为:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (RESULT_OK == resultCode) {
// Get Extra from the intent
Bundle extras = data.getExtras();
// Get the returned image from extra
Bitmap bmp = (Bitmap) extras.get("data");
iv = (ImageView) findViewById(R.id.ReturnedImageView);
iv.setImageBitmap(bmp);
}
}
<小时/> *****快乐的编码!!!! *****
答案 1 :(得分:4)
在相机按钮点击事件中,您可以尝试:
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(getTempFile(this)));
startActivityForResult(intent, TAKE_PHOTO_CODE);
declare TAKE_PHOTO_CODE globally as:
private static final int TAKE_PHOTO_CODE = 1;
在代码中添加getTempFile函数,这将有助于保存您在名为app的包名称的文件夹下单击sdcard的名为myImage.png的图像。
private File getTempFile(Context context) {
final File path = new File(Environment.getExternalStorageDirectory(),
context.getPackageName());
if (!path.exists()) {
path.mkdir();
}
return new File(path, "myImage.png");
}
现在在OnActivityResult函数上添加:
if (requestCode == TAKE_PHOTO_CODE) {
final File file = getTempFile(this);
try {
Uri uri = Uri.fromFile(file);
Bitmap captureBmp = Media.getBitmap(getContentResolver(),
uri);
image.setImageBitmap(captureBmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
如果您遇到内存问题而不是添加以下代码:
@Override
protected void onPause() {
image.setImageURI(null);
super.onPause();
}
我希望这会对你有所帮助
答案 2 :(得分:3)
我怀疑3个可能的问题可能会造成您的问题:
当您使用null
方法拨打extras.get("data");
时,有些设备会返回onActivityResult
,因此您的问题可能是NullPointerException
。要解决此问题,您需要传递确切的URI
位置,以告知相机应用在哪里存储并在onActivityResult
中使用它来将图像检索为Bitmap
。
在Bitmap
extras.get("data");
时,其他一些设备会返回完整尺寸onActivityResult
。如果位图太大而导致OutOfMemmoryError
,那么您可能需要以较小的尺寸解码图像,以免占用如此多的内存堆。在这种情况下,这两个链接可以帮助您:
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
您的活动可能会被GC
破坏,因此您必须使用onSavedInstanceState
和onRestoreInstanceState
来保存Activity
的数据。有关详细信息,请参阅this previous post的答案。
我不知道你是否已经处理过这些问题。
希望有所帮助:)
答案 3 :(得分:1)
首先,请务必检查请求代码,您可能会在那里捕获其他人的结果。其次,不要使用intent的数据Bitmap - 如果有的话,它很小,但由于你提供了存储捕获图像的路径,它甚至不应该存在(参见here)。因此,当您收到 请求的RESULT_OK时,将您提供的网址存储为输出文件路径并从那里读取位图:
...
// save your file uri, not necessarily static
mUriSavedImage = Uri.fromFile(output);
startActivityForResult(camera, MY_REQUEST_CODE);
/* Make a String like "com.myname.MY_REQUEST_CODE" and hash it into int to give it
a bit of uniqueness */
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Bitmap bmp = BitmapFactory.decodeFile(mUriSavedImage);
if (bmp != null) {
image.setImageBitmap(bmp); // Set imageview to image that was
// captured
image.setScaleType(ScaleType.FIT_XY);
} else {
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
答案 4 :(得分:0)
我遇到了同样的问题。显然,修复方法是将uriSavedImage设置为静态。不确定这是不是最好的方法。但这对我有用。
答案 5 :(得分:0)
按照此link上给出的步骤操作。希望这对你有用。
OR
在不崩溃的情况下拍摄图像
在 MainActivity
中写下以下代码// Storage for camera image URI components
private final static String CAPTURED_PHOTO_PATH_KEY = "mCurrentPhotoPath";
private final static String CAPTURED_PHOTO_URI_KEY = "mCapturedImageURI";
// Required for camera operations in order to save the image file on resume.
private String mCurrentPhotoPath = null;
private Uri mCapturedImageURI = null;
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
if (mCurrentPhotoPath != null) {
savedInstanceState.putString(CAPTURED_PHOTO_PATH_KEY, mCurrentPhotoPath);
}
if (mCapturedImageURI != null) {
savedInstanceState.putString(CAPTURED_PHOTO_URI_KEY, mCapturedImageURI.toString());
}
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey(CAPTURED_PHOTO_PATH_KEY)) {
mCurrentPhotoPath = savedInstanceState.getString(CAPTURED_PHOTO_PATH_KEY);
}
if (savedInstanceState.containsKey(CAPTURED_PHOTO_URI_KEY)) {
mCapturedImageURI = Uri.parse(savedInstanceState.getString(CAPTURED_PHOTO_URI_KEY));
}
super.onRestoreInstanceState(savedInstanceState);
}
答案 6 :(得分:0)
大家好,我知道答案已经给出,但这也是我找到的最简单的解决方案之一
这是一个关于设备自我烦恼的例子!
AndroidCameraUtils - 下载项目并从库项目中包含以下内容,您可以使用以下代码片段!
private void setupCameraIntentHelper(){ mCameraIntentHelper = new CameraIntentHelper(this,new CameraIntentHelperCallback(){ @覆盖 public void onPhotoUriFound(Date dateCameraIntentStarted,Uri photoUri,int rotateXDegrees){ messageView.setText(getString(R.string.activity_camera_intent_photo_uri_found)+ photoUri.toString());
Bitmap photo = BitmapHelper.readBitmap(CameraIntentActivity.this, photoUri);
if (photo != null) {
photo = BitmapHelper.shrinkBitmap(photo, 300, rotateXDegrees);
ImageView imageView = (ImageView) findViewById(de.ecotastic.android.camerautil.sample.R.id.activity_camera_intent_image_view);
imageView.setImageBitmap(photo);
}
}
@Override
public void deletePhotoWithUri(Uri photoUri) {
BitmapHelper.deleteImageWithUriIfExists(photoUri, CameraIntentActivity.this);
}
@Override
public void onSdCardNotMounted() {
Toast.makeText(getApplicationContext(), getString(R.string.error_sd_card_not_mounted), Toast.LENGTH_LONG).show();
}
@Override
public void onCanceled() {
Toast.makeText(getApplicationContext(), getString(R.string.warning_camera_intent_canceled), Toast.LENGTH_LONG).show();
}
@Override
public void onCouldNotTakePhoto() {
Toast.makeText(getApplicationContext(), getString(R.string.error_could_not_take_photo), Toast.LENGTH_LONG).show();
}
@Override
public void onPhotoUriNotFound() {
messageView.setText(getString(R.string.activity_camera_intent_photo_uri_not_found));
}
@Override
public void logException(Exception e) {
Toast.makeText(getApplicationContext(), getString(R.string.error_sth_went_wrong), Toast.LENGTH_LONG).show();
Log.d(getClass().getName(), e.getMessage());
}
});
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
mCameraIntentHelper.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mCameraIntentHelper.onRestoreInstanceState(savedInstanceState);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
mCameraIntentHelper.onActivityResult(requestCode, resultCode, intent);
}
}
注意: - 我尝试了许多相机工具的例子,当然还有另外一种方法可以处理它但是对于初学者和那些对核心概念不太熟悉的人来说会更舒适项目。谢谢!
答案 7 :(得分:0)
对于Samsung设备,请在AndroidManifest.xml文件中的第一行以下添加
android:configChanges =“ orientation | screenSize”
我希望这对您有用