2017-07-26 224 views
0

我有一个Android视频捕获应用程序,但在三星设备中,我收到下面的错误。三星设备上的Android Camera2问题

我试图从mRecordButton.click(这是实际停止录制的按钮)中删除startPreview(),但没有成功。

我能做些什么?

错误:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.camera2.CaptureRequest$Builder android.hardware.camera2.CameraDevice.createCaptureRequest(int)' on a null object reference 
     at com.jobconvo.www.newjcapp.CameraActivity.startPreview(CameraActivity.java:427) 
     at com.jobconvo.www.newjcapp.CameraActivity.access$800(CameraActivity.java:53) 
     at com.jobconvo.www.newjcapp.CameraActivity$5.onClick(CameraActivity.java:268) 
     at android.view.View.performClick(View.java:5716) 
     at android.widget.TextView.performClick(TextView.java:10926) 
     at android.view.View$PerformClick.run(View.java:22596) 
     at android.os.Handler.handleCallback(Handler.java:739) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:148) 
     at android.app.ActivityThread.main(ActivityThread.java:7325) 
     at java.lang.reflect.Method.invoke(Method.java) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 

我的相机活动代码:

public class CameraActivity extends AppCompatActivity { 

private static final int STATE_PREVIEW = 0; 
private static final int STATE_WAIT_LOCK = 1; 
private int mCaptureState = STATE_PREVIEW; 

private TextureView mTextureView; 
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() { 
    @Override 
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 
     setupCamera(width, height); 
     try { 
      connectCamera(); 
     } catch (CameraAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 

    } 

    @Override 
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 
     return false; 
    } 

    @Override 
    public void onSurfaceTextureUpdated(SurfaceTexture surface) { 

    } 
}; 

private CameraDevice mCameraDevice; 
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() { 
    @Override 
    public void onOpened(CameraDevice camera) { 
     mCameraDevice = camera; 
     mMediaRecorder = new MediaRecorder(); 
     if (mIsRecording) { 
      try { 
       createVideoFileName(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      startRecord(); 
      mMediaRecorder.start(); 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        countDownTimer.start(); 
       } 
      }); 
     } else { 
      startPreview(); 
     } 
    } 

    @Override 
    public void onDisconnected(CameraDevice camera) { 
     camera.close(); 
     mCameraDevice = null; 
    } 

    @Override 
    public void onError(CameraDevice camera, int error) { 
     camera.close(); 
     mCameraDevice = null; 
    } 
}; 


private HandlerThread mBackgroundHandlerThread; 
private Handler mBackgroundHandler; 
private String mCameraId; 
private Size mPreviewSize; 
private Size mVideoSize; 

private MediaRecorder mMediaRecorder; 
private int mTotalRotation; 
private CameraCaptureSession mPreviewCaptureSession; 
private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new 
     CameraCaptureSession.CaptureCallback() { 

      private void process(CaptureResult captureResult) { 
       switch (mCaptureState) { 
        case STATE_PREVIEW: 
         // Do nothing 
         break; 
        case STATE_WAIT_LOCK: 
         mCaptureState = STATE_PREVIEW; 
         Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE); 
         if (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || 
           afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) { 
          Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show(); 
         } 
         break; 
       } 
      } 

      @Override 
      public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 
       super.onCaptureCompleted(session, request, result); 

       process(result); 
      } 
     }; 

private CameraCaptureSession mRecordCaptureSession; 

private CameraCaptureSession.CaptureCallback mRecordCaptureCallback = new 
     CameraCaptureSession.CaptureCallback() { 

      private void process(CaptureResult captureResult) { 
       switch (mCaptureState) { 
        case STATE_PREVIEW: 
         // Do nothing 
         break; 
        case STATE_WAIT_LOCK: 
         mCaptureState = STATE_PREVIEW; 
         Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE); 
         if (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || 
           afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) { 
          Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show(); 
         } 
         break; 
       } 
      } 

      @Override 
      public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { 
       super.onCaptureCompleted(session, request, result); 

       process(result); 
      } 
     }; 

private CaptureRequest.Builder mCaptureRequestBuilder; 

private Button mRecordButton; 
private boolean mIsRecording = false; 
private boolean mIsTimelapse = false; 

private File mVideoFolder; 
private String mVideoFileName; 

private MainModel mainModel; 

private static SparseIntArray ORIENTATIONS = new SparseIntArray(); 

static { 
    ORIENTATIONS.append(Surface.ROTATION_0, 0); 
    ORIENTATIONS.append(Surface.ROTATION_90, 90); 
    ORIENTATIONS.append(Surface.ROTATION_180, 180); 
    ORIENTATIONS.append(Surface.ROTATION_270, 270); 
} 

private static class CompareSizeByArea implements Comparator<Size> { 

    @Override 
    public int compare(Size lhs, Size rhs) { 
     return Long.signum((long) (lhs.getWidth() * lhs.getHeight()) - 
       (long) (rhs.getWidth() * rhs.getHeight())); 
    } 
} 

int questionId; 
int questionAnswerTime; 
String interviewId; 
TextView showTimer; 

