我正在尝试在 android 中创建背景录像机。为此,我创建了一个Service
类来实现视频录制。当我按下按钮开始录制时,它开始成功,但是当我停止它时,出现以下异常:
06-27 17:32:20.974 20244-21916/com.svtech.thirdeye.thirdeye E/MediaRecorderJNI: Application lost the surface
06-27 17:32:24.513 20244-21848/com.svtech.thirdeye.thirdeye E/NativeCrypto: ssl=0x587e0d60 cert_verify_callback x509_store_ctx=0x54ab7a48 arg=0x0
06-27 17:32:24.513 20244-21848/com.svtech.thirdeye.thirdeye E/NativeCrypto: ssl=0x587e0d60 cert_verify_callback calling verifyCertificateChain authMethod=ECDHE_ECDSA
06-27 17:32:25.009 20244-20244/com.svtech.thirdeye.thirdeye E/MediaRecorder: stop called in an invalid state: 4
06-27 17:32:25.033 20244-20244/com.svtech.thirdeye.thirdeye E/AndroidRuntime:
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to stop service com.svtech.thirdeye.thirdeye.Services.VideoRecordingOldApiService@424cfbb8: java.lang.IllegalStateException
at android.app.ActivityThread.handleStopService(ActivityThread.java:2894)
at android.app.ActivityThread.access$2000(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5371)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException
at android.media.MediaRecorder.stop(Native Method)
at com.svtech.thirdeye.thirdeye.Services.VideoRecordingOldApiService.onDestroy(VideoRecordingOldApiService.java:129)
at android.app.ActivityThread.handleStopService(ActivityThread.java:2877)
at android.app.ActivityThread.access$2000(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1466)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5371)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
这是我的VideoRecordingOldApiService
课
public class VideoRecordingOldApiService extends Service {
private Handler handler;
protected String fileName;
private Camera mCamera;
private CameraPreview cameraPreview;
private MediaRecorder videoRecorder;
private CameraCheck cameraCheck;
private Thread recorderThread;
public VideoRecordingOldApiService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
recorderThread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
mCamera = cameraCheck.getDesiredCamera(getApplicationContext(),
Camera.CameraInfo.CAMERA_FACING_BACK, handler);
cameraPreview = new CameraPreview(getApplicationContext(), mCamera);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), R.string.video_recorder_started, Toast.LENGTH_SHORT).show();
}
});
mCamera.unlock();
videoRecorder.setCamera(mCamera);
videoRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
videoRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
videoRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
videoRecorder.setOutputFile(fileName);
videoRecorder.setPreviewDisplay(cameraPreview.getHolder().getSurface());
try {
videoRecorder.prepare();
videoRecorder.start();
} catch (Exception e) {
e.printStackTrace();
}
}
});
recorderThread.start();
return START_REDELIVER_INTENT;
}
@Override
public void onCreate() {
getFileName();
handler = new Handler();
videoRecorder = new MediaRecorder();
cameraCheck = new CameraCheck();
//Setup Notification
final Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.addCategory("android.intent.category.LAUNCHER");
final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification;
notification = new Notification.Builder(getApplicationContext())
.setSmallIcon(R.drawable.videorecordicon)
.setOngoing(true)
.setPriority(Notification.PRIORITY_DEFAULT)
.setContentTitle(getResources().getString(R.string.video_recorder_notification))
.setContentText(getResources().getString(R.string.notification_video_text) + "...")
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
}
@Override
public void onDestroy() {
if (videoRecorder != null){
videoRecorder.stop();
videoRecorder.release();
videoRecorder = null;
Toast.makeText(getApplicationContext(), R.string.recording_done, Toast.LENGTH_SHORT).show();
recorderThread.interrupt();
mCamera.lock();
if (mCamera != null){
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
public String getFileName (){
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
+ "/" + "video_record" + System.currentTimeMillis() + ".mp4";
} else {
Toast.makeText(getApplicationContext(), "No External Storage Found", Toast.LENGTH_LONG).show();
}
return fileName;
}
}
编辑:
这是我修改后的VideoRecordingOldApiService
课程:
public class VideoRecordingOldApiService extends Service implements MediaRecorder.OnInfoListener, MediaRecorder.OnErrorListener {
private Camera mCamera;
private String outputFile;
private FrameLayout frameLayout;
private MediaRecorder mMediaRecorder;
private CameraCheck cameraCheck;
private final static String TAG = "VideoRecorderService";
private CameraPreview cameraPreview;
public VideoRecordingOldApiService() {
}
@Override
public void onCreate() {
cameraCheck = new CameraCheck();
frameLayout = MainActivity.PlaceholderFragment.previewFrameLayout;
//Setup Notification
final Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.addCategory("android.intent.category.LAUNCHER");
final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification;
notification = new Notification.Builder(getApplicationContext())
.setSmallIcon(R.drawable.videorecordicon)
.setOngoing(true)
.setPriority(Notification.PRIORITY_DEFAULT)
.setContentTitle(getResources().getString(R.string.video_recorder_notification))
.setContentText(getResources().getString(R.string.notification_video_text) + "...")
.setContentIntent(pendingIntent).build();
startForeground(1, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), R.string.video_recorder_started, Toast.LENGTH_LONG).show();
if (initCamera()) {
initRecorder();
} else {
Toast.makeText(getApplicationContext(), "Camera not found", Toast.LENGTH_SHORT).show();
}
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
stopRecording();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
public String getFileName() {
String fileName = null;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
+ "/" + "video_record" + System.currentTimeMillis() + ".mp4";
Log.i("Camera Recorder", fileName);
} else {
Toast.makeText(getApplicationContext(), "No External Storage Found", Toast.LENGTH_LONG).show();
}
return fileName;
}
private boolean initCamera() {
try {
mCamera = cameraCheck.getDesiredCamera(this, Camera.CameraInfo.CAMERA_FACING_FRONT);
cameraPreview = new CameraPreview(getApplicationContext(), mCamera);
frameLayout.addView(cameraPreview);
} catch (Exception e) {
Log.v(TAG, "Could not initialise the camera");
e.printStackTrace();
return false;
}
return true;
}
private void initRecorder() {
if (mMediaRecorder == null) {
mMediaRecorder = new MediaRecorder();
outputFile = getFileName();
try {
// mCamera.unlock();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));
mMediaRecorder.setOutputFile(outputFile);
mMediaRecorder.setPreviewDisplay(cameraPreview.getHolder().getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (Exception e) {
Log.v(TAG, "MediaRecorder failed to initialize");
e.printStackTrace();
}
mMediaRecorder.setOnInfoListener(this);
mMediaRecorder.setOnErrorListener(this);
}
}
@Override
public void onInfo (MediaRecorder mr,int what, int extra){
}
@Override
public void onError (MediaRecorder mr,int what, int extra){
}
private void stopRecording() {
try {
mMediaRecorder.stop();
} catch (Exception e) {
//This can happen if recorder has already stopped.
Log.e(TAG, "Got IllegalStateException in stopRecording " + e.getMessage());
}
releaseRecorder();
Toast.makeText(getApplicationContext(), R.string.recording_done, Toast.LENGTH_SHORT).show();
releaseCamera();
}
private void releaseRecorder() {
if (mMediaRecorder != null) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
}
}
private void releaseCamera() {
if (mCamera != null) {
//mCamera.lock();
mCamera.release();
mCamera = null;
}
}
}
我现在正在获取相机预览。MediaRecorder 正在目录中创建文件,但不知何故我仍在IllegalStateException
继续onStop()
。有人可以帮忙吗????