android中的java.lang.OutOfMemoryError,同时从android中的画廊获取图像
Posted
技术标签:
【中文标题】android中的java.lang.OutOfMemoryError,同时从android中的画廊获取图像【英文标题】:java.lang.OutOfMemoryError in android while getting image from gallery in android 【发布时间】:2012-12-12 15:07:35 【问题描述】:我正在使用代码从图库中挑选图片
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery);
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, SELECT_PICTURE);
public void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == SELECT_PICTURE && resultCode == RESULT_OK && null != data)
Uri selectedImage = data.getData();
String[] filePathColumn = MediaStore.Images.Media.DATA ;
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
picturePath = cursor.getString(columnIndex);
cursor.close();
Log.v("picturePath", "picturePath: " + picturePath);
Bitmap bitmap = BitmapFactory.decodeFile(picturePath);
Intent intentUpload = new Intent(GalleryActivity.this, UploadActivity.class);
// intentUpload.putExtra("BitmapImage", bitmap);
MyApplicationGlobal.bitmap = bitmap;
startActivity(intentUpload);
finish();
public String getPath(Uri uri)
String[] projection = MediaStore.Images.Media.DATA ;
Cursor cursor = managedQuery(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
但我遇到了错误
FATAL EXCEPTION: main
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:324)
at com.markphoto_activities.GalleryActivity.onActivityResult(GalleryActivity.java:59)
at android.app.Activity.dispatchActivityResult(Activity.java:4541)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2740)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:2787)
at android.app.ActivityThread.access$2000(ActivityThread.java:122)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1032)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
原木猫是
: E/dalvikvm-heap(2487): Out of memory on a 17915920-byte allocation.
"main" prio=5 tid=1 RUNNABLE
| group="main" sCount=0 dsCount=0 obj=0x400d5638 self=0x126c8
| sysTid=2487 nice=0 sched=0/0 cgrp=default handle=-1342909336
| schedstat=( 2650512000 283442000 1204 ) utm=226 stm=39 core=1
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:324)
at com.markphoto_activities.GalleryActivity.onActivityResult(GalleryActivity.java:59)
at android.app.Activity.dispatchActivityResult(Activity.java:4541)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2740)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:2787)
at android.app.ActivityThread.access$2000(ActivityThread.java:122)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1032)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
: D/skia(2487): libjpeg error 105 < Ss=%d, Se=%d, Ah=%d, Al=%d> from allocPixelRef [3456 2592]
: D/skia(2487): --- decoder->decode returned false
: D/AndroidRuntime(2487): Shutting down VM
【问题讨论】:
@DipakKeshariya 嘿,你的回答是正确的,正是我想要的。但普拉蒂克的回答要好一些。所以我接受了,对不起,我不能接受另一个,所以只赞成 【参考方案1】:试试这个:
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent imageReturnedIntent)
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode)
case SELECT_PHOTO:
if (resultCode == RESULT_OK)
Uri selectedImage = imageReturnedIntent.getData();
try
picImageView.setImageBitmap(decodeUri(selectedImage));
catch (FileNotFoundException e)
e.printStackTrace();
然后声明如下函数:
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o);
final int REQUIRED_SIZE = 100;
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;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
return BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o2);
谢谢。
【讨论】:
您好,我之前在 SO:while(true)
上看到过这段代码 sn-p,if(condition)
到 break;
,真的很伤我的眼睛。您可以简单地将相反的条件放在 while 循环中,这样您就不再需要那个 break 了。在这种情况下:while (!(width_tmp / 2 < REQUIRED_SIZE && height_tmp / 2 < REQUIRED_SIZE)) ...
Cheers =) 这使您的代码更具可读性并且它是语义(!)。随意分享你的想法,我希望你们能理解我想表达的意思。
如何知道reqHeight和reqWidth?我的意思是我们需要将其修复为静态值吗?或者我们可以改变那些 w.r.t 设备?【参考方案2】:
您尝试加载的图像太大。它导致堆大小迅速增长并填满,从而导致应用程序崩溃。 尝试缩小图像然后加载它。
可以使用如下代码sn-p:
public static Bitmap getResizedBitmap(Bitmap image, int newHeight, int newWidth)
int width = image.getWidth();
int height = image.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(image, 0, 0, width, height,
matrix, false);
return resizedBitmap;
【讨论】:
【参考方案3】:将下面的函数添加到你的java文件中,并在获取图像路径或图像uri后在onActivityResult()
中调用这个函数,它将解决你的问题。
private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o);
// The new size we want to scale to
final int REQUIRED_SIZE = 100;
// Find the correct scale value. It should be the power of 2.
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;
return BitmapFactory.decodeStream(
getContentResolver().openInputStream(selectedImage), null, o2);
【讨论】:
如何知道reqHeight和reqWidth?我的意思是我们需要将其修复为静态值吗?或者我们可以改变那些 w.r.t 设备?【参考方案4】:试试这个方法...
@Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent)
int orientation =0;
super.onActivityResult(requestCode, resultcode, intent);
if (requestCode == 1)
if (intent != null && resultcode == RESULT_OK)
Uri selectedImage = intent.getData();
String[] filePathColumn = MediaStore.Images.Media.DATA;
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
Log.v("log","filePath is : "+filePath);
cursor.close();
try
ExifInterface exif = new ExifInterface(filePath);
orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
//Toast.makeText(getApplicationContext(), ""+orientation, 1).show();
Log.v("log", "ort is "+orientation);
catch (IOException e)
e.printStackTrace();
if(bmp != null && !bmp.isRecycled())
bmp = null;
File f = new File(filePath);
bmp = decodeFile(f,300,420);
这是解码功能...
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT)
try
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
catch (FileNotFoundException e)
return null;
【讨论】:
如何知道reqHeight和reqWidth?我的意思是我们需要将其修复为静态值吗?或者我们可以改变那些 w.r.t 设备?以上是关于android中的java.lang.OutOfMemoryError,同时从android中的画廊获取图像的主要内容,如果未能解决你的问题,请参考以下文章