【问题标题】:OutOfMemoryError in Android on Galaxy note 1 (AOSP based ROM) when try to higher the resolution for a tiny little bit当尝试提高一点点分辨率时,Galaxy note 1(基于 AOSP 的 ROM)上的 Android 中出现 OutOfMemoryError
【发布时间】:2014-12-07 12:27:57
【问题描述】:

我一直在处理Android上的图像,已经好几天了,我似乎无法解决它。

在我的应用中有一个“添加照片”按钮。当用户点击它时,她可以从图库中选择一张照片,或者用相机拍摄一张新照片。

但为了避免出现 OutOfMemoryError,我不得不降低分辨率,以至于发送到服务器的图片几乎只是一个缩略图。

当我将 200 更改为 250 时,在这一行上会出现上述错误! 位图缩放 = Bitmap.createScaledBitmap(bitmap2, 200, 200, true);

(该错误发生在 Android 4.2+ 上,而不是在较低的 Android 上。它在 Android 4.1 上运行良好,即使是 400、400)

我的代码哪一部分是错的?

代码如下:

 public class CreatePropertyActivity5 extends ActionBarActivity {
protected static final int SELECT_PICTURE = 1;
private static final int ACTIVITY_REQUEST_CODE_IMAGE = 100;
private static final int IMAGE_DESCRIPTION = 200;
LinearLayout ll; 
private List<File> cameraImageFiles;
private JSONRequestForCreatePropertyListing propertyListing;
ImageView imageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_create_property_5);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    propertyListing = (JSONRequestForCreatePropertyListing) getIntent().getSerializableExtra("JSONRequestForCreatePropertyListing");
    CreatePropertListingAsync cplp = new CreatePropertListingAsync(this, propertyListing);
    cplp.execute();

}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.create_property_activity5, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public void onClickTakePicture(View v) throws IOException {
    // Camera.
    final List<Intent> cameraIntents = new ArrayList<Intent>();
    final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);     
    final PackageManager packageManager = getPackageManager();
    final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);


    cameraImageFiles = new ArrayList<File>();

    int i=0;
    for(ResolveInfo res : listCam) {
        final String packageName = res.activityInfo.packageName;
        final Intent intent = new Intent(captureIntent);
        intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
        intent.setPackage(packageName);
        intent.putExtra(MediaStore.MEDIA_IGNORE_FILENAME, ".nomedia");

        //** below 4 lines put the uri of the camera taken picture to the EXTRA_OUTPUT 
        File cameraImageOutputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "myFileName");
        cameraImageFiles.add(cameraImageOutputFile);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraImageFiles.get(i)));
        i++;

        cameraIntents.add(intent);
    }

    // Filesystem.
    final Intent galleryIntent = new Intent();
    galleryIntent.setType("image/*");
    galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

    // Chooser of filesystem options.
    final Intent chooserIntent = Intent.createChooser(galleryIntent, "add new");

    // Add the camera options.
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
    startActivityForResult(chooserIntent, ACTIVITY_REQUEST_CODE_IMAGE);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent)
{
    ll = (LinearLayout) findViewById(R.id.llCreatePropertyImages);

    switch(requestCode) { 

    // For sending photos to server. We come here from activity51
    case IMAGE_DESCRIPTION:
        String s = imageReturnedIntent.getStringExtra("key");
        //user entered description is in "key"
        imageView.setTag(s);
        Bitmap bitmap1 = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
        ByteArrayOutputStream stream=new ByteArrayOutputStream();
        bitmap1.compress(Bitmap.CompressFormat.PNG, 90, stream);
        byte[] image=stream.toByteArray();
        String img_str = Base64.encodeToString(image, 0);

        //This part sends the picture to the server
        ArrayList<Photos> photos = new ArrayList<Photos>();
        photos.add(new Photos(new Ax(img_str)));

        int id = Integer.parseInt((String) ((TextView) findViewById(R.id.txt_property_listing_ID)).getText());
        int editPass = Integer.parseInt((String) ((TextView) findViewById(R.id.txt_property_listing_password)).getText());
        JSONRequestForAddPhoto jr = new JSONRequestForAddPhoto(id, editPass, photos);

        new AddPhotoAsync(this, jr).execute();
        break;

    //For choosing photos from gallery or taking one with camera
    case ACTIVITY_REQUEST_CODE_IMAGE:
        if(resultCode == RESULT_OK){

            Uri uri = null;
            if(imageReturnedIntent == null){   //since we used EXTRA_OUTPUT for camera, so it will be null

                for(int i=0;i<cameraImageFiles.size();i++){
                    if(cameraImageFiles.get(i).exists()){
                        uri = Uri.fromFile(cameraImageFiles.get(i));
                        break;
                    }
                }
            }
            else {  // from gallery
                uri = imageReturnedIntent.getData();
            }

            if(uri != null){
                imageView = new ImageView(this);
                imageView.setPadding(0, 10, 0, 0);
                ll.setVisibility(View.VISIBLE);
                try {

                    Bitmap bitmap2 = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
                    Bitmap scaled = Bitmap.createScaledBitmap(bitmap2, 250, 250, true);
                    bitmap2.recycle();
                    imageView.setImageBitmap(scaled);
                    ll.addView(imageView);

                    //*** show activity51
                    Intent i= new Intent(this, CreatePropertyActivity51.class);
                    i.putExtra("photo", scaled);


                    startActivityForResult(i,IMAGE_DESCRIPTION);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }


            }
        }
    }
}

【问题讨论】:

  • 200x200 甚至 400x400 非常小,您可能正在泄漏内存。你会记住多少张图片?
  • “该错误发生在 Android 4.2+ 上,而不是在较低的 Android 上。它在 Android 4.1 上运行良好,即使是 400、400”——不,它会在任何版本的 Android 上发生,当你没有足够的内存。您是否有足够的内存将取决于许多因素,包括您的进程的堆限制以及在执行此工作之前您在该进程中所做的工作。您的OutOfMemoryError 与 Android 版本之间没有紧密联系。
  • 您需要优化您的代码,因为当您在应用程序中加载许多图像时,通常会发生 outOfMemoryError。
  • @rekire : 这个活动是我唯一有图像的地方。 onClickTakePicture() 可以被多次调用。但我第一次打电话就出错了。

标签: android bitmap android-camera resolution


【解决方案1】:

我认为你的代码没有错,但可以优化。但如果你处理一些大图像,我建议你看看这个答案:https://stackoverflow.com/a/27270469/2101822

【讨论】:

  • 有什么优化建议吗?我回收位图。这就是我所知道的关于优化的全部内容。
  • 我的老板要杀了我。请看看这个:developer.android.com/training/displaying-bitmaps/… 它可能会有所帮助
  • :))我已经读过了。我不知道如何获取这个 resId,因为我的 imageView 中仍然没有图像。我应该从 uri 获取 id 吗?可以吗?因为我没有找到任何指南。
【解决方案2】:

我查看了您的代码,但您没有按照开发者网站中提到的方式进行操作。
如何load large bitmaps efficiently

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}

先试试吧!

【讨论】:

  • 我的图片是保存在设备上的文件。我所拥有的是他们的 Uri,如何从 Uri 实现代码中的这个 resId?我没有找到任何指导。
  • @Tina 你读过 BitmapFactory 类吗?您始终可以使用 BitmapFactory.decodeFile() 而不是 BitmapFactory.decodeResource() 。
猜你喜欢
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
相关资源
最近更新 更多