简体   繁体   中英

Android Camera Application: How to display picture after it is saved internally?

So I want to build an Android app that uses the camera and saves the image internally (within the app) and then displays the picture that you just took in the next activity...but I'm having trouble outputting the image. I believe I've saved the picture correctly...but I'm not sure how to read the data. I looked at many tutorials but cannot find out what methods I'm supposed to put in the next activity to display the image. Here is the code for the main activity:

import android.hardware.Camera;
import android.net.Uri;
import android.os.Environment;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class MainActivity extends ActionBarActivity {

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

    // Create an instance of Camera
    Camera mCamera = getCameraInstance();

    // Create our Preview view and set it as the content of our activity.
    CameraPreview mPreview = new CameraPreview(this, mCamera);
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
    preview.addView(mPreview);

    // Add a listener to the Capture button
    Button captureButton = (Button) findViewById(R.id.button_capture);

    captureButton.setOnClickListener(new View.OnClickListener() {

                                         @Override
                                         public void onClick(View v) {
                                             Camera mCamera = getCameraInstance();
                                             // get an image from the camera
                                             mCamera.takePicture(null, null, mPicture);
                                         }
                                     }
    );





}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d("Logtag:", "Error creating media file, check storage permissions: "
                   );
            return;
        }

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
        } catch (FileNotFoundException e) {
            Log.d("Logtag:", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("Logtag:", "Error accessing file: " + e.getMessage());
        }
    }
};


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
/** A safe way to get an instance of the Camera object. */
public Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
        Toast.makeText(getApplicationContext(), "Camera is not available (in use or does not exist)",
                Toast.LENGTH_LONG).show();
    }
    return c; // returns null if camera is unavailable
}





public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
    return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
            Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This locat ion works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("Logtag", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

}

Pass the path or uri of the image file to the other activity in the intent. Inflate a layout including an ImageView. Decode the image file using BitmapFactory. Set the resulting bitmap on the ImageView.

I know this is probably not the answer you are looking for, but have you considered using a library to display the photo you just took?

I usually use Picasso and I am very happy with it. http://square.github.io/picasso/

If you have a image path and a View to display the image, you can basically display the image in one line of code like :

Picasso.with(context).load(pictureFile.getAbsolutePath()).into(view);

You will need to decode the file data. In order to save memory, scale down the bitmap to something appropriate for your display (maxSize)

public static Bitmap decodeFile(File f, final int maxSize) {

    Bitmap b = null;
    // Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;

    FileInputStream fis = null;
    try {
        fis = new FileInputStream(f);
        BitmapFactory.decodeStream(fis, null, o);
        fis.close();

        int scale = 1;
        if (o.outHeight > maxSize || o.outWidth > maxSize) {
            scale = (int) Math.pow(2, (int) Math.round(Math.log(maxSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;

        fis = new FileInputStream(f);
        b = BitmapFactory.decodeStream(fis, null, o2);

    } catch (Exception e) {
        Log.e(ImageUtils.TAG, "Error processing bitmap", e);
    } finally {
        FileUtil.closeQuietly(fis);
    }


    return b;
}

The bitmap can then be used in an ImageView

eg

mImageView.setImageBitmap(bitmap);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM