Android Camera.takePicture() - nullPointerExceptio

2019-05-30 07:27发布

问题:

I have a feeling this is a minor mistake somewhere small. I'm trying to setup a custom camera and when I click the capture button I am getting a null pointer. Perhaps my camera instance is null? Not sure why as I followed the documentation pretty closely. Post the code and error below, thanks!

Main class:

public class CameraActivity extends Activity {
    private Camera mCamera;
    private CameraPreview mPreview;
    private String TAG = "CameraActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.camera_preview);

        // 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);

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

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera mCamera = null;
        try {
            mCamera = Camera.open(); // attempt to get a Camera instance
        }
        catch (Exception e){
            // Camera is not available (in use or does not exist)
        }
        return mCamera; // returns null if camera is unavailable
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mCamera != null){
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mCamera = getCameraInstance();
    }

    private PictureCallback mPicture = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d(TAG, "Attempting to store picture...");
            final int MEDIA_TYPE_IMAGE = 100;
            File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
            if (pictureFile == null){
                Log.d(TAG, "Error creating media file, check storage permissions");
                return;
            }

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

Cat log:

03-27 01:13:06.892: E/AndroidRuntime(8008): FATAL EXCEPTION: main
03-27 01:13:06.892: E/AndroidRuntime(8008): java.lang.NullPointerException
03-27 01:13:06.892: E/AndroidRuntime(8008):     at com.justbaumdev.tagsense.CameraActivity$2.onClick(CameraActivity.java:47)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at android.view.View.performClick(View.java:4204)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at android.view.View$PerformClick.run(View.java:17355)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at android.os.Handler.handleCallback(Handler.java:725)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at android.os.Handler.dispatchMessage(Handler.java:92)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at android.os.Looper.loop(Looper.java:137)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at android.app.ActivityThread.main(ActivityThread.java:5041)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at java.lang.reflect.Method.invokeNative(Native Method)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at java.lang.reflect.Method.invoke(Method.java:511)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-27 01:13:06.892: E/AndroidRuntime(8008):     at dalvik.system.NativeStart.main(Native Method)

Preview class:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private int cameraId = 0;
    private Context mContext;
    private String TAG = "CameraPreview";

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

        //get notified if surface created/destroyed
        mHolder = getHolder();
        mHolder.addCallback(this);
    }

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

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //Take care of this in cameraActivity
//      mCamera.stopPreview();
//        mCamera.release();
    }


    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if(mHolder.getSurface() == null)
            return;

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

        //setCameraDisplayOrientation(mContext, mCamera, cameraId);


        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();
        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

Manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.justbaumdev.tagsense"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="16" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.NFC" />

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.nfc" />
    <uses-feature android:name="android.hardware.wifi.direct" />

    <uses-permission android:name="android.permission.READ_PROFILE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Holo" >
        <activity
            android:name=".TagSense"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.justbaumdev.tagsense.NFC">
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="application/com.justbaumdev.tagsense" />
            </intent-filter>
        </activity>
        <activity android:name="AlbumGallery"></activity>
        <activity android:name="CameraActivity"></activity>
    </application>

</manifest>

回答1:

i see at least one error. You're calling the getCameraInstance() at onCreate() and onResume(), and the onResume() is called after the call to onCreate(), which leads to two camera.open() without a camera.release(). you should just call the camera.open() at onResume().

http://developer.android.com/training/camera/cameradirect.html



回答2:

inside

public static Camera getCameraInstance()

you are initializing a local (method) variable

Camera mCamera = null;

not the class instance variable (you intend)

private Camera mCamera;

change the line from:

Camera mCamera = null;

to

this.mCamera = null;

Note: getCameraInstance() should not be a static method.