我正在尝试创建后台视频录制 Android应用程序,该应用程序在后台(当应用程序不在前台时)以及屏幕关闭时录制视频。我在PlayStore中发现了一些可以执行此功能的应用程序,因此我相信这是可行的。
我尝试使用服务和活动来实现此目的。该活动有两个按钮和一个SurfaceView。当我单击开始录制按钮时,该服务开始使用MediaRecorder录制视频,并且应用程序进入后台。当我再次从后台打开该应用程序以停止视频录制并单击 Stop Recording (停止录制)按钮时,该应用程序将崩溃并显示以下日志。我在这里搜索过,发现与此相关的代码不同,但是找不到任何可以帮助我解决此问题的解决方案。
08-13 22:04:50.085 24729-24729/com.meowme.camerarecorder E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.meowme.camerarecorder, PID: 24729
java.lang.RuntimeException: Unable to stop service com.meowme.camerarecorder.RecorderService@38a64c2: java.lang.IllegalStateException
at android.app.ActivityThread.handleStopService(ActivityThread.java:3727)
at android.app.ActivityThread.-wrap27(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1806)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6940)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.IllegalStateException
at android.media.MediaRecorder._stop(Native Method)
at android.media.MediaRecorder.stop(MediaRecorder.java:1306)
at com.meowme.camerarecorder.RecorderService.stopRecording(RecorderService.java:164)
at com.meowme.camerarecorder.RecorderService.onDestroy(RecorderService.java:92)
at android.app.ActivityThread.handleStopService(ActivityThread.java:3709)
at android.app.ActivityThread.-wrap27(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1806)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6940)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
CameraRecorder.java
public class CameraRecorder extends Activity implements SurfaceHolder.Callback {
private static final String TAG = CameraRecorder.class.getSimpleName();
public static final int RequestPermissionCode = 7;
public static SurfaceView mSurfaceView;
public static SurfaceHolder mSurfaceHolder;
public static Camera mCamera;
public static boolean mPreviewRunning;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (CheckingPermissionIsEnabledOrNot()) {
initializeMainActivity();
} else {
RequestMultiplePermission();
}
}
private void initializeMainActivity() {
setContentView(R.layout.main);
mSurfaceView = findViewById(R.id.surfaceView1);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
Button btnStart = findViewById(R.id.StartService);
btnStart.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(CameraRecorder.this, RecorderService.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startService(intent);
finish();
}
});
Button btnStop = findViewById(R.id.StopService);
btnStop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopService(new Intent(CameraRecorder.this, RecorderService.class));
}
});
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
public boolean CheckingPermissionIsEnabledOrNot() {
int FirstPermissionResult = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);
int SecondPermissionResult = ContextCompat.checkSelfPermission(getApplicationContext(), RECORD_AUDIO);
int ThirdPermissionResult = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE);
return FirstPermissionResult == PackageManager.PERMISSION_GRANTED &&
SecondPermissionResult == PackageManager.PERMISSION_GRANTED &&
ThirdPermissionResult == PackageManager.PERMISSION_GRANTED;
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case RequestPermissionCode:
if (grantResults.length > 0) {
boolean CameraPermission = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean RecordAudioPermission = grantResults[1] == PackageManager.PERMISSION_GRANTED;
boolean ExternalStoragePermission = grantResults[2] == PackageManager.PERMISSION_GRANTED;
if (CameraPermission && RecordAudioPermission && ExternalStoragePermission) {
Toast.makeText(CameraRecorder.this, "Permission Granted", Toast.LENGTH_LONG).show();
// TODO show activity here..
initializeMainActivity();
}
else {
Toast.makeText(CameraRecorder.this, "Permission Denied", Toast.LENGTH_LONG).show();
finish();
}
}
break;
}
}
private void RequestMultiplePermission() {
// Creating String Array with Permissions.
ActivityCompat.requestPermissions(CameraRecorder.this, new String[]
{
CAMERA,
RECORD_AUDIO,
WRITE_EXTERNAL_STORAGE,
}, RequestPermissionCode);
}
}
RecorderService.java
public class RecorderService extends Service {
private static final String TAG = "RecorderService";
private SurfaceView mSurfaceView;
private SurfaceHolder mSurfaceHolder;
private static Camera mServiceCamera;
private boolean mRecordingStatus;
private MediaRecorder mMediaRecorder;
@Override
public void onCreate() {
mRecordingStatus = false;
mServiceCamera = CameraRecorder.mCamera;
mSurfaceView = CameraRecorder.mSurfaceView;
mSurfaceHolder = CameraRecorder.mSurfaceHolder;
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
if (mRecordingStatus == false)
startRecording();
return START_STICKY;
}
@Override
public void onDestroy() {
stopRecording();
mRecordingStatus = false;
super.onDestroy();
}
public boolean startRecording() {
try {
Toast.makeText(getBaseContext(), "Recording Started", Toast.LENGTH_SHORT).show();
mServiceCamera = Camera.open();
Camera.Parameters params = mServiceCamera.getParameters();
mServiceCamera.setParameters(params);
Camera.Parameters p = mServiceCamera.getParameters();
final List<Size> listPreviewSize = p.getSupportedPreviewSizes();
for (Size size : listPreviewSize) {
Log.i(TAG, String.format("Supported Preview Size (%d, %d)", size.width, size.height));
}
Size previewSize = listPreviewSize.get(0);
p.setPreviewSize(previewSize.width, previewSize.height);
mServiceCamera.setParameters(p);
try {
mServiceCamera.setPreviewDisplay(mSurfaceHolder);
mServiceCamera.startPreview();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
mServiceCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mServiceCamera);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory().getPath() + "video" + System.currentTimeMillis() + ".mp4");
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.prepare();
mMediaRecorder.start();
mRecordingStatus = true;
return true;
} catch (IllegalStateException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
} catch (IOException e) {
Log.d(TAG, e.getMessage());
e.printStackTrace();
return false;
}
}
public void stopRecording() {
Toast.makeText(getBaseContext(), "Recording Stopped", Toast.LENGTH_SHORT).show();
try {
mServiceCamera.reconnect();
} catch (IOException e) {
e.printStackTrace();
}
mMediaRecorder.stop();
mMediaRecorder.reset();
mServiceCamera.stopPreview();
mMediaRecorder.release();
mServiceCamera.release();
mServiceCamera = null;
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<Button
android:id="@+id/StartService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:background="#5699e6"
android:padding="16dp"
android:text="Start Recording"
android:textColor="#fff"
android:textSize="15sp">
</Button>
<Button
android:id="@+id/StopService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="5dp"
android:background="#5699e6"
android:layout_marginBottom="16dp"
android:padding="16dp"
android:text="Stop Recording"
android:textColor="#fff"
android:textSize="15sp"></Button>
<SurfaceView
android:id="@+id/surfaceView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</SurfaceView>
</LinearLayout>
如果有人可以指导我如何解决此问题,那将真的很有帮助。
答案 0 :(得分:0)
快速查看崩溃日志可以告诉我,很可能是在关闭服务时发生的。在“ stopRecording()”中,调用mMediaRecorder.stop(),它似乎已停止,因为它引发了IllegalStateException。
在停止之前,检查媒体记录器是否正在运行。
答案 1 :(得分:0)
请使用此代码为我工作
mMediaRecorder.setOutputFile(
Environment.getExternalStorageDirectory()+"/"+
DateFormat.format("yyyy-MM-dd_kk-mm-ss", new Date().getTime())+
".mp4"
);