2017-08-09 98 views
0

我正在android studio中製作一個自定義攝像頭。如果我退出該應用程序,它會在返回時崩潰。我知道問題在於activity的生命週期,logcat指出我在cameraPreview.java文件中有`mCamera.setPreviewDisplay(surfaceHolder)'的行。我已經看到其他類似的帖子,但我仍然不知道如何解決它。任何幫助表示讚賞。定製安卓攝像頭上的java.lang.NullPointerException

homePage.java

import android.Manifest; 
import android.content.DialogInterface; 
import android.content.pm.PackageManager; 
import android.support.annotation.NonNull; 
import android.support.v4.app.ActivityCompat; 
import android.support.v4.content.ContextCompat; 
import android.support.v7.app.AlertDialog; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.FrameLayout; 
import android.widget.Toast; 
import java.util.ArrayList; 
import java.util.List; 
import android.hardware.Camera; 

public class homePage extends AppCompatActivity { 

    private static final int CAMERA_PERMISSION = 123; 
    private static final String TAG = "homePage"; 
    private Camera mCamera; 
    private CameraPreview mCameraPreview; 

    private boolean cameraPermission() { 
     int CameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); 

     List<String> cameraPermissionNeeded = new ArrayList<>(); 

     if (CameraPermission != PackageManager.PERMISSION_GRANTED) { 
      cameraPermissionNeeded.add(Manifest.permission.CAMERA); 
     } 
     if (!cameraPermissionNeeded.isEmpty()) { 
      ActivityCompat.requestPermissions(this, 
        cameraPermissionNeeded.toArray(new String[cameraPermissionNeeded.size()]), 
        CAMERA_PERMISSION); 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, 
              @NonNull String permissions[], 
              @NonNull int[] grantResults) { 

     switch(requestCode) { 
      case CAMERA_PERMISSION: 
       if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
        return; 
       }else { 
        Toast.makeText(this, "Certain permissions needed to continue", Toast.LENGTH_SHORT).show(); 
       } 
       break; 
     } 
    } 

    private boolean hasCamera() { 

     if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) { 
      return true; 
     }else { 

      AlertDialog camAlert = new AlertDialog.Builder(homePage.this).create(); 
      camAlert.setTitle("Alert"); 
      camAlert.setMessage("there is no usable camera"); 
      camAlert.setButton(AlertDialog.BUTTON_NEUTRAL, "OK", 
        new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog, int which) { 
          dialog.dismiss(); 
         } 
        }); 
      camAlert.show(); 
      return false; 
     } 
    } 

    @SuppressWarnings("deprecation") 
    public static android.hardware.Camera getCameraInstance() { 
     android.hardware.Camera c = null; 

     try { 
      c = android.hardware.Camera.open(); 
     } 
     catch (Exception e) { 

      Log.d(TAG, "camera in use or does not exist"); 
     } 
     return c; 
    } 

    private void releaseCamera(){ 
     if (mCamera != null){ 
      mCamera.release(); 
      mCamera = null; 

     } 
    } 

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

     cameraPermission(); 
     hasCamera(); 

     mCamera = getCameraInstance(); 
     mCameraPreview = new CameraPreview(this, mCamera); 
     FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
     preview.addView(mCameraPreview); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     releaseCamera(); 

    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     hasCamera(); 
     mCamera.stopPreview(); 

     if (this.mCamera == null) { 
      mCamera = getCameraInstance(); 
      mCameraPreview = new CameraPreview(this, mCamera); 
      FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
      preview.addView(mCameraPreview); 
     } 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 

     if (mCamera == null) { 
      mCamera = getCameraInstance(); 
      mCameraPreview = new CameraPreview(this, mCamera); 
      FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
      preview.addView(mCameraPreview); 
     } 
    } 
    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     releaseCamera(); 

    } 
} 

cameraPreview.java

import android.content.Context; 
import android.hardware.Camera; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import java.io.IOException; 
import static android.content.ContentValues.TAG; 

@SuppressWarnings("deprecation") 
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 

    private SurfaceHolder mSurfaceHolder; 
    private Camera mCamera; 

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

     this.mCamera = camera; 
     this.mSurfaceHolder = this.getHolder(); 
     this.mSurfaceHolder.addCallback(this); 
     this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    private void releaseCamera() { 
     if (mCamera != null) { 
      mCamera.release(); 
      mCamera = null; 
     } 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder surfaceHolder) { 
     try { 
//==================logcat points out this line=================== 

      mCamera.setPreviewDisplay(surfaceHolder); 

//================================================================ 
      mCamera.startPreview(); 

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

    @Override 
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 

     releaseCamera(); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) { 
     if (mSurfaceHolder.getSurface() == null) { 
      return; 
     } 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 

     } 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 

     } 

     try { 
      mCamera.setPreviewDisplay(surfaceHolder); 
      mCamera.startPreview(); 
     } catch (Exception e) { 
      //blank 
     } 
    } 
} 

logcat的

08-09 11:48:17.192 8075-8075/? I/art: Late-enabling -Xcheck:jni 
08-09 11:48:17.223 8075-8082/? E/art: Failed sending reply to debugger: Broken pipe 
08-09 11:48:17.224 8075-8082/? I/art: Debugger is no longer active 
08-09 11:48:17.224 8075-8082/? I/art: Starting a blocking GC Instrumentation 
08-09 11:48:17.319 8075-8075/? W/System: ClassLoader referenced unknown path: /data/app/hernanrazo.camera-1/lib/arm64 
08-09 11:48:17.331 8075-8075/? I/InstantRun: starting instant run server: is main process 
08-09 11:48:17.394 8075-8075/? W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable 
08-09 11:48:17.544 8075-8128/? I/Adreno: QUALCOMM build     : 6818200, Idb2b4cb785 
             Build Date      : 11/17/16 
             OpenGL ES Shader Compiler Version: XE031.09.00.04 
             Local Branch      : N25 
             Remote Branch     : 
             Remote Branch     : 
             Reconstruct Branch    : 
08-09 11:48:17.565 8075-8128/? I/OpenGLRenderer: Initialized EGL, version 1.4 
08-09 11:48:17.565 8075-8128/? D/OpenGLRenderer: Swap behavior 1 
08-09 11:48:24.832 8075-8075/hernanrazo.camera W/IInputConnectionWrapper: finishComposingText on inactive InputConnection 
08-09 11:48:24.832 8075-8075/hernanrazo.camera W/IInputConnectionWrapper: finishComposingText on inactive InputConnection 
08-09 11:48:28.527 8075-8075/hernanrazo.camera I/Choreographer: Skipped 32 frames! The application may be doing too much work on its main thread. 
08-09 11:48:28.914 8075-8075/hernanrazo.camera W/IInputConnectionWrapper: finishComposingText on inactive InputConnection 
08-09 11:48:43.705 8075-8075/hernanrazo.camera D/AndroidRuntime: Shutting down VM 
08-09 11:48:43.706 8075-8075/hernanrazo.camera E/AndroidRuntime: FATAL EXCEPTION: main 
                   Process: hernanrazo.camera, PID: 8075 
                   java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference 
                    at hernanrazo.camera.CameraPreview.surfaceCreated(CameraPreview.java:36) 
                    at android.view.SurfaceView.updateWindow(SurfaceView.java:618) 
                    at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:247) 
                    at android.view.View.dispatchWindowVisibilityChanged(View.java:10357) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1290) 
                    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1544) 
                    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254) 
                    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6338) 
                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874) 
                    at android.view.Choreographer.doCallbacks(Choreographer.java:686) 
                    at android.view.Choreographer.doFrame(Choreographer.java:621) 
                    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860) 
                    at android.os.Handler.handleCallback(Handler.java:751) 
                    at android.os.Handler.dispatchMessage(Handler.java:95) 
                    at android.os.Looper.loop(Looper.java:154) 
                    at android.app.ActivityThread.main(ActivityThread.java:6121) 
                    at java.lang.reflect.Method.invoke(Native Method) 
                    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 

回答

0

大概誤差函數

surfaceDestroyed()

因爲這個方法調用

releaseCamera()

而且在該方法的相機變量被設置爲空,請在至極時刻檢查執行surfaceDestroyed( )功能。

+0

我應該只是叫'mCamera.release();'而不是'releaseCamera();' ? –

+0

嘗試在releaseCamera()函數中刪除mCamera = null。 – Chefes

+0

這樣做會消除nullPointerException錯誤,但logcat現在告訴我相機正在使用Camera.release()之後被調用 –