Android Camera 2 Api問題二
只無意中發現sony某款手機上出現該問題:
有時mMediaRecorder.stop()時會引發CameraDevice.StateCallback中onError()方法。
解決思路來自http://stackoverflow.com/questions/27907090/android-camera-2-api
描述①
After calling mMediaRecorder.stop() an IllegalStateException is always thrown. I’ve noticed that on devices with INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY the CameraDevice changes status to error, immediately calling onError() in the CameraDevice.StateCallback.
In the sample you referenced, onError() closes the camera and finishes the activity, so just change onError() to re-open the camera, like this:
描述②
It depends on what you are doing with the CameraCaptureSession and the MediaRecorder but when you call mMediaRecorder.stop() I think it is destroying the surface used for the camera preview session which causes this error because the documentation says
Once recording is stopped, you will have to configure it again as if it has just been constructed
Therefore if you call PreviewSession.abortCaptures() (mPreviewSession.stopRepeating(); isn’t necessary from what I gather) it stops the camera sending output to the recorder surface which will allow you to stop the MediaRecorder without issue.
PreviewSession.abortCaptures(); doesn’t instantly stop the camera preview output so you might find you need to call MediaRecorder.stop() in the onClosed() or onReady() method of the CameraCaptureSession.StateCallback
/*
* Copyright 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.king.android5x.camera2video;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.provider.MediaStore;
import android.text.format.DateFormat;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import com.boens.data.SaveFolderName;
import com.boens.data.VedioBitmap;
import com.boens.homepage.R;
import com.boens.tools.Deletedir;
import com.boens.tools.GetScreenshop;
@SuppressLint("NewApi")
public class Camera2VideoFragment extends Fragment
implements View.OnClickListener {
public int RESULT_OK = -1;
private boolean isHasRecord = false;
private boolean isStartRecording = true;
private boolean happen_error = false;
private ImageView imageview_screenshop_sdk5;
private TextView timeTextView;
private TextView mintimeTextView;
private TextView maxtimeTextView;
private ProgressBar progressbar;//錄製時進度條
private static final int Maxtime = 1;//錄製時長最大5min;伺服器端接收視訊大小不能超過50M
private static final int Mintime = 10;//錄製時長最少10s;
private int second = 0;
private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
private static final String TAG = "Camera2VideoFragment";
//private static final int REQUEST_VIDEO_PERMISSIONS = 1;
private static final String FRAGMENT_DIALOG = "dialog";
/* private static final String[] VIDEO_PERMISSIONS = {
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO,
};*/
Activity activity;
static {
ORIENTATIONS.append(Surface.ROTATION_0, 90);
ORIENTATIONS.append(Surface.ROTATION_90, 0);
ORIENTATIONS.append(Surface.ROTATION_180, 270);
ORIENTATIONS.append(Surface.ROTATION_270, 180);
}
/**
* An {@link AutoFitTextureView} for camera preview.
*/
private AutoFitTextureView mTextureView;
/**
* Button to record video
*/
private Button mButtonVideo;
/**
* A refernce to the opened {@link android.hardware.camera2.CameraDevice}.
*/
private CameraDevice mCameraDevice;
/**
* A reference to the current {@link android.hardware.camera2.CameraCaptureSession} for
* preview.
*/
private CameraCaptureSession mPreviewSession;
/**
* {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
* {@link TextureView}.
*/
@SuppressLint("NewApi")
private TextureView.SurfaceTextureListener mSurfaceTextureListener
= new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
int width, int height) {
openCamera(width, height);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
int width, int height) {
configureTransform(width, height);
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
/**
* The {@link android.util.Size} of camera preview.
*/
private Size mPreviewSize;
/**
* The {@link android.util.Size} of video recording.
*/
private Size mVideoSize;
/**
* Camera preview.
*/
private CaptureRequest.Builder mPreviewBuilder;
/**
* MediaRecorder
*/
private MediaRecorder mMediaRecorder;
/**
* Whether the app is recording video now
*/
private boolean isRunning ;
/**
* An additional thread for running tasks that shouldn't block the UI.
*/
private HandlerThread mBackgroundThread;
/**
* A {@link Handler} for running tasks in the background.
*/
private Handler mBackgroundHandler;
/**
* A {@link Semaphore} to prevent the app from exiting before closing the camera.
*/
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
/**
* {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its status.
*/
private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
@SuppressLint("NewApi")
@Override
public void onOpened(CameraDevice cameraDevice) {
mCameraDevice = cameraDevice;
startPreview();
mCameraOpenCloseLock.release();
if (null != mTextureView) {
configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
}
}
@Override
public void onDisconnected(CameraDevice cameraDevice) {
mCameraOpenCloseLock.release();
cameraDevice.close();
mCameraDevice = null;
}
@Override
public void onError(CameraDevice cameraDevice, int error) {
happen_error = true;
if(isHasRecord){
closeCamera();
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
}
else if(isHasRecord == false && happen_error == true){
handler.sendEmptyMessage(6);
WhenDonotSupportNewCamera2() ;
}
}
};
public void WhenDonotSupportNewCamera2() {
//Activity activity = getActivity();
mCameraOpenCloseLock.release();
if (null != mCameraDevice){
mCameraDevice.close();
mCameraDevice = null;
}
Intent intent = new Intent();
if(isHasRecord){
activity.setResult(RESULT_OK,intent);
// 關閉Activity
activity.finish();
}
else {
exitRefree() ;
activity.finish();
}
}
public static Camera2VideoFragment newInstance() {
return new Camera2VideoFragment();
}
/**
* In this sample, we choose a video size with 3x4 aspect ratio. Also, we don't use sizes
* larger than 1080p, since MediaRecorder cannot handle such a high-resolution video.
*
* @param choices The list of available sizes
* @return The video size
*/
private static Size chooseVideoSize(Size[] choices) {
for (Size size : choices) {
if (size.getWidth() == size.getHeight() * 4 / 3 && size.getWidth() <= 1080) {
return size;
}
}
Log.e(TAG, "Couldn't find any suitable video size");
return choices[choices.length - 1];
}
/**
* Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
* width and height are at least as large as the respective requested values, and whose aspect
* ratio matches with the specified value.
*
* @param choices The list of sizes that the camera supports for the intended output class
* @param width The minimum desired width
* @param height The minimum desired height
* @param aspectRatio The aspect ratio
* @return The optimal {@code Size}, or an arbitrary one if none were big enough
*/
public static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
// Collect the supported resolutions that are at least as big as the preview Surface
List<Size> bigEnough = new ArrayList<Size>();
int w = aspectRatio.getWidth();
int h = aspectRatio.getHeight();
for (Size option : choices) {
if (option.getHeight() == option.getWidth() * h / w &&
option.getWidth() >= width && option.getHeight() >= height) {
bigEnough.add(option);
}
}
// Pick the smallest of those, assuming we found any
if (bigEnough.size() > 0) {
return Collections.min(bigEnough, new CompareSizesByArea());
} else {
Log.e(TAG, "Couldn't find any suitable preview size");
return choices[0];
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.mediarecord_fragment_sdk5, container, false);
}
@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
activity = getActivity();
mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
mButtonVideo = (Button) view.findViewById(R.id.video);
imageview_screenshop_sdk5 = (ImageView) view.findViewById(R.id.imageview_screenshop_sdk5);
progressbar = (ProgressBar) view.findViewById(R.id.pb_progressbar_sdk5);
timeTextView = (TextView) view.findViewById(R.id.luzhi_time_sdk5);
mintimeTextView = (TextView) view.findViewById(R.id.luzhi_mintime_sdk5);
maxtimeTextView = (TextView) view.findViewById(R.id.luzhi_maxtime_sdk5);
mintimeTextView.setText(Mintime+"s");
maxtimeTextView.setText(Maxtime + "min");
mButtonVideo.setOnClickListener(this);
view.findViewById(R.id.info).setOnClickListener(this);
}
@Override
public void onResume() {
super.onResume();
startBackgroundThread();
if (mTextureView.isAvailable()) {
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
} else {
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
}
}
@Override
public void onPause() {
closeCamera();
stopBackgroundThread();
super.onPause();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.video: {
if (isStartRecording ) {
startRecordingVideo();
}
else{
stopRecordingVideo();
}
break;
}
case R.id.info: {
//final Activity activity = getActivity();
if (null != activity) {
Intent intent = new Intent();
if (second > 10 && isRunning == true) {
new AlertDialog.Builder(activity)
.setTitle(R.string.warm_prompt)
.setMessage(getText(R.string.is_cancel_recordding).toString())
.setPositiveButton(R.string.dialog_sure,
new DialogInterface.OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
exitRefree();
activity.finish();
}
})
.setNegativeButton(R.string.dialog_cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
}
}).show();
}
else if(isHasRecord){
activity.setResult(RESULT_OK,intent);
// 關閉Activity
activity.finish();
}
else {
exitRefree() ;
activity.finish();
}
}
break;
}
}
}
/**
* 直接退出時
*/
public void exitRefree() {
if (VedioBitmap.bitmapVedio != null && !VedioBitmap.bitmapVedio.isRecycled()) {
VedioBitmap.bitmapVedio.recycle();
}
if (null != VedioBitmap.pathVedio
&& VedioBitmap.pathVedio.contains(SaveFolderName.namefolder) && !(VedioBitmap.pathVedio
.contains("http"))) {
File takeVedioFile = new File(
VedioBitmap.pathVedio);
Deletedir.deleteFileSafely(takeVedioFile);
}
VedioBitmap.bitmapVedio = null;
VedioBitmap.pathVedio = null;
}
/**
* Starts a background thread and its {@link Handler}.
*/
private void startBackgroundThread() {
mBackgroundThread = new HandlerThread("CameraBackground");
mBackgroundThread.start();
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}
/**
* Stops the background thread and its {@link Handler}.
*/
private void stopBackgroundThread() {
mBackgroundThread.quitSafely();
try {
mBackgroundThread.join();
mBackgroundThread = null;
mBackgroundHandler = null;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Tries to open a {@link CameraDevice}. The result is listened by `mStateCallback`.
*/
private void openCamera(int width, int height) {
isRunning = false;
isStartRecording = true;
// final Activity activity = getActivity();
if (null == activity || activity.isFinishing()) {
return;
}
CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
try {
Log.d(TAG, "tryAcquire");
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Time out waiting to lock camera opening.");
}
String cameraId = manager.getCameraIdList()[0];
// Choose the sizes for camera preview and video recording
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
int sdf = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
System.out.println(sdf);
StreamConfigurationMap map = characteristics
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
width, height, mVideoSize);
int orientation = getResources().getConfiguration().orientation;
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
} else {
mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
}
configureTransform(width, height);
mMediaRecorder = new MediaRecorder();
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException e) {
Toast.makeText(activity, R.string.camera_error, Toast.LENGTH_SHORT).show();
activity.finish();
} catch (NullPointerException e) {
// Currently an NPE is thrown when the Camera2API is used but not supported on the
// device this code runs.
ErrorDialog.newInstance(getString(R.string.camera_error)).show(getChildFragmentManager(), FRAGMENT_DIALOG);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera opening.");
}
}
private void closeCamera() {
try {
mCameraOpenCloseLock.acquire();
if (null != mCameraDevice) {
mCameraDevice.close();
mCameraDevice = null;
}
if (null != mMediaRecorder) {
mMediaRecorder.release();
mMediaRecorder = null;
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted while trying to lock camera closing.");
} finally {
mCameraOpenCloseLock.release();
}
}
/**
* Start the camera preview.
*/
private void startPreview() {
if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
return;
}
try {
setUpMediaRecorder();
SurfaceTexture texture = mTextureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
List<Surface> surfaces = new ArrayList<Surface>();
Surface previewSurface = new Surface(texture);
surfaces.add(previewSurface);
mPreviewBuilder.addTarget(previewSurface);
Surface recorderSurface = mMediaRecorder.getSurface();
surfaces.add(recorderSurface);
mPreviewBuilder.addTarget(recorderSurface);
mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession cameraCaptureSession) {
mPreviewSession = cameraCaptureSession;
updatePreview();
}
@Override
public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
// Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
}
}
}, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Update the camera preview. {@link #startPreview()} needs to be called in advance.
*/
private void updatePreview() {
if (null == mCameraDevice) {
return;
}
try {
setUpCaptureRequestBuilder(mPreviewBuilder);
HandlerThread thread = new HandlerThread("CameraPreview");
thread.start();
mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
}
/**
* Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
* This method should not to be called until the camera preview size is determined in
* openCamera, or until the size of `mTextureView` is fixed.
*
* @param viewWidth The width of `mTextureView`
* @param viewHeight The height of `mTextureView`
*/
private void configureTransform(int viewWidth, int viewHeight) {
//Activity activity = getActivity();
if (null == mTextureView || null == mPreviewSize || null == activity) {
return;
}
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
Matrix matrix = new Matrix();
RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
float centerX = viewRect.centerX();
float centerY = viewRect.centerY();
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
float scale = Math.max(
(float) viewHeight / mPreviewSize.getHeight(),
(float) viewWidth / mPreviewSize.getWidth());
matrix.postScale(scale, scale, centerX, centerY);
matrix.postRotate(90 * (rotation - 2), centerX, centerY);
}
mTextureView.setTransform(matrix);
}
private void setUpMediaRecorder() throws IOException {
// final Activity activity = getActivity();
if (null == activity) {
return;
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
String path = getSDPath();
if (path != null) {
new DateFormat();
String nameString = "huban_vedio.mp4";
SaveFolderName.dirFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/"+SaveFolderName.namefolder + "/");
if(!SaveFolderName.dirFile.exists())
SaveFolderName.dirFile.mkdirs();
path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/"+ SaveFolderName.namefolder + "/" + nameString;
VedioBitmap.pathVedio = path;
mMediaRecorder.setOutputFile(path);
}
mMediaRecorder.setVideoEncodingBitRate(3*512*512);
mMediaRecorder.setVideoFrameRate(20);
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setAudioEncodingBitRate(2*512*512);//設定音訊編碼錄音位元率
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation);
mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
}
/**
* 獲取SD path
* @return
*/
public String getSDPath(){
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState()
.equals(android.os.Environment.MEDIA_MOUNTED); // 判斷sd卡是否存在
if (sdCardExist)
{
sdDir = Environment.getExternalStorageDirectory();// 獲取根目錄
return sdDir.toString();
}
return null;
}
class mTimestampRunnable implements Runnable{
@Override
public void run(){
while (isRunning) {
try {
Thread.sleep(1*1000);
second++;
if(second <= Maxtime*60 && second >= 0)
handler.sendEmptyMessage(1);
if(second == Maxtime*60+1){
handler.sendEmptyMessage(3);
}
} catch (InterruptedException e) {
handler.sendEmptyMessage(4);
}
progressbar.setProgress(second);
}
if(isRunning == false){
handler.sendEmptyMessage(5);
}
}
}
@SuppressLint("HandlerLeak")
Handler handler = new Handler(){
public void handleMessage(Message msg){
switch (msg.what) {
case 1:
if(second < 10 && second >= 0)
timeTextView.setText("00:0"+second);
else if(second >= 10 && second <60)
timeTextView.setText("00:"+second);
else if(second == 60)
timeTextView.setText("01:00");
else if(second >= 60 && second <= Maxtime*60){
int min = second/60;
int sec = second%60;
if(sec < 10)
timeTextView.setText("0"+String.valueOf(min)+":0"+sec);
else
timeTextView.setText("0"+String.valueOf(min)+":"+sec);
}
break;
case 3:
stopRecordingVideo();
break;
case 4:
stopRecordingVideo();
Toast.makeText(getActivity(), R.string.failure_record, Toast.LENGTH_SHORT).show();
break;
case 5:
// Stop recording
try {
if (null != mMediaRecorder) {
mMediaRecorder.stop();
mMediaRecorder.reset();
}
}
catch (Exception e) {
e.printStackTrace();
}
mButtonVideo.setBackgroundResource(R.drawable.lustart);
Bitmap bitmap = GetScreenshop.getVideoThumbnail(VedioBitmap.pathVedio, 80, 80,
MediaStore.Video.Thumbnails.MINI_KIND);
if(bitmap != null)
imageview_screenshop_sdk5.setImageBitmap(bitmap);
if(isHasRecord == true && happen_error == false ){
startPreview();
}
break;
case 6:
Toast.makeText(getActivity(), R.string.camera_error, Toast.LENGTH_SHORT).show();
default:
break;
}
}
};
Thread thread;
private void startRecordingVideo() {
try {
isRunning = true;
isStartRecording = false;
isHasRecord = false;
happen_error = false;
progressbar.setProgress(second);
progressbar.setMax(Maxtime*60);
mButtonVideo.setBackgroundResource(R.drawable.lureset);
// Start recording
mMediaRecorder.start();
thread = new Thread(new mTimestampRunnable());
thread.start();
} catch (IllegalStateException e) {
// e.printStackTrace();
Toast.makeText(activity, R.string.recordmedia_error, Toast.LENGTH_SHORT).show();
isRunning = false;
isStartRecording = true;
isHasRecord = false;
happen_error = false;
mButtonVideo.setBackgroundResource(R.drawable.lustart);
}
}
private void stopRecordingVideo() {
isHasRecord = true;
second = -1;
isRunning = false;
isStartRecording = true;
happen_error = false;
}
/**
* Compares two {@code Size}s based on their areas.
*/
static class CompareSizesByArea implements Comparator<Size> {
@Override
public int compare(Size lhs, Size rhs) {
// We cast here to ensure the multiplications won't overflow
return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
(long) rhs.getWidth() * rhs.getHeight());
}
}
public static class ErrorDialog extends DialogFragment {
private static final String ARG_MESSAGE = "message";
public static ErrorDialog newInstance(String message) {
ErrorDialog dialog = new ErrorDialog();
Bundle args = new Bundle();
args.putString(ARG_MESSAGE, message);
dialog.setArguments(args);
return dialog;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Activity activity = getActivity();
return new AlertDialog.Builder(activity)
.setMessage(getArguments().getString(ARG_MESSAGE))
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
activity.finish();
}
})
.create();
}
}
public static class ConfirmationDialog extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Fragment parent = getParentFragment();
return new AlertDialog.Builder(getActivity())
.setMessage(R.string.permission_request)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
parent.getActivity().finish();
}
})
.create();
}
}
}
我自己是這樣處理的:
@Override
public void onError(CameraDevice cameraDevice, int error) {
happen_error = true;//標記
if(){
closeCamera();
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
}
else if(isHasRecord == false && happen_error == true){
handler.sendEmptyMessage(6);
WhenDonotSupportNewCamera2() ;
}
}