Android: Saving Bitmap to External Memory

2019-09-10 08:07发布

问题:

I'm currently working on a project of capturing an image, cropping the image, processing the image then saving the processed image. My problem lies in saving the processed image. I can't save the processed image. For every image that is captured, the captured image is being shown in the gallery instead of the processed image. I'm thinking that because the capturing image code saves the image to the SD card, I can't save the processed image that is on a bitmap... I hope you can enlighten me on what is the problem of my code. There is no error on the code by the way.

To be a little more specific, the app I'm working with captures image then crops the image. After that image will be shown in imageView. When processed, it will be again shown in an imageView. when i get the image to save in the external storage, nothing happens...

Here is the code for capturing and cropping the image

public class MainActivity extends Activity {

ImageView mainImageview;
Button mainButtonTakePhoto;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initializeControls();
}

private void initializeControls() {
    mainImageview = (ImageView)findViewById(R.id.imageView1);
    mainButtonTakePhoto = (Button)findViewById(R.id.button3);
    mainButtonTakePhoto.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick (View v) {
            /* create an instance of intent
             * pass action android.media.action.IMAGE_CAPTURE
             * as argument to launch camera */
            Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
             /*create instance of File with name img.jpg*/
            File file = new File(Environment.getExternalStorageDirectory()+File.separator + "img.jpg");
            /*put uri as extra in intent object*/
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
            /*start activity for result pass intent as argument and request code */
            startActivityForResult(intent, 1);
        }
    });

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    //if request code is same we pass as argument in startActivityForResult
    if(requestCode==1){
        //create instance of File with same name we created before to get image from storage
        File file = new File(Environment.getExternalStorageDirectory()+File.separator + "img.jpg");
        //Crop the captured image using an other intent
        try {
            /*the user's device may not support cropping*/
            cropCapturedImage(Uri.fromFile(file));
        }
        catch(ActivityNotFoundException aNFE){
            //display an error message if user device doesn't support
            String errorMessage = "Sorry - your device doesn't support the crop action!";
            Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    if(requestCode==2){
        //Create an instance of bundle and get the returned data
        Bundle extras = data.getExtras();
        //get the cropped bitmap from extras
        Bitmap thePic = extras.getParcelable("data");
        //set image bitmap to image view
        mainImageview.setImageBitmap(thePic);
    }
}
//create helping method cropCapturedImage(Uri picUri)
public void cropCapturedImage(Uri picUri){
    //call the standard crop action intent
    Intent cropIntent = new Intent("com.android.camera.action.CROP");
    //indicate image type and Uri of image
    cropIntent.setDataAndType(picUri, "image/*");
    //set crop properties
    cropIntent.putExtra("crop", "true");
    //indicate aspect of desired crop
    cropIntent.putExtra("aspectX", 0);
    cropIntent.putExtra("aspectY", 0);
    //indicate output X and Y
    cropIntent.putExtra("outputX", 128);
    cropIntent.putExtra("outputY", 256);
    //retrieve data on return
    cropIntent.putExtra("return-data", true);
    //start the activity - we handle returning in onActivityResult
    startActivityForResult(cropIntent, 2);
}
}

And here is the code for saving the image.

    public void saveImageToExternalStorage(Bitmap finalBitmap) {
    String root =Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
    File myDir = new File(root + "/saved_images");
    myDir.mkdirs();
    Random generator = new Random();
    int n = 10000;
    n = generator.nextInt(n);
    String fname = "Image-" + n + ".jpg";
    File file1 = new File(myDir, fname);
    if (file1.exists())
        file1.delete();
    try {
        FileOutputStream out = new FileOutputStream(file1);
        finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }


    // Tell the media scanner about the new file so that it is
    // immediately available to the user.
    MediaScannerConnection.scanFile(this, new String[] { file1.toString() },                null,
            new MediaScannerConnection.OnScanCompletedListener() {
                public void onScanCompleted(String path, Uri uri) {
                    Log.i("ExternalStorage", "Scanned " + path + ":");
                    Log.i("ExternalStorage", "-> uri=" + uri);
                }
            });

}

Thanks a lot for your help. I'm trying not to trouble anyone if this is a stupid question. And I'm really trying my best to research and study every part of the code I'm using/lifting... Thanks again...

回答1:

Are you testing it on api23 and up? If so... are you manually requesting permission to WRITE_EXTERNAL_STORAGE? because putting it in manifest is not enough.



回答2:

The code works just fine... I'm sorry to waste all of your time and concern... I just added the manifest to write to memory... When I read from android developers about the manifest for writing to storage, I thought there is no need for the manifest when you are using API19 and up...