使用后置摄像头时发生致命异常 java.lang.outofmemory

fatal exception java.lang.outofmemory when using back camera

我制作了一个 android 应用程序来捕获图像并在图像上添加标题。当我从手机摄像头使用时应用程序正常工作,但是当我使用后置摄像头时应用程序崩溃并出现错误 java.lang.outofmemory 我的代码在这里

public class MainActivity extends AppCompatActivity {

private ImageView imageResult;
Bitmap processedBitmap;
String photoName;
Uri source1;
private String pictureImagePath = "";
File imgFile;

/**
 * ATTENTION: This was auto-generated to implement the App Indexing API.
 * See https://g.co/AppIndexing/AndroidStudio for more information.
 */
private GoogleApiClient client;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageResult = (ImageView) this.findViewById(R.id.imageView1);
    Button takePicture = (Button) this.findViewById(R.id.btnTakePic);
    Button renamePicture = (Button) this.findViewById(R.id.btnRename);
    Button savePicture = (Button) this.findViewById(R.id.btnSave);
    final File myDir=new File("/sdcard/saved_images");
    myDir.mkdirs();
    File myDirTemp = new File("/sdcard/saved_images/Temp");
    myDirTemp.mkdirs();

    takePicture.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = timeStamp + ".jpg";
            File storageDir = new File("/sdcard/saved_images/Temp");
            pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
            File file = new File(pictureImagePath);
            Uri outputFileUri = Uri.fromFile(file);
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
            startActivityForResult(cameraIntent, 1);


        }
    });
    renamePicture.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            if(source1!=null){
                AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
                final EditText input = new EditText(MainActivity.this);
                input.setInputType(InputType.TYPE_CLASS_NUMBER);
                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.MATCH_PARENT,
                        LinearLayout.LayoutParams.MATCH_PARENT);
                input.setLayoutParams(lp);
                dialog.setView(input);
                dialog.setCancelable(false);
                dialog.setTitle("Rename Photo");
                dialog.setMessage("Enter Photo Name");
                dialog.setPositiveButton("Save", null);
                dialog.setNegativeButton("cancel", null);

                final AlertDialog alertdialog = dialog.create();
                alertdialog.setOnShowListener(new DialogInterface.OnShowListener() {

                    @Override
                    public void onShow(DialogInterface dialog) {
                        // TODO Auto-generated method stub
                        Button b = alertdialog.getButton(AlertDialog.BUTTON_POSITIVE);
                        Button c = alertdialog.getButton(AlertDialog.BUTTON_NEGATIVE);

                        b.setOnClickListener(new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                // TODO Auto-generated method stub
                                String SpinName = input.getText().toString();
                                if(SpinName.length()==0){
                                    Toast.makeText(MainActivity.this, "Enter Photo Name", Toast.LENGTH_LONG).show();
                                }else{
                                    photoName = input.getText().toString();
                                    processedBitmap = ProcessingBitmap();
                                    if(processedBitmap != null){
                                        imageResult.setImageBitmap(processedBitmap);
                                     }
                                }
                                alertdialog.dismiss();

                            }
                        });
                        c.setOnClickListener(new View.OnClickListener() {

                            @Override
                            public void onClick(View v) {
                                // TODO Auto-generated method stub
                                alertdialog.dismiss();
                            }
                        });
                    }
                });alertdialog.show();}
            else{
                Toast.makeText(MainActivity.this, "Take Image First", Toast.LENGTH_LONG).show();
            }
        }
    });


    savePicture.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(source1!=null){
            String fname = photoName +".jpg";
            File file = new File (myDir, fname);
            if (file.exists ()) file.delete ();
            try {
                FileOutputStream out = new FileOutputStream(file);
                processedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                out.flush();
                out.close();

                AlertDialog.Builder aldialog = (new AlertDialog.Builder(MainActivity.this));
                aldialog.setTitle("saved");
                aldialog.setMessage("Image Saved Successfully");
                aldialog.setPositiveButton("OK", new DialogInterface.OnClickListener(){
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        imageResult.setImageResource(0);
                        source1 = null;
                    }
                });aldialog.show();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else{
            Toast.makeText(MainActivity.this, "Take Image First", Toast.LENGTH_LONG).show();
        }
        }
    });
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 1) {
        imgFile = new  File(pictureImagePath);
        if(imgFile.exists()){
            source1 = Uri.fromFile(imgFile);
            Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
            imageResult.setImageBitmap(myBitmap);


        }
    }

}

private Bitmap ProcessingBitmap() {
    Bitmap bm1 =  null;
    Bitmap newBitmap = null;
    try{
        bm1 = BitmapFactory.decodeStream(getContentResolver().openInputStream(Uri.fromFile(imgFile)));

        Bitmap.Config config = bm1.getConfig();
        if(config==null){
            config = Bitmap.Config.ARGB_8888;
        }
        newBitmap = Bitmap.createBitmap(bm1.getWidth(), bm1.getHeight(),config);
        Canvas newCanvas = new Canvas(newBitmap);
        newCanvas.drawBitmap(bm1,0,0,null);

        if(photoName!= null){
            Paint paintText =  new Paint(Paint.ANTI_ALIAS_FLAG);
            paintText.setColor(Color.WHITE);
            paintText.setTextSize(120);
            paintText.setShadowLayer(10f,10f,10f, Color.BLACK);
            Rect rectText = new Rect();
            paintText.getTextBounds(photoName, 0, photoName.length(), rectText);
            newCanvas.drawText(photoName, 0, bm1.getHeight()- rectText.height(), paintText);
            //newCanvas.drawText(photoName,bm1.getWidth()-rectText.left,bm1.getWidth()-rectText.top, paintText);


            Toast.makeText(MainActivity.this, "done", Toast.LENGTH_LONG).show();}
        else{
            Toast.makeText(MainActivity.this, "undone", Toast.LENGTH_LONG).show();}
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    return newBitmap;
}
}

请说出一些建议。 异常日志在这里

E/AndroidRuntime:致命异常:main 进程:com.surveyphotoapp,PID:24765 java.lang.OutOfMemoryError 在 android.graphics.Bitmap.nativeCreate(本机方法) 在 android.graphics.Bitmap.createBitmap(Bitmap.java:822) 在 android.graphics.Bitmap.createBitmap(Bitmap.java:799) 在 android.graphics.Bitmap.createBitmap(Bitmap.java:766) 在 com.surveyphotoapp.MainActivity.ProcessingBitmap(MainActivity.java:214) 在 com.surveyphotoapp.MainActivity.access$100(MainActivity.java:44) 在 com.surveyphotoapp.MainActivity$2$1$1.onClick(MainActivity.java:127) 在 android.view.View.performClick(View.java:4444) 在 android.view.View$PerformClick.run(View.java:18440) 在 android.os.Handler.handleCallback(Handler.java:733) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:136) 在 android.app.ActivityThread.main(ActivityThread.java:5052) 在 java.lang.reflect.Method.invokeNative(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:515) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612) 在 dalvik.system.NativeStart.main(本机方法)

后置摄像头的图像分辨率高于前置摄像头。因此,从字节流直接创建位图可能会因 OutOfMemoryError 而失败,尤其是在 VM 堆大小较小的设备上。

为避免小 VM 堆大小的错误,您可以在解码位图时捕获 OutOfMemoryError,如果发生这种情况,请减小图像大小并重试。

public static Bitmap getBitmapFromStream(Context context, InputStream istr) {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    final int REQUIRED_SIZE = display.getWidth();

    istr.mark(Integer.MAX_VALUE);
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true; 
    BitmapFactory.decodeStream(istr, null, o);
    int width_tmp = o.outWidth, height_tmp = o.outHeight;
    int scale = 1;
    while (true){
        if (width_tmp / 2 < REQUIRED_SIZE)
            break;
        width_tmp /= 2;
        height_tmp /= 2;
        scale *= 2;
    }

    while (true) {
        try {
            istr.reset();
            o = new BitmapFactory.Options();
            o.inSampleSize = scale;
            return BitmapFactory.decodeStream(istr, null, o);
        } catch (OutOfMemoryError ex) {
            scale *= 2;
            if (scale >= 32) {
                // Failed
                return null;
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        }
    }
}