从Android摄像头拍摄多张照片后应用程序崩溃
我正在为Android开发一个应用程序,该应用程序应该从摄像头拍摄照片,并将这些图像用作应用程序的个人资料图片。然而,该应用程序在前3-4张照片中运行良好,但当我尝试拍摄更多照片时,该应用程序崩溃。原因是内存泄漏 以下是摄像头启动意图的代码:从Android摄像头拍摄多张照片后应用程序崩溃,android,android-camera,Android,Android Camera,我正在为Android开发一个应用程序,该应用程序应该从摄像头拍摄照片,并将这些图像用作应用程序的个人资料图片。然而,该应用程序在前3-4张照片中运行良好,但当我尝试拍摄更多照片时,该应用程序崩溃。原因是内存泄漏 以下是摄像头启动意图的代码: String fileName = "temp.jpg"; ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, fileName); m
String fileName = "temp.jpg";
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
mCapturedImageURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
startActivityForResult(takePictureIntent,RESULT_LOAD_IMAGE_CAMERA);
以下是接收意向书的代码:
if (requestCode == RESULT_LOAD_IMAGE_CAMERA && resultCode == RESULT_OK ) {
String[] projection = { MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery(mCapturedImageURI, projection, null, null, null);
final int column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
String capturedImageFilePath = cursor.getString(column_index_data);
profilePic.setImageURI(Uri.fromFile(new File(capturedImageFilePath)));
}
以下是日志:
02-28 18:28:36.727: E/dalvikvm-heap(4081): 9830400-byte external allocation too large for this process.
02-28 18:28:36.727: E/GraphicsJNI(4081): VM won't let us allocate 9830400 bytes
02-28 18:28:36.824: E/AndroidRuntime(4081): FATAL EXCEPTION: main
02-28 18:28:36.824: E/AndroidRuntime(4081): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:562)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:426)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.graphics.drawable.Drawable.createFromStream(Drawable.java:657)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.widget.ImageView.resolveUri(ImageView.java:509)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.widget.ImageView.setImageURI(ImageView.java:293)
02-28 18:28:36.824: E/AndroidRuntime(4081): at com.octanetech.cortes.ProfileActivity.onActivityResult(ProfileActivity.java:596)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.app.Activity.dispatchActivityResult(Activity.java:3890)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.app.ActivityThread.deliverResults(ActivityThread.java:3511)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3557)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.app.ActivityThread.access$2800(ActivityThread.java:125)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2063)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.os.Handler.dispatchMessage(Handler.java:99)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.os.Looper.loop(Looper.java:123)
02-28 18:28:36.824: E/AndroidRuntime(4081): at android.app.ActivityThread.main(ActivityThread.java:4627)
02-28 18:28:36.824: E/AndroidRuntime(4081): at java.lang.reflect.Method.invokeNative(Native Method)
02-28 18:28:36.824: E/AndroidRuntime(4081): at java.lang.reflect.Method.invoke(Method.java:521)
02-28 18:28:36.824: E/AndroidRuntime(4081): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
02-28 18:28:36.824: E/AndroidRuntime(4081): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
02-28 18:28:36.824: E/AndroidRuntime(4081): at dalvik.system.NativeStart.main(Native Method)
非常感谢您的帮助。请更换此线路
profilePic.setImageURI(Uri.fromFile(new File(capturedImageFilePath)));
您直接从SD卡加载图像,它的大小可能太大,从而导致内存问题
试试这个
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize=8; // 1/8 of original image
Bitmap b = BitmapFactory.decodeFile(capturedImageFilePath,options);
profilePic.setImageBitmap(b);
更换这条线
profilePic.setImageURI(Uri.fromFile(new File(capturedImageFilePath)));
您直接从SD卡加载图像,它的大小可能太大,从而导致内存问题
试试这个
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize=8; // 1/8 of original image
Bitmap b = BitmapFactory.decodeFile(capturedImageFilePath,options);
profilePic.setImageBitmap(b);
尝试使用inSampleSize缩放较大的位图,如下所示: 摘自@Fedor的懒惰列表的片段 public int inSampleSize 如果设置为大于1的值,则请求解码器对原始图像进行二次采样,并返回一个较小的图像以节省内存
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
//解码图像并对其进行缩放以减少内存消耗
私有位图解码文件(文件f){
试一试{
//解码图像大小
BitmapFactory.Options o=新的BitmapFactory.Options();
o、 inJustDecodeBounds=true;
FileInputStream stream1=新的FileInputStream(f);
解码流(stream1,null,o);
stream1.close();
//找到正确的刻度值。它应该是2的幂。
所需的最终int_尺寸=70;
内部宽度=o.向外宽度,高度=o.向外高度;
int标度=1;
while(true){
如果(width_tmp/2尝试使用inSampleSize缩放较大的位图,如下所示:
摘自@Fedor的懒惰列表的片段
public int inSampleSize
如果设置为大于1的值,则请求解码器对原始图像进行二次采样,并返回一个较小的图像以节省内存
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
//解码图像并对其进行缩放以减少内存消耗
私有位图解码文件(文件f){
试一试{
//解码图像大小
BitmapFactory.Options o=新的BitmapFactory.Options();
o、 inJustDecodeBounds=true;
FileInputStream stream1=新的FileInputStream(f);
解码流(stream1,null,o);
stream1.close();
//找到正确的刻度值。它应该是2的幂。
所需的最终int_尺寸=70;
内部宽度=o.向外宽度,高度=o.向外高度;
int标度=1;
while(true){
如果(width_tmp/2最后我自己解决了这个问题。导致内存泄漏的主要问题是我没有回收位图对象。我只是用另一个位图图像替换位图对象。虽然该对象被另一个位图图像替换,但仍然存在以前的位图图像所以,从相机上拍摄多幅图像时,位图图像会堆积起来,并引发内存不足的异常
因此,在将新图像分配给位图对象之前,我玩了一个循环(删除)位图图像的技巧。
我刚用过
mImageBitmap.recycle();
这清除了以前的位图图像,没有发生内存泄漏。希望它也能帮助其他人。最后我自己解决了这个问题。导致内存泄漏的主要问题是我没有回收位图对象。我只是用另一个位图图像替换位图对象。你当对象被另一个位图图像替换时,内存中仍然存在前一个位图图像。因此,从相机拍摄多个图像时,位图图像堆积并引发内存不足的异常
因此,在将新图像分配给位图对象之前,我玩了一个循环(删除)位图图像的技巧。
我刚用过
mImageBitmap.recycle();
这刷新了以前的位图图像,没有发生内存泄漏。希望这对其他人也有帮助。你有机会阅读此图片吗?你有机会阅读此图片吗?谢谢你的回复。我不太关心内存大小,我更担心的是内存泄漏正在发生。不知怎的,这张图片是由c捕获的amera没有在垃圾收集中被删除。它存储在应用程序的内存中。我们可以采用这种方法,但它只会将我的应用程序崩溃延迟8倍,而不会完全阻止它。感谢您的回复。我不太关心内存的大小,我更担心的是内存泄漏正在发生。一些相机拍摄的图像如何在垃圾收集中不被移除。它被存储在应用程序的内存中。我们可以采用这种方法,但它只会将我的应用程序崩溃延迟8倍,而不会完全阻止它。谢谢你的回复。我不太关心内存的大小,我更担心的是内存泄漏正在发生。不知何故,摄像头捕获的图像没有在垃圾收集中被删除。它被存储在应用程序的内存中。我们可以采用这种方法,但它只会延迟我的应用程序崩溃,而不会完全阻止它。感谢您的回复。我不太关心备忘录的大小ry,我更担心的是内存泄漏正在发生。不知何故,摄像头捕获的图像没有在垃圾收集中被删除。它被存储在应用程序的内存中。我们可以采用这种方法,但它只会延迟应用程序的崩溃,而不会完全阻止它。