private static String formatTime(int elapsed) { 
    int ss = elapsed % 60; 
    elapsed /= 60; 
    int min = elapsed % 60; 
    elapsed /= 60; 
    int hh = elapsed % 24; 
    return strzero(min) + ":" + strzero(ss); 
} 

private static String strzero(int n) { 
    if (n < 10) 
     return "0" + String.valueOf(n); 
    return String.valueOf(n); 
} 

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

    Fabric.with(this, new Crashlytics()); 

    mainModel = (MainModel) getIntent().getSerializableExtra("serialized_data"); 

    interviewId = mainModel.getInterviewID(); 
    final ScriptQuestion getQuestion = mainModel.questions.get(0); 
    questionId = getQuestion.getQuestionId(); 
    questionAnswerTime = getQuestion.getQuestionAnswerTime(); 

    showTimer = (TextView) findViewById(R.id.chronometer); 
    mTextureView = (TextureView) findViewById(R.id.textureView); 
    mRecordButton = (Button) findViewById(R.id.videoButton); 

    mRecordButton.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      countDownTimer.cancel(); 
      mIsRecording = false; 
      mIsTimelapse = false; 

      // Starting the preview prior to stopping recording which should hopefully 
      // resolve issues being seen in Samsung devices. 

      startPreview(); 
      mMediaRecorder.stop(); 
      mMediaRecorder.reset(); 


      Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
      mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mVideoFileName))); 
      sendBroadcast(mediaStoreUpdateIntent); 

      goNext(); 
     } 
    }); 

} 

private CountDownTimer countDownTimer = new CountDownTimer(600000, 1000) { 
    public void onTick(long millisUntilFinished) { 
     // 600000 = 10 minutes 
     int restTime = questionAnswerTime * 60 - (600 - ((int) (millisUntilFinished)/1000)); 
     String tmpRest = formatTime(restTime); 

     showTimer.setText(tmpRest); 
     if (restTime < 1) { 
      onFinish(); 
     } 
    } 

    public void onFinish() { 
     mRecordButton.performClick(); 
    } 
}; 

@Override 
protected void onResume() { 
    super.onResume(); 

    startBackgroundThread(); 

    if (mTextureView.isAvailable()) { 
     setupCamera(mTextureView.getWidth(), mTextureView.getHeight()); 

    } else { 
     mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); 
    } 

    mIsRecording = true; 

} 

@Override 
protected void onPause() { 
    closeCamera(); 

    stopBackgroundThread(); 

    super.onPause(); 
} 

@Override 
public void onWindowFocusChanged(boolean hasFocus) { 
    super.onWindowFocusChanged(hasFocus); 
    View decorView = getWindow().getDecorView(); 
    if (hasFocus) { 
     decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE 
       | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 
       | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 
       | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 
       | View.SYSTEM_UI_FLAG_FULLSCREEN 
       | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 
    } 
} 

private void setupCamera(int width, int height) { 
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
    try { 
     for (String cameraId : cameraManager.getCameraIdList()) { 
      CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId); 
      if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == 
        CameraCharacteristics.LENS_FACING_BACK) { 
       continue; 
      } 
      StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation(); 
      mTotalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation); 
      boolean swapRotation = mTotalRotation == 90 || mTotalRotation == 270; 
      int rotatedWidth = width; 
      int rotatedHeight = height; 
      if (swapRotation) { 
       rotatedWidth = height; 
       rotatedHeight = width; 
      } 
      mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight); 
      mVideoSize = chooseOptimalSize(map.getOutputSizes(MediaRecorder.class), rotatedWidth, rotatedHeight); 

      mCameraId = cameraId; 
      return; 
     } 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

private void connectCamera() throws CameraAccessException { 
    CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 
     return; 
    } 
    cameraManager.openCamera(mCameraId, mCameraDeviceStateCallback, mBackgroundHandler); 
} 

private void startRecord() { 

    try { 
     if(mIsRecording) { 
      setupMediaRecorder(); 
     } else if(mIsTimelapse) { 
      setupTimelapse(); 
     } 
     SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); 
     surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
     Surface previewSurface = new Surface(surfaceTexture); 
     Surface recordSurface = mMediaRecorder.getSurface(); 
     mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 
     mCaptureRequestBuilder.addTarget(previewSurface); 
     mCaptureRequestBuilder.addTarget(recordSurface); 

     mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface), 
       new CameraCaptureSession.StateCallback() { 
        @Override 
        public void onConfigured(CameraCaptureSession session) { 
         mRecordCaptureSession = session; 
         try { 
          mRecordCaptureSession.setRepeatingRequest(
            mCaptureRequestBuilder.build(), null, null 
          ); 
         } catch (CameraAccessException e) { 
          e.printStackTrace(); 
         } 
        } 

        @Override 
        public void onConfigureFailed(CameraCaptureSession session) { 
         //Log.d(TAG, "onConfigureFailed: startRecord"); 
        } 
       }, null); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

