2013-02-28 3 views
1

Я разрабатываю приложение для Android, которое должно снимать с камеры и использовать эти изображения в качестве фотографий профиля для приложения. Однако приложение работает отлично для первых 3-4 снимков, но когда я пытаюсь сделать больше снимков, приложение разбивается. Причина - утечка памяти.Сбой приложения после съемки нескольких фотографий с камеры Android

Вот код для исходного намерения камеры:

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) 

Любой помощь будет высоко оценена.

+0

У вас была возможность прочитать это? http://stackoverflow.com/questions/4511057/android-out-of-memory-on-image-capture – appsroxcom

ответ

3

Наконец я решил проблему сам. Основная проблема, вызвавшая утечку памяти, заключается в том, что я не перерабатывал растровые объекты. Я был просто , заменив растровый объект другим растровым изображением. Думал, что объект был заменен другим растровым изображением, однако в памяти сохранилось предыдущее изображение растрового изображения. Таким образом, при съемке нескольких изображений с камеры, растровые изображения складываются и возникают исключение из памяти.

Поэтому я сыграл трюк, чтобы переработать (удалить) изображение растрового изображения, прежде чем назначать новое изображение объекту Bitmap. я просто использовал

mImageBitmap.recycle(); 

Это смывает предыдущий растровое изображение и не произошло утечки памяти. Надеюсь, это помогло и другим.

3

Заменить эту линию

profilePic.setImageURI(Uri.fromFile(new File(capturedImageFilePath))); 

Вы загружаете изображения с SDCard непосредственно, и это может быть большим по размеру, что вызывает проблемы с памятью.

Попробуйте

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize=8;  // 1/8 of original image 
Bitmap b = BitmapFactory.decodeFile(capturedImageFilePath,options); 
profilePic.setImageBitmap(b); 
+0

Спасибо за ответ. Я не очень беспокоюсь о размере памяти, мои большие опасения связаны с тем, что происходит утечка памяти. Каким-то образом изображение, которое снимается камерой, не удаляется в сборке мусора. Он хранится в памяти приложения. Мы можем следовать этому подходу, но это только задержит крах моего приложения в 8 раз, чтобы не предотвратить его полностью. –

0

Попробуйте уменьшить ваши большие растровые изображения с помощью inSampleSize следующим образом: Отрывок взят из @ ленивым списка Федора https://github.com/thest1/LazyList/blob/master/src/com/fedorvlasov/lazylist/ImageLoader.java

общественности Int inSampleSize

Если установлено значение> 1, запрашивает декодер для подвыборки исходного изображения, возвращая asmaller изображение для сохранения памяти.

//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; 
    } 

Надеется, что это поможет вам:

+0

Спасибо за ответ.Я не очень беспокоюсь о размере памяти, мои большие опасения связаны с тем, что происходит утечка памяти. Каким-то образом изображение, которое снимается камерой, не удаляется в сборке мусора. Он хранится в памяти приложения. Мы можем следовать этому подходу, но это только задержит крах моего приложения, а не полностью его предотвратит. –

Смежные вопросы