Включить запись экрана с помощью фоновой службы - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь сделать экранный рекордер, используя фоновый сервис. Как только MainActivity вызывает его, служба запускается с записи экрана. Я получаю сообщение об ошибке во время создания виртуального дисплея. Ошибка: java.lang.NullPointerException: Attempt to invoke virtual method 'createVirtualDisplay'

MainActivity. java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ....
    startService(new Intent(getApplicationContext(), service.class));
    ....
}

Сервис. java

package com.gautam.screenRecorder;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Environment;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.IOException;


import static android.os.Environment.DIRECTORY_MOVIES;

public class service extends Service   implements SurfaceHolder.Callback{
private MediaRecorder mMediaRecorder;
private static final int DISPLAY_WIDTH = 480;
private static final int DISPLAY_HEIGHT = 640;
private VirtualDisplay mVirtualDisplay;

private MediaProjection mMediaProjection;
MediaProjectionManager mProjectionManager;
private SurfaceView surfaceView;
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Toast.makeText(this, "Service starte by user.", Toast.LENGTH_LONG).show();

    surfaceView = new SurfaceView(getApplicationContext());

    mProjectionManager = (MediaProjectionManager)
            this.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    try {
        startRecording(1,intent);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return START_STICKY;
}

private void startRecording(int resultCode, Intent data) throws InterruptedException {
    mMediaRecorder = new MediaRecorder();
    DisplayMetrics metrics = new DisplayMetrics();
    WindowManager wm = (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE);
    wm.getDefaultDisplay().getRealMetrics(metrics);
    int displayWidth = metrics.widthPixels;
    int displayHeight = metrics.heightPixels;
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mMediaRecorder.setVideoEncodingBitRate(8 * 1000 * 1000);
    mMediaRecorder.setVideoFrameRate(15);
    mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);

    String videoDir = Environment.getExternalStoragePublicDirectory(DIRECTORY_MOVIES).getAbsolutePath();
    Long timestamp = System.currentTimeMillis();

    String orientation = "portrait";
    if( displayWidth > displayHeight ) {
        orientation = "landscape";
    }
    String filePathAndName = videoDir + "/time_" + timestamp.toString() + "_mode_" + orientation + ".mp4";

    mMediaRecorder.setOutputFile( filePathAndName );

    try {
        mMediaRecorder.prepare();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
    mVirtualDisplay = createVirtualDisplay();
    mMediaRecorder.start();
    wait(2000);
    stopRecording();
    Log.v("screen", "Started recording");
}

private VirtualDisplay createVirtualDisplay() {
    DisplayMetrics metrics = new DisplayMetrics();
    WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    Display display = window.getDefaultDisplay();
    window.getDefaultDisplay().getMetrics(metrics);
    int mScreenDensity;
    mScreenDensity = metrics.densityDpi;

    VirtualDisplay vd=mMediaProjection.createVirtualDisplay("MainActivity",
            DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            surfaceView.getHolder().getSurface(), null /*Callbacks*/, null /*Handler*/);

    return  vd;
}

private void stopRecording() {
    mMediaRecorder.stop();
    mMediaProjection.stop();
    mMediaRecorder.release();
    mVirtualDisplay.release();
}

@Override
public void onDestroy() {
    //super.onDestroy();
    Toast.makeText(this, "Service destroyed by user.", Toast.LENGTH_LONG).show();
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.v("surface","created");
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}
}

Ошибка

2020-04-13 18:23:26.623 14877-14877/com.android.systemupdates D/AndroidRuntime: Shutting down VM
2020-04-13 18:23:26.632 14877-14877/com.android.systemupdates E/AndroidRuntime: FATAL EXCEPTION: main

 Process: com.android.systemupdates, PID: 14877
    java.lang.RuntimeException: Unable to start service com.android.systemupdates.service@c7be1f4 with Intent { cmp=com.android.systemupdates/.service }: 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:3935)
        at android.app.ActivityThread.access$1700(ActivityThread.java:241)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1838)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7156)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
     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.android.systemupdates.service.createVirtualDisplay(service.java:119)
        at com.android.systemupdates.service.startRecording(service.java:104)
        at com.android.systemupdates.service.onStartCommand(service.java:60)
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3916)
        at android.app.ActivityThread.access$1700(ActivityThread.java:241) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1838) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7156) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975) 

[Примечание] -Версия с его использованием Android Версия 6.0. -Принятие решения без использования уведомлений.

...