private void startPreview() { 

    SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); 
    assert surfaceTexture != null; 
    surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); 
    Surface previewSurface = new Surface(surfaceTexture); 

    try { 
     mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     mCaptureRequestBuilder.addTarget(previewSurface); 

     mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), 
       new CameraCaptureSession.StateCallback() { 
        @Override 
        public void onConfigured(CameraCaptureSession session) { 
         //Log.d(TAG, "onConfigured: startPreview"); 
         mPreviewCaptureSession = session; 
         try { 
          mPreviewCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(), 
            null, mBackgroundHandler); 
         } catch (CameraAccessException e) { 
          e.printStackTrace(); 
         } 
        } 

        @Override 
        public void onConfigureFailed(CameraCaptureSession session) { 
         //Log.d(TAG, "onConfigureFailed: startPreview"); 

        } 
       }, null); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

private void closeCamera() { 
    if(mCameraDevice != null) { 
     mCameraDevice.close(); 
     mCameraDevice = null; 
    } 
    if(mMediaRecorder != null) { 
     mMediaRecorder.release(); 
     mMediaRecorder = null; 
    } 
} 

private void startBackgroundThread() { 
    mBackgroundHandlerThread = new HandlerThread("Camera2VideoImage"); 
    mBackgroundHandlerThread.start(); 
    mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper()); 
} 

private void stopBackgroundThread() { 
    mBackgroundHandlerThread.quitSafely(); 
    try { 
     mBackgroundHandlerThread.join(); 
     mBackgroundHandlerThread = null; 
     mBackgroundHandler = null; 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation) { 
    int sensorOrienatation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); 
    deviceOrientation = ORIENTATIONS.get(deviceOrientation); 
    return (sensorOrienatation + deviceOrientation + 360) % 360; 
} 

private static Size chooseOptimalSize(Size[] choices, int width, int height) { 
    List<Size> bigEnough = new ArrayList<Size>(); 
    for(Size option : choices) { 
     if(option.getHeight() == option.getWidth() * height/width && 
       option.getWidth() >= width && option.getHeight() >= height) { 
      bigEnough.add(option); 
     } 
    } 
    if(bigEnough.size() > 0) { 
     return Collections.min(bigEnough, new CompareSizeByArea()); 
    } else { 
     return choices[0]; 
    } 
} 

private File createVideoFileName() throws IOException { 

    File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "JobConvoVideos"); 
    mVideoFolder = new File(mediaStorageDir, "JobConvoVideos"); 
    if(!mVideoFolder.exists()) { 
     mVideoFolder.mkdirs(); 
    } 

    String prepend = "android-" + interviewId + "-" + String.valueOf(questionId) + ".mp4"; 
    File videoFile = new File(mediaStorageDir.getPath() + File.separator + prepend); 
    mVideoFileName = videoFile.getAbsolutePath(); 

    return videoFile; 
} 

public static File getOutputMediaFile(String _interviewId, int qstId, Context _context){ 

    String idInterview = _interviewId; 
    idInterview = "android-" + idInterview + "-" + String.valueOf(qstId) + ".mp4"; 

    File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "JobConvoVideos"); 
    _context.getExternalFilesDir("JobConvoVideos"); 
    File f = new File(mediaStorageDir.getPath() + File.separator + idInterview); 
    return f; 
} 

private void setupMediaRecorder() throws IOException { 
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); 
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
    mMediaRecorder.setOutputFile(mVideoFileName); 
    mMediaRecorder.setVideoEncodingBitRate(1000000); 
    mMediaRecorder.setVideoFrameRate(30); 
    mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight()); 
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP); 
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
    mMediaRecorder.setOrientationHint(mTotalRotation); 
    mMediaRecorder.getMaxAmplitude(); 
    mMediaRecorder.prepare(); 
} 

private void setupTimelapse() throws IOException { 
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
    mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_QVGA)); 
    mMediaRecorder.setOutputFile(mVideoFileName); 
    mMediaRecorder.setCaptureRate(2); 
    mMediaRecorder.setOrientationHint(mTotalRotation); 
    mMediaRecorder.prepare(); 
} 


private void goNext() { 

    finish(); 

    Intent goUpload = new Intent(this, VideoUploadActivity.class); 
    goUpload.putExtra("serialized_data", mainModel); 
    startActivity(goUpload); 

} 

@Override 
public void onBackPressed() { 
    Toast.makeText(getApplicationContext(), R.string.getBack, Toast.LENGTH_LONG).show(); 
} 

}

回答

0

我在这里增加了一个尝试捕捉其中的应用显示出了很大的改善。尽管如此,它仍然有时会崩溃。不经常。

mRecordButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       countDownTimer.cancel(); 
       mIsRecording = false; 
       mIsTimelapse = false; 

       // Starting the preview prior to stopping recording which should hopefully 
       // resolve issues being seen in Samsung devices. 

       try { 
        startPreview(); 
        mMediaRecorder.stop(); 
        mMediaRecorder.reset(); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 

       Intent mediaStoreUpdateIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 
       mediaStoreUpdateIntent.setData(Uri.fromFile(new File(mVideoFileName))); 
       sendBroadcast(mediaStoreUpdateIntent); 

       goNext(); 
      } 
     }); 
相关问题