Android 相机应用程序无法正确显示图像

Android Camera Application does not display image correctly

我想制作一个应用程序,用设备的相机拍照,将图像保存在内存中,然后在下一个 Activity 中显示该图像。预览效果很好,但是当我点击“捕获”按钮时,应用程序会转到下一个 activity,并且只显示空白屏幕。也许我没有正确写入或读取文件?

这是主要内容 Activity:

public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "File_name";
private Camera mCamera;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Create an instance of 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) {
                // get an image from the camera
                    mCamera.takePicture(null, null, mPicture);
                         }
              }
    );

}

//////////////////////
public void sendInfo(String pathway) {
    Intent intent = new Intent(this, show_image.class);
    intent.putExtra(EXTRA_MESSAGE,pathway);
    startActivity(intent);
}
/////////////////
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

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

        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

        ContextWrapper cw = new ContextWrapper(getApplicationContext());
        // path to /data/data/yourapp/app_data/imageDir
        File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
        // Create imageDir
        File mypath=new File(directory,"pic.jpg");
        FileOutputStream fos = null;

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

        try {
            fos = new FileOutputStream(mypath);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.close();
            String path = directory.getAbsolutePath();
            sendInfo(path);
        } 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
}
}

这是第二个 activity,它应该显示刚刚拍摄的图像:

public class show_image extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent intent = getIntent();
    String path = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

    try {
        File f = new File(path, "pic.jpg");
        Bitmap b = BitmapFactory.decodeStream(new FileInputStream(f));
        ImageView img= new ImageView(this);
        img.setImageBitmap(b);
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }



}

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("Logtag", "Error processing bitmap", e);
    } finally {
        //FileUtil.closeQuietly(fis);
    }

    return b;
}




@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);
}

}

来自 Android 工作室的 LogCat:

02-25 12:32:49.389  17041-17041/edu.ramapo.camer I/System.out﹕ debugger has settled (1496)


02-25 12:32:49.620  17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.view.ViewGroup.onNestedScrollAccepted, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onNestedScrollAccepted


02-25 12:32:49.620  17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 11360: Landroid/view/ViewGroup;.onNestedScrollAccepted (Landroid/view/View;Landroid/view/View;I)V

02-25 12:32:49.620  17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000

02-25 12:32:49.620  17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.view.ViewGroup.onStopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onStopNestedScroll

02-25 12:32:49.620  17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 11366: Landroid/view/ViewGroup;.onStopNestedScroll (Landroid/view/View;)V

02-25 12:32:49.620  17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000

02-25 12:32:49.630  17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.support.v7.internal.widget.ActionBarOverlayLayout.stopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.setHideOnContentScrollEnabled

02-25 12:32:49.630  17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 9050: Landroid/support/v7/internal/widget/ActionBarOverlayLayout;.stopNestedScroll ()V

02-25 12:32:49.630  17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000e

02-25 12:32:49.660  17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method 
android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations

02-25 12:32:49.660  17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 367: Landroid/content/res/TypedArray;.getChangingConfigurations ()I

02-25 12:32:49.660  17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002

02-25 12:32:49.670  17041-17041/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType

02-25 12:32:49.670  17041-17041/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 389: Landroid/content/res/TypedArray;.getType (I)I

02-25 12:32:49.670  17041-17041/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002

02-25 12:32:50.611  17041-17041/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libEGL_adreno200.so

02-25 12:32:50.621  17041-17041/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_adreno200.so

02-25 12:32:50.621  17041-17041/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libGLESv2_adreno200.so

02-25 12:32:50.631  17041-17041/edu.ramapo.camer I/Adreno200-EGL﹕ <qeglDrvAPI_eglInitialize:265>: EGL 1.4 QUALCOMM build: HAREESHG_Nondeterministic_AU+PATCH[ES]_msm8960_JB_1.9.6_MR2_CL3219408_release_ENGG (CL3219408)
    Build Date: 09/28/13 Sat
    Local Branch: hhh
    Remote Branch: quic/jb_1.9.6_1
    Local Patches: 8d50ec23e42ef52b570aa6ff1650afac0b503d78 CL3219408: Fix in the Glreadpixels for negative offsets and larger dimensions.
    801859126f6ca69482b39a34ca61447e3f7cded8 rb: fix panel settings to clear undrawn/undefined buffers
    Reconstruct Branch: LOCAL_PATCH[ES]

02-25 12:32:50.991  17041-17041/edu.ramapo.camer D/OpenGLRenderer﹕ Enabling debug mode 0

02-25 12:32:51.552  17041-17041/edu.ramapo.camer I/Choreographer﹕ Skipped 59 frames!  The application may be doing too much work on its main thread.

02-25 12:32:56.037  17041-17047/edu.ramapo.camer D/dalvikvm﹕ Debugger has detached; object registry had 4113 entries

02-25 12:33:18.651  17041-17041/edu.ramapo.camer D/dalvikvm﹕ GC_FOR_ALLOC freed 694K, 38% free 12155K/19420K, paused 29ms, total 32ms

02-25 12:33:18.771  17041-17041/edu.ramapo.camer I/dalvikvm-heap﹕ Grow heap (frag case) to 45.705MB for 31961104-byte allocation

02-25 12:33:24.507  17041-17041/edu.ramapo.camer D/dalvikvm﹕ GC_FOR_ALLOC freed 31627K, 40% free 11825K/19424K, paused 30ms, total 30ms

02-25 12:33:24.587  17041-17041/edu.ramapo.camer I/dalvikvm-heap﹕ Grow heap (frag case) to 45.382MB for 31961104-byte allocation

好吧,现在我复制了我发给你的应用程序 link 这里已经是代码:

public class GlassARTest extends FragmentActivity {

    private static final String TAG = "CameraActivity";

    public static final int MEDIA_TYPE_IMAGE = 1;
    private Camera mCamera;
    private CameraPreview mPreview;
    private Context mContext;

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

        mContext = this;

        if(checkCameraHardware(mContext)){
            // Create an instance of Camera
            mCamera = getCameraInstance();

            // Create our Preview view and set it as the content of our activity.
            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) {
                        // get an image from the camera
                        mCamera.takePicture(null, null, mPicture);
                    }
                }
            );
        }
    }

    private PictureCallback mPicture = new PictureCallback() {

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

            new AsyncTask<Void, Void, String>() {

                @Override
                protected String doInBackground(Void... params) {
                    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
                    if (pictureFile == null){
                        Log.d(TAG, "Error creating media file, check storage permissions: ");
                        return null;
                    }

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

                @Override
                protected void onPostExecute(String result) {
                    super.onPostExecute(result);
                    if(result != null){
                        Intent intent = new Intent(mContext, ImageDisplayActivity.class);
                        intent.putExtra(ImageDisplayActivity.KEY_PATH, result);
                        startActivity(intent);
                    }
                }

            }.execute();


        }
    };


    /** A basic Camera preview class */
    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
        private SurfaceHolder mHolder;
        private Camera mCamera;

        public CameraPreview(Context context, Camera camera) {
            super(context);
            mCamera = camera;

            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            mHolder = getHolder();
            mHolder.addCallback(this);
            // deprecated setting, but required on Android versions prior to 3.0
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, now tell the camera where to draw the preview.
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
            } catch (IOException e) {
                Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // empty. Take care of releasing the Camera preview in your activity.
        }

        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.

            if (mHolder.getSurface() == null){
              // preview surface does not exist
              return;
            }

            // stop preview before making changes
            try {
                mCamera.stopPreview();
            } catch (Exception e){
              // ignore: tried to stop a non-existent preview
            }

            // set preview size and make any resize, rotate or
            // reformatting changes here

            // start preview with new settings
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();

            } catch (Exception e){
                Log.d(TAG, "Error starting camera preview: " + e.getMessage());
            }
        }
    }

    /** A safe way to get an instance of the Camera object. */
    public static 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)
        }
        return c; // returns null if camera is unavailable
    }

    /** Check if this device has a camera */
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }


    /** 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 location 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("MyCameraApp", "failed to create directory");
                return null;
            }
        }

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

        return mediaFile;
    }

}  private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) {
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, now tell the camera where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // empty. Take care of releasing the Camera preview in your activity.
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
        }

        // stop preview before making changes
        try {
            mCamera.stopPreview();
        } catch (Exception e){
          // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

/** A safe way to get an instance of the Camera object. */
public static 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)
    }
    return c; // returns null if camera is unavailable
}

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}


/** 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 location 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("MyCameraApp", "failed to create directory");
            return null;
        }
    }

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

    return mediaFile;
}

}

和另一个 Activity:

public class ImageDisplayActivity extends FragmentActivity{

    public static final String KEY_PATH = "path";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image_display);
        final ImageView imageDisplay = (ImageView)findViewById(R.id.image_displayer);
        final Bundle extras = getIntent().getExtras();
        if(extras != null){
            final String path = extras.getString(KEY_PATH);
            File imgFile = new File(path);
            Bitmap bitmap = decodeFile(imgFile);
            imageDisplay.setImageBitmap(bitmap);
        }

    }


    private Bitmap decodeFile(File f){
        Bitmap b = null;
        try {
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;

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

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

            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            fis = new FileInputStream(f);
            b = BitmapFactory.decodeStream(fis, null, o2);
            fis.close();
        } catch (IOException e) {
        }
        return b;
    }

}

这段代码显示了我所拍照片的像素化图像(因为我只是出于测试目的以低质量对其进行解码)。 希望对你有帮助。