Galaxy note 1(基于AOSP的ROM)上的Android中的OutOfMemoryError在尝试稍微提高分辨率时出错

Galaxy note 1(基于AOSP的ROM)上的Android中的OutOfMemoryError在尝试稍微提高分辨率时出错,android,bitmap,android-camera,resolution,Android,Bitmap,Android Camera,Resolution,我一直在安卓上处理图像,这已经有好几天了,我似乎无法解决它 在我的应用程序中有一个添加照片按钮。当用户点击它时,她可以从图库中选择一张照片,或者用相机拍摄一张新照片 但是为了避免出现内存错误,我不得不降低分辨率,以至于发送到服务器的图片几乎只不过是一个缩略图 在这一行中,当我将200更改为250时,它给出了提到的错误! 位图缩放=位图.createScaledBitmapbitmap2,200,200,true 该错误发生在Android 4.2+上,而不是较低级别的Android上。它在安卓4

我一直在安卓上处理图像,这已经有好几天了,我似乎无法解决它

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

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

在这一行中,当我将200更改为250时,它给出了提到的错误! 位图缩放=位图.createScaledBitmapbitmap2,200,200,true


该错误发生在Android 4.2+上,而不是较低级别的Android上。它在安卓4.1上运行得非常好,即使有400400

我的代码哪部分是错的

代码如下:

 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上。它在安卓4.1上运行得非常好,即使有400400-不,当你没有足够的内存时,它会出现在任何版本的安卓上。您是否有足够的内存将由许多因素决定,包括进程的堆限制以及您在执行此工作之前在该进程中所做的工作。OutOfMemoryError与Android版本之间没有紧密的联系。您需要的是优化代码,因为当您加载到应用程序中的许多图像时,OutOfMemoryError通常会发生。@rekire:这个活动是我唯一有图像的地方。可以多次调用onClickTakePicture。但我在第一次通话时就出错了。有什么优化建议吗?我循环使用位图。这就是我对优化的全部了解。我的老板会杀了我的。请看一下这个:它可能会有帮助:我已经读过了。我不知道的是如何获得这个剩余,因为我的imageView中仍然没有图像。我应该从uri获取id吗?能做到吗?因为我没有找到任何指南。我的图像是保存在设备上的文件。我拥有的是它们的Uri,如何从Uri实现代码中的这个剩余部分?我没有找到任何可以引导我完成这一过程的东西。@Tina你读过BitmapFactory类吗?始终可以使用BitmapFactory.decodeFile而不是BitmapFactory.decodeResource。
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);
}