Take picture with android camera (intent) out of m

2019-07-08 20:41发布

问题:

I'm having two troubles with the below code. It just take picture "onclick" using intent of camera android and it display the image on the ImageView.

  1. After two or three pictures without leaving the activity, it crash with an outOfMemory error often when i'm rotating the display.
  2. When I take picture first time, it refresh the imageview but when i do second or third time...it doesn't refresh the picture until I rotate the screen
  3. I would like to save picture on internal storage instead of external, but I don't understand how to do cause I tried several tutorial and it stucks the camera!

    public class HandScryActivity extends Activity {

    private static int TAKE_PICTURE = 1;
    private MtgMatch myMatch;
    private File handFile;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.handscry);  
        // Disable screen saver
        getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
        // Load match 
        myMatch = MtgMatch.getSingletonMtgMatch();
        handFile = new File(Environment.getExternalStorageDirectory(), "test.jpg");
        if (myMatch.getHandUri() != null) { loadPicture(); }        
    }
    
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        loadPicture();
    }
    
    // Handles onGame clicked buttons
    public void btnHandClick(View v) {
            Button clickedButton = (Button) v;
        // according to clicked button
        switch (clickedButton.getId()) {
            case R.id.btnBackToGame:
                this.finish();
                break;
            case R.id.btnTakePicture:              
                myMatch.setHandUri(Uri.fromFile(handFile));
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);                
                intent.putExtra(MediaStore.EXTRA_OUTPUT, myMatch.getHandUri());
                startActivityForResult(intent, TAKE_PICTURE);
                break;              
            default:
                break;
        }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {                     
            if (requestCode == TAKE_PICTURE) {
                // Display image
                if (resultCode == RESULT_OK) {
                    loadPicture();
            } else if (resultCode == RESULT_CANCELED) {
                // User cancelled the image capture
            } else {
                // Image capture failed, advise user
            }
        }
    }
    
    // Put the photo inside frame
    private void loadPicture() {
            ImageView img = (ImageView) findViewById(R.id.imgHand);
            img.setImageURI(myMatch.getHandUri());
    }
    
    }
    

回答1:

You have a memory leak. The reason rotating your screen is causing memory exhaustion is because a screen rotate automatically destroys the Activity and rebuilds it. You can prove this by overriding the onPause and onStart methods and placing a debug statement in them, then rotate the screen and you see them get invoked. You need to understand the android Activity Lifecycle.

You have memory leaks because you are keeping references to those images in memory. You need to be tracking the memory usage. When you tilt the screen, the old activity is sticking around in memory, and a new one is created. In order for the garbage collector to collect up your unnecessary objects, you have to make sure there are no references left to them in the code. There are tools to chart the memory usage of your application so you can find out where the memory leak is:

Follow the directions in this page to have MAT tell you where the memory leak is:

Memory Analyzer Tool in android?



回答2:

To fix the high Memory usage that you are experiencing, it might be worthwhile to you, to take the file that the camera is returning, load it to a bitmap, and using bitmap factory options, set the option to use a sample size. (this scales down the image, but most likely you don't need a 2560x1900 image shown on a 640x480 screen) Check out this tutorial: http://tutorials-android.blogspot.co.il/2011/11/outofmemory-exception-when-decoding.html



回答3:

try this,

before set image on image view decode bitmap which you get from onActivityResult.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options);

after decoding set on image view.