嘿,我有一个完整的正在运行的应用程序,女巫开始从前台服务捕获屏幕内容但是当我在停止后第二次尝试录制时它崩溃了
这是整个场景:我正在从这样的主要活动开始前台服务:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_CANCELED && requestCode == Const.SCREEN_RECORD_REQUEST_CODE) {
Toast.makeText(this,
getString(R.string.screen_recording_permission_denied), Toast.LENGTH_SHORT).show();
if (getIntent().getAction().equals(getString(R.string.app_shortcut_action)))
finish();
return;
}
Intent recorderService = new Intent(this, IZIGaapsRecordingSession.class);
recorderService.putExtra(Const.RECORDER_INTENT_DATA, data);
recorderService.putExtra(Const.RECORDER_INTENT_RESULT, resultCode);
recorderService.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(recorderService);
finish();
}
然后服务是这样的:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
data = intent.getParcelableExtra(Const.RECORDER_INTENT_DATA);
result = intent.getIntExtra(Const.RECORDER_INTENT_RESULT, Activity.RESULT_OK);
Intent recordStartIntent = new Intent(this, IZIGaapsRecordingSession.class);
recordStartIntent.setAction(Const.SCREEN_RECORDING_START);
PendingIntent precordStartIntent = PendingIntent.getService(this, 0, recordStartIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action(R.drawable.ic_pause_black_24dp,
getString(R.string.screen_notification_action_start), precordStartIntent);
startNotificationForeGround(createRecordingNotification(action).build(), Const.SCREEN_RECORDER_NOTIFICATION_ID);
switch (intent.getAction()) {
case Const.SCREEN_RECORDING_START:
if (!isRecording) {
getValues();
startRecording();
}
} else {
Toast.makeText(this, R.string.screenrecording_already_active_toast, Toast.LENGTH_SHORT).show();
}
break;
case Const.SCREEN_RECORDING_PAUSE:
pauseScreenRecording();
break;
case Const.SCREEN_RECORDING_RESUME:
resumeScreenRecording();
break;
case Const.SCREEN_RECORDING_STOP:
stopScreenSharing();
stopForeground(true);
break;
}
return START_STICKY;
}
@TargetApi(24)
private void pauseScreenRecording() {
mMediaRecorder.pause();
elapsedTime += (System.currentTimeMillis() - startTime);
Intent recordResumeIntent = new Intent(this, IZIGaapsRecordingSession.class);
recordResumeIntent.setAction(Const.SCREEN_RECORDING_RESUME);
PendingIntent precordResumeIntent = PendingIntent.getService(this, 0, recordResumeIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action(android.R.drawable.ic_media_play,
getString(R.string.screen_recording_notification_action_resume), precordResumeIntent);
updateNotification(createRecordingNotification(action).setUsesChronometer(false).build(), Const.SCREEN_RECORDER_NOTIFICATION_ID);
//Toast.makeText(this, R.string.screen_recording_paused_toast, Toast.LENGTH_SHORT).show();
}
@TargetApi(24)
private void resumeScreenRecording() {
mMediaRecorder.resume();
startTime = System.currentTimeMillis();
Intent recordPauseIntent = new Intent(this, IZIGaapsRecordingSession.class);
recordPauseIntent.setAction(Const.SCREEN_RECORDING_PAUSE);
PendingIntent precordPauseIntent = PendingIntent.getService(this, 0, recordPauseIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action(android.R.drawable.ic_media_pause,
getString(R.string.screen_recording_notification_action_pause), precordPauseIntent);
updateNotification(createRecordingNotification(action).setUsesChronometer(true)
.setWhen((System.currentTimeMillis() - elapsedTime)).build(), Const.SCREEN_RECORDER_NOTIFICATION_ID);
}
private void startRecording() {
mMediaRecorder = new MediaRecorder();
initRecorder();
mMediaProjectionCallback = new MediaProjectionCallback();
MediaProjectionManager mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
mMediaProjection = mProjectionManager.getMediaProjection(result, data);
mMediaProjection.registerCallback(mMediaProjectionCallback, null);
if (mVirtualDisplay == null)
mVirtualDisplay = createVirtualDisplay();
try {
mMediaRecorder.start();
isRecording = true;
} catch (IllegalStateException e){
isRecording = false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
startTime = System.currentTimeMillis();
Intent recordPauseIntent = new Intent(this, IZIGaapsRecordingSession.class);
recordPauseIntent.setAction(Const.SCREEN_RECORDING_PAUSE);
PendingIntent precordPauseIntent = PendingIntent.getService(this, 0, recordPauseIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action(android.R.drawable.ic_media_pause,
getString(R.string.screen_recording_notification_action_pause), precordPauseIntent);
startNotificationForeGround(createRecordingNotification(action).build(), Const.SCREEN_RECORDER_NOTIFICATION_ID);
}else if (isRecording) {
stopScreenRecording();
}
}
private void stopScreenRecording() {
Intent recordStopIntent = new Intent(this, IZIGaapsRecordingSession.class);
recordStopIntent.setAction(Const.SCREEN_RECORDING_STOP);
PendingIntent precordStopIntent = PendingIntent.getService(this, 0, recordStopIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action(R.drawable.ic_notification_stop,
getString(R.string.screen_recording_notification_action_stop), precordStopIntent);
updateNotification(createRecordingNotification(action).build(), Const.SCREEN_RECORDER_NOTIFICATION_ID);
}
private VirtualDisplay createVirtualDisplay() {
return mMediaProjection.createVirtualDisplay("IZIGaapsMain",
WIDTH, HEIGHT, DENSITY_DPI,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mMediaRecorder.getSurface(), null , null);
}
private void initRecorder() {
try {
if (mustRecAudio)
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mMediaRecorder.setOutputFile(SAVEPATH);
mMediaRecorder.setVideoSize(WIDTH, HEIGHT);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
if (mustRecAudio)
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mMediaRecorder.setVideoEncodingBitRate(BITRATE);
mMediaRecorder.setVideoFrameRate(FPS);
int rotation = window.getDefaultDisplay().getRotation();
int orientation = ORIENTATIONS.get(rotation + 90);
mMediaRecorder.setOrientationHint(orientation);
mMediaRecorder.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
private NotificationCompat.Builder createRecordingNotification(NotificationCompat.Action action) {
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.rec_icon);
Intent UIIntent = new Intent(this, IZIGaapsMain.class);
PendingIntent notificationContentIntent = PendingIntent.getActivity(this, 0, UIIntent, 0);
NotificationCompat.Builder notification = new NotificationCompat.Builder(this, Const.RECORDING_NOTIFICATION_CHANNEL_ID)
.setContentTitle(getResources().getString(R.string.screen_recording_notification_title))
.setTicker(getResources().getString(R.string.screen_recording_notification_title))
.setSmallIcon(R.drawable.rec_icon)
.setLargeIcon(
Bitmap.createScaledBitmap(icon, 128, 128, false))
.setPriority(Notification.PRIORITY_MIN);
/* .addAction(R.drawable.ic_pause_black_24dp, getResources().getString(R.string.screen_notification_action_start),
precordStartIntent); */
if (action != null)
notification.addAction(action);
return notification;
}
private void startNotificationForeGround(Notification notification, int ID) {
startForeground(ID, notification);
}
private void updateNotification(Notification notification, int ID) {
getManager().notify(ID, notification);
}
private NotificationManager getManager() {
if (mNotificationManager == null) {
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
return mNotificationManager;
}
@Override
public void onDestroy() {
super.onDestroy();
stopScreenSharing();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void getValues() {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
String res = prefs.getString(getString(R.string.res_key), getResolution());
setWidthHeight(res);
FPS = Integer.parseInt(prefs.getString(getString(R.string.fps_key), "30"));
BITRATE = Integer.parseInt(prefs.getString(getString(R.string.bitrate_key), "7130317"));
mustRecAudio = prefs.getBoolean(getString(R.string.audiorec_key), false);
String saveLocation = prefs.getString(getString(R.string.savelocation_key),
Environment.getExternalStorageDirectory() + File.separator + Const.APPDIR);
File saveDir = new File(saveLocation);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !saveDir.isDirectory()) {
saveDir.mkdirs();
}
useFloatingControls = prefs.getBoolean(getString(R.string.preference_floating_control_key), false);
counters = prefs.getInt("key",0);
SAVEPATH = saveLocation + File.separator + "Recording" + "- " + counters + ".mp4";
}
private void setWidthHeight(String res) {
String[] widthHeight = res.split("x");
WIDTH = Integer.parseInt(widthHeight[0]);
HEIGHT = Integer.parseInt(widthHeight[1]);
}
private String getResolution() {
DisplayMetrics metrics = new DisplayMetrics();
window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
window.getDefaultDisplay().getMetrics(metrics);
DENSITY_DPI = metrics.densityDpi;
int width = metrics.widthPixels;
int height = metrics.heightPixels;
return width + "x" + height;
}
private void destroyMediaProjection() {
try {
mMediaRecorder.stop();
indexFile();
} catch (RuntimeException e) {
if (new File(SAVEPATH).delete())
Toast.makeText(this, getString(R.string.fatal_exception_message), Toast.LENGTH_SHORT).show();
} finally {
mMediaRecorder.reset();
mVirtualDisplay.release();
mVirtualDisplay = null;
mMediaRecorder.release();
if (mMediaProjection != null) {
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
}
isRecording = false;
Intent recordStartIntent = new Intent(this, IZIGaapsRecordingSession.class);
recordStartIntent.setAction(Const.SCREEN_RECORDING_START);
PendingIntent precordStartIntent = PendingIntent.getService(this, 0, recordStartIntent, 0);
NotificationCompat.Action action = new NotificationCompat.Action(R.drawable.ic_pause_black_24dp,
getString(R.string.screen_notification_action_start), precordStartIntent);
updateNotification(createRecordingNotification(action).build(), Const.SCREEN_RECORDER_NOTIFICATION_ID);
}
private void indexFile() {
ArrayList<String> toBeScanned = new ArrayList<>();
toBeScanned.add(SAVEPATH);
String[] toBeScannedStr = new String[toBeScanned.size()];
toBeScannedStr = toBeScanned.toArray(toBeScannedStr);
MediaScannerConnection.scanFile(this, toBeScannedStr, null, (path, uri) -> {
Message message = mHandler.obtainMessage();
message.sendToTarget();
stopSelf();
});
}
Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message message) {
}
};
private void stopScreenSharing() {
if (mVirtualDisplay == null) {
return;
}
destroyMediaProjection();
counters = counters + 1;
prefs.edit().putInt("key", counters).apply();
}
private class MediaProjectionCallback extends MediaProjection.Callback {
@Override
public void onStop() {
stopScreenSharing();
}
}
}
但是它因这个 logcat 错误而崩溃
12-06 19:49:03.681 9454-9454/com.IZIGaaps.MyRecorder E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.IZIGaaps.MyRecorder, PID: 9454
java.lang.RuntimeException: Unable to start service com.IZIGaaps.MyRecorder.IZIGaapsRecordingSession@859c9ab with Intent { act=com.IZIGaaps.MyRecorder.services.action.startrecording flg=0x10000000 cmp=com.IZIGaaps.MyRecorder/.IZIGaapsRecordingSession VirtualScreenParam=Params{mDisplayId=-1, null, mFlags=0x00000000)} bnds=[743,691][1075,805] }: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.display.VirtualDisplay android.media.projection.MediaProjection.createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay$Callback, android.os.Handler)' on a null object reference
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4150)
at android.app.ActivityThread.access$2400(ActivityThread.java:230)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1925)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7409)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.hardware.display.VirtualDisplay android.media.projection.MediaProjection.createVirtualDisplay(java.lang.String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay$Callback, android.os.Handler)' on a null object reference
at com.IZIGaaps.MyRecorder.IZIGaapsRecordingSession.createVirtualDisplay(IZIGaapsRecordingSession.java:321)
at com.IZIGaaps.MyRecorder.IZIGaapsRecordingSession.startRecording(IZIGaapsRecordingSession.java:276)
at com.IZIGaaps.MyRecorder.IZIGaapsRecordingSession.onStartCommand(IZIGaapsRecordingSession.java:194)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4133)
at android.app.ActivityThread.access$2400(ActivityThread.java:230)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1925)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7409)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
不知道我已经知道关于空指针的问题出在哪里,我对此做了一些事情,但没有奏效
顺便说一句,任何帮助将不胜感激