2016-05-27 9 views
0

Meine benutzerdefinierte Kamera-Implementierung funktioniert für etwa 95% meiner Benutzer. Aber es gibt Zeiten, wenn es eine NullPointerException gibt, nachdem sie die Kameravorschau-Aktivität fortsetzen, sagen nach der Auswahl eines Fotos aus der Galerie (und keine tatsächlichen Bilder), oder sie minimieren die App, ich habe keine Ahnung warum, aber es passiert sogar wenn die Kamera-Instanz direkt vor der Verwendung erstellt wird.Warum tritt beim Fortsetzen von CameraPreview eine NullPointerException auf?

Bitte überprüfen Sie meinen Code (markierte Fehler Zeile wie folgt:/* Zeile 30 -> * /).

Ausnahme:

Android Version: Android-Version: 4.4.4

Dies ist mein benutzerdefiniertes Fehlerbehandlungser:. Java.lang.NullPointerException bei com.cerculdivelor.posting.CameraPreview (CameraPreview .java-: 30) bei com.cerculdivelor.posting.CameraActivity.startCameraPreview (CameraActivity.java:130) bei com.cerculdivelor.posting.CameraActivity.onResume (CameraActivity.java:99) bei android.app.Instrumentation . callActivityOnResume (Instrumentation.java:1199) bei android.app.Activity.performResume (Activity.java:5521) bei android.app.ActivityThread.performResumeActivity (ActivityThread.java:3046) bei android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3085) bei android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1325) bei android.os.Handler.dispatchMessage (Handler.java:102) bei android.os.Looper. loop (Looper.java:136) um android.app.ActivityThread.main (ActivityThread.java:5584) um java.lang.reflect.Method.invokeNative (Native Methode) um java.lang.reflect.Method.invoke (Method.java:515) unter com.android. internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:1268) bei com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1084) um dalvik.system.NativeStart.main (native Methode)

Kamera Aktivität:

   @Override 
       protected void onResume() { 
        super.onResume(); 
         //Start the camera preview 
         if (Build.VERSION.SDK_INT >= 23) { 
          checkCameraPermissionFirst(); 
         } else { 
          try { 
           startCameraPreview(); 
          } catch(Exception e){ 
           http.sendToServer(e); 
          } 

        } 

        //Check write permission, prompt the user to grant permission in case if SDK > 19 (Lolipop) 
        if (Build.VERSION.SDK_INT >= 23) { 
         checkWritePermissionFirst(); 
        } 
       } 

       @Override 
       protected void onPause() { 
        super.onPause(); 
        Log.i("TAG", "PAUSED!!"); 
        // TODO: kicsit veszelyes, figyelemmel kell kovetni! 
        //mCamera = null; 

       } 

       private void startCameraPreview() { 
        // Create an instance of Camera 
        mCamera = getCameraInstance(); 
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 

        // remove any inital previews 
        //TODO: ezt azert figyelni kell meg! 
        preview.removeAllViews(); 

    /* line 130 -> */ mPreview = new CameraPreview(this, mCamera); 
        preview.addView(mPreview); 
       } 

    public static Camera getCameraInstance(Context context) { 
     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) 
      Log.w("TAG", "Camera error: " + e); 
      HttpConActivity http = new HttpConActivity(context); 
      http.sendToServer(e); 
     } 
     return c; // returns null if camera is unavailable 
    } 

Kamera Vorschau Aktivität:

package com.cerculdivelor.posting; 

    import java.io.IOException; 
    import java.util.List; 

    import android.content.Context; 
    import android.hardware.Camera; 
    import android.hardware.Camera.Parameters; 
    import android.hardware.Camera.Size; 
    import android.util.Log; 
    import android.view.SurfaceHolder; 
    import android.view.SurfaceView; 

    public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 

     private static final String TAG = "CameraPreview"; 

     private Context mContext; 
     private SurfaceHolder mHolder; 
     private Camera mCamera; 
     private List<Size> mSupportedPreviewSizes; 
     private Size mPreviewSize; 

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

       // supported preview sizes 
/* line 30 -> */ mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
      for(Size str: mSupportedPreviewSizes) 
        Log.e(TAG, "Preview sizes available: " + str.width + "/" + str.height); 

      // 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) { 
      // empty. surfaceChanged will take care of stuff 
     } 

     public void surfaceDestroyed(SurfaceHolder holder) { 
      // empty. Take care of releasing the Camera preview in your activity. 
      if (mCamera != null) { 
       mCamera.stopPreview(); 
       mCamera.release(); 
       mCamera = null; 

       Log.i("TAG", "Surface was distroyed."); 
      } 

     } 

     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
      Log.e(TAG, "surfaceChanged => w=" + w + ", h=" + 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 
      if(mCamera != null) { 
       try { 
        Parameters parameters = mCamera.getParameters(); 
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 

        if (parameters.getSupportedFocusModes().contains(
          Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 
         parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 
        } 

        mCamera.setParameters(parameters); 
        mCamera.setDisplayOrientation(90); 
        mCamera.setPreviewDisplay(mHolder); 
        mCamera.startPreview(); 

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

     @Override 
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
      final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); 
      final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); 

      if (mSupportedPreviewSizes != null) { 
       mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); 
      } 

      float ratio; 
      if(mPreviewSize.height >= mPreviewSize.width) 
       ratio = (float) mPreviewSize.height/(float) mPreviewSize.width; 
      else 
       ratio = (float) mPreviewSize.width/(float) mPreviewSize.height; 

      // One of these methods should be used, second method squishes preview slightly 
      setMeasuredDimension(width, (int) (width * ratio)); 
    //  setMeasuredDimension((int) (width * ratio), height); 
     } 

     private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
      final double ASPECT_TOLERANCE = 0.1; 
      double targetRatio = (double) h/w; 

      if (sizes == null) 
       return null; 

      Size optimalSize = null; 
      double minDiff = Double.MAX_VALUE; 

      int targetHeight = h; 

      for (Size size : sizes) { 
       double ratio = (double) size.height/size.width; 
       if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) 
        continue; 

       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 

      if (optimalSize == null) { 
       minDiff = Double.MAX_VALUE; 
       for (Size size : sizes) { 
        if (Math.abs(size.height - targetHeight) < minDiff) { 
         optimalSize = size; 
         minDiff = Math.abs(size.height - targetHeight); 
        } 
       } 
      } 

      return optimalSize; 
     } 
    } 
+0

woher wird Ihre startCameraPreview aus aufgerufen? –

+0

@TomerShemesh, oben in onResume. Thaks –

Antwort

0

Es kann sein, weil die mCamera verloren geht, wenn die App im Hintergrund zerstört wird. Hast du versucht, die Kamera-Instanz direkt in die Klasse zu bekommen?

mCamera = camera; 
if(mCamera==null) 
{ 
    mCamera = getCameraInstance() 
} 
+0

Entschuldigung, zuerst habe ich vergessen, den getCameraInstance() -Baustein zu posten. Ich habe meine Frage aktualisiert, Sie können sie am Ende des Kameraaktivitätsteils sehen. Jedenfalls initiiere ich hier Camera (c = Camera.open()), genau wie die Dokumentation sagt. :( –

0

In Ihrem surfaceDestroyed Sie setzen null auf Ihre Kamera (mCamera = null;), dann, wenn die App nach vorne kommen wieder haben Sie Ihre Variable in null, versuchen in der surfaceCreated Methode mit:

if (mCamera == null) { 
    mCamera = Camera.open(); 
    mCamera.setPreviewDisplay(holder); 
} 
+0

Bitte sehen Sie meine getCameraInstance() (am Ende der Kamera-Aktivität oben), Entschuldigung dafür, es nicht früher zu veröffentlichen. Hier mache ich Camera.open() - wie die offiziellen Dokumente sagen.Und es sagt auch, dass ich es in der Pause jedes Mal freigeben muss. –

Verwandte Themen