I have a program that is supposed to grab an image from a user's gallery and then display the image in a subsequent activity. As part of my testing, I try to do the operation twice in a row: in ViewImageActivity I click on the button that takes me to the gallery; pick an image; then see the image in FriendsActivity. Then I click the back button and repeat the process. The second time around I always get a ava.lang.OutOfMemoryError
. I am including the error log:
04-26 09:43:57.911: W/dalvikvm(30841): threadid=1: thread exiting with uncaught exception (group=0x40c231f8)
04-26 09:43:57.918: E/AndroidRuntime(30841): FATAL EXCEPTION: main
04-26 09:43:57.918: E/AndroidRuntime(30841): java.lang.OutOfMemoryError
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:324)
04-26 09:43:57.918: E/AndroidRuntime(30841): at com.example.game.utils.FileUtils.imageFromGallery(FileUtils.java:87)
04-26 09:43:57.918: E/AndroidRuntime(30841): at com.example.game.utils.FileUtils.unmarshallBitmap(FileUtils.java:71)
04-26 09:43:57.918: E/AndroidRuntime(30841): at com.example.game.FriendsActivity.onCreate(FriendsActivity.java:46)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.Activity.performCreate(Activity.java:4638)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1051)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1940)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2001)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.ActivityThread.access$600(ActivityThread.java:129)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1153)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.os.Handler.dispatchMessage(Handler.java:99)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.os.Looper.loop(Looper.java:137)
04-26 09:43:57.918: E/AndroidRuntime(30841): at android.app.ActivityThread.main(ActivityThread.java:4516)
04-26 09:43:57.918: E/AndroidRuntime(30841): at java.lang.reflect.Method.invokeNative(Native Method)
04-26 09:43:57.918: E/AndroidRuntime(30841): at java.lang.reflect.Method.invoke(Method.java:511)
04-26 09:43:57.918: E/AndroidRuntime(30841): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
04-26 09:43:57.918: E/AndroidRuntime(30841): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
04-26 09:43:57.918: E/AndroidRuntime(30841): at dalvik.system.NativeStart.main(Native Method)
04-26 09:44:00.997: I/Process(30841): Sending signal. PID: 30841 SIG: 9
My program is written like so:
ViewImageActivity dispatch intent to get photo from image gallery; then onActivityResult calls FriendsActivity. FriendsActivity in turn calls FileUtils's static method unmarshallBitmap
to get the image for displaying. See following snippets:
ViewImageActivity:
public void dispatchGalleryIntent(View view) {
Intent gallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(gallery, LOAD_IMAGE_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == LOAD_IMAGE_REQUEST_CODE) {
imageUri = data.getData();
}
dispatchIntentToFriendsActivity();
}
}
private void dispatchIntentTo FriendsActivity() {
Intent intent = new Intent(this, FriendsActivity.class);
intent.putExtra(IMAGE_URI, imageUri);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
FriendsActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_friends);
Uri imageUri = (Uri) getIntent().getExtras().get(IMAGE_URI);
myImage = FileUtils.unmarshallBitmap(imageUri, getContentResolver());
...
}
FileUtils
public static Bitmap unmarshallBitmap(Uri imageUri, ContentResolver resolver) {
return imageFromGallery(imageUri, resolver);
}
private static Bitmap imageFromGallery(Uri imageUri, ContentResolver resolver) {
try {
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = resolver.query(imageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
return BitmapFactory.decodeFile(picturePath);
} catch (Exception x) {
return null;
}
}
BTW: I already saw How to solve the Out of Memory issue while displaying image in android?. My image loads fine the first time. The problem is if user change their mind and decide to choose a different image (back button and repeat), then the app crash as explained above.