Android screen recording service usage (source code)

Android screen recording service usage (source code)

Starting from Android 5.0, you can record the screen of the mobile phone, and use scenarios: such as video uploading in wrong scenes, simple screen acquisition, etc. The use cases and a brief introduction to the classes used are posted below
- MediaProjection
- MediaRecorder
- VirtualDisplay
-Use- Summarize


MediaProjection

MediaProjection is a new means of screen capture or screen recording provided to developers after 5.0. MediaProjection can be used to capture the screen One of the main methods we use
here is

public VirtualDisplay createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, android.hardware.display.VirtualDisplay.Callback callback, Handler handler) {
        throw new RuntimeException("Stub!");
    }

Parameter 1: The actual streaming media display entity name, cannot be null;

Parameter 2: The width of the actual streaming media display entity, in pixels, must be greater than 0;

Parameter 3: The height of the actual streaming media display entity, in pixels, must be greater than 0;

Parameter 4: The pixel density of the actual streaming media display entity, the unit is dp, which must be greater than 0;

Parameter 5: The combination of actual streaming media display entity flags, please see the flags in DisplayManager for more information, the value is one of {VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY, VIRTUAL_DISPLAY_FLAG_PRESENTATION,
VIRTUAL_DISPLAY_FLAG_PUBLIC,
VIRTUAL_DISPLAY_FLAG_SECURE}

Parameter 6: surface instance for playing streaming media, can be null, if there is no;

Parameter 7: The callback method when the actual streaming media display entity state changes, may be null;

Parameter 8: The handler that calls the callback method of parameter 7;

Return the VirtualDisplay instance, please see the VirtualDisplay class for details;

MediaRecorder

Add support for recording audio and video, the Android system provides this class. The use of this class is also very simple

The following is the configuration for MediaRecorder

setAudioSource(MediaRecorder.AudioSource.);
Set the sound source, generally pass in the MediaRecorder.AudioSource.MIC parameter to specify the recording of the sound from the microphone. (If you only record the screen here, you can not set it)
setVideoSource(MediaRecorder.VideoSource.SURFACE);
Set the video source for recording. Such as screen, etc.
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
Set the format of the recorded audio and video files.
setOutputFile(getsaveDirectory() + temp + ".mp4");
Set the save location of the recorded audio file.
setVideoSize(width, height); The maximum can only be set to 640x480
to set the width to be shot and the height of the video.
setVideoEncoder(MediaRecorder.VideoEncoder.H264);
Set the encoding format of the video
setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
Set the audio encoding format
setVideoEncodingBitRate(1024 * 1024);
Set the encoding bit rate of the recorded video.
setVideoFrameRate(18);
Set the capture frame rate of the recorded video.
setOrientationHint(90);
Set the orientation hint of the output video playback.
setMaxDuration(30*1000);
Set the maximum duration of the recording session (in ms).
prepare();
prepare for recording

VirtualDisplay

The VirtualDisplay class represents a virtual display. You need to call the createVirtualDisplay() method of the DisplayManager class to render the content of the virtual display on a Surface control. When the process terminates, the virtual display will be automatically released, and all windows will be forcibly removed. . When it is no longer used, you should call release() method to release resources.
There are 6 main methods in this class, which are mainly used to operate the display, such as getting the display, setting/getting the surface,

Note that for some apps, such as the recording of each operation of the game, if you create this VirtualDisplay frequently, the phone memory will continue to be consumed and the phone will become a card. Therefore, the created operation is placed in the service, and the system will automatically use the currently created VirtualDisplay. Infrequent creation and non-release

The simple method
Surface getSurface()
gets the surface of the virtual display.
release()
releases the display, and destroys the surface on which it is based.
resize (int width, int height, int densityDpi) The
running application uses the VR to adapt to the changing conditional state without destroying and rebuilding an instance.
setSurface (Surface surface)
Sets the surface the virtual display relies on. Removing the surface on which the virtual display is based is equivalent to turning off the screen. The caller /// needs to manually destroy the surface.

use

Create a service RecordUtil to start this service before recording screen, you can start this service in AppApplication, and bind this service to the specific screen recording interface, pay attention to register this service in AndroidManifest.xml

Serve

public class RecordUtil extends Service {
//    private static RecordUtil recordUtil = null;
    private MediaProjection mediaProjection;



    private MediaRecorder mediaRecorder;
    private  VirtualDisplay virtualDisplay;
    private boolean running;
    private int width = 320;
    private int height = 420;
    private int dpi;
    private Context context;

    public static int current = 0;

    public RecordUtil(){

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new RecordBinder();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread serviceThread = new HandlerThread("service_thread",
                android.os.Process.THREAD_PRIORITY_BACKGROUND);
        serviceThread.start();
        running = false;
        mediaRecorder = new MediaRecorder();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return  START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }



    public void setMediaProject(MediaProjection project) {
        mediaProjection = project;
    }

    public boolean isRunning() {
        return running;
    }

    public void setConfig(int width, int height, int dpi) {
        this.width = width;
        this.height = height;
        this.dpi = dpi;
    }

    public boolean startRecord(String temp) {
        if(mediaRecorder != null) {
            if (mediaProjection == null || running) {
                return false;
            }
            try {
                initRecorder(temp);
                createVirtualDisplay();
                mediaRecorder.start();
                running = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    public boolean stopRecord() {
        if(mediaRecorder != null) {
            if (!running) {
                return false;
            }
            try {
                running = false;
                mediaRecorder.stop();
            mediaRecorder.reset();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    virtualDisplay.release();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        mediaProjection.stop();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return true;
    }

    public boolean release(){
        if(mediaRecorder != null && hasLollipop()) {
            if (!running) {
                return false;
            }
            try {
                running = false;
                mediaRecorder.stop();
                mediaRecorder.reset();
                virtualDisplay.release();
                mediaProjection.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return true;
    }

    public static boolean hasLollipop(){
        return Build.VERSION.SDK_INT >= 21;
    }

    private void createVirtualDisplay() {
//        if(virtualDisplay == null) {
            if(hasLollipop()) {
                virtualDisplay = mediaProjection.createVirtualDisplay("MainScreen", width, height, dpi,
                        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
            }
//        }

    }

    private void initRecorder(String temp) {
        if(mediaRecorder != null) {
            try {
                // mediaRecorder.setAudioSource(MediaRecorder.AudioSource.);
                mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
                mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                mediaRecorder.setOutputFile(getsaveDirectory() + temp + ".mp4");
                //mediaRecorder.setVideoSize(width, height);
                mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
                // mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
                mediaRecorder.setVideoEncodingBitRate(1024 * 1024);
                mediaRecorder.setVideoFrameRate(18);
                //设置要捕获的视频的宽度和高度
                //mSurfaceHolder.setFixedSize(320, 240);//最高只能设置640x480
                mediaRecorder.setVideoSize(width, height);//最高只能设置640x480
                //mediaRecorder.setOrientationHint(90);
                //mediaRecorder.setMaxDuration(30*1000);
                mediaRecorder.prepare();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getsaveDirectory() {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String rootDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "ScreenRecord" + "/";

            File file = new File(rootDir);
            if (!file.exists()) {
                if (!file.mkdirs()) {
                    return null;
                }
            }

            //Toast.makeText(context, rootDir, Toast.LENGTH_SHORT).show();

            return rootDir;
        } else {
            return null;
        }
    }


    /**
     * 递归删除文件
     * @param file
     */
    public static void recursionDeleteFile(File file){
        try {
            if(file.isFile()){
                file.delete();
                return;
            }
            if(file.isDirectory()){
                File[] childFile = file.listFiles();
                if(childFile == null || childFile.length == 0){
                    file.delete();
                    return;
                }
                for(File f : childFile){
                    recursionDeleteFile(f);
                }
                file.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public class RecordBinder extends Binder {
        public RecordUtil getRecordService() {
            return RecordUtil.this;
        }
    }
}

AppApplication

 startService(new Intent(this, RecordUtil.class));

Activity


 public MediaProjectionManager projectionManager;
 public MediaProjection mediaProjection;
 public RecordUtil recordService;

 绑定服务
 public void bind(){
   Intent intent = new Intent(this, RecordUtil.class);
   bindService(intent, connection, BIND_AUTO_CREATE);
}

并在Activity重写
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        try {
            Logger.i("----activity-->" + requestCode + "---result--->" + resultCode);

            Logger.i("----activity-->" + requestCode + "---result--->" + resultCode);
            UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data);

            if(DeviceUtils.hasLollipop()) {
                if (requestCode == 101 && resultCode == RESULT_OK) {
//                   RecordUtil recordUtil=new RecordUtil();
                    if (RecordUtil.hasLollipop()) {
                        Logger.e("________________________onActivityResult");
                        mediaProjection = projectionManager.getMediaProjection(resultCode, data);
                        recordService.setMediaProject(mediaProjection);
                        /*if (RecordUtil.current > 3) {
                            RecordUtil.current = 0;
                        }*/
                        RecordUtil.current++;
                        //RecordUtil.getInstance().setOutFile("temp"+RecordUtil.current);
                        recordService.startRecord("temp" + RecordUtil.current);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
 private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            DisplayMetrics metrics = new DisplayMetrics();
            getWindowManager().getDefaultDisplay().getMetrics(metrics);
            RecordUtil.RecordBinder binder = (RecordUtil.RecordBinder) service;
            recordService = binder.getRecordService();
            recordService.setConfig(320, 420, metrics.densityDpi);
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {}
    };
 @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);

    }

Start screen recording

if(RecordUtil.hasLollipop()) {
                                if(mediaProjection != null){
                                    if(ecordService.isRunning()){
                                        recordService.stopRecord();
                                    }
                                }
                                Logger.e("_________________________录制视频开始");
                                RecordUtil.current++;
                                Intent captureIntent =projectionManager.createScreenCaptureIntent();
         startActivityForResult(captureIntent, RECORD_REQUEST_CODE);
                                if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                                        != PackageManager.PERMISSION_GRANTED) {
                                    ActivityCompat.requestPermissions(mActivity,
                                            new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_REQUEST_CODE);
                                }

                                if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.RECORD_AUDIO)
                                        != PackageManager.PERMISSION_GRANTED) {
                                    ActivityCompat.requestPermissions(mActivity,
                                            new String[] {Manifest.permission.RECORD_AUDIO}, AUDIO_REQUEST_CODE);
                                }


                            }

Get screen recording file path

  if (recordService.isRunning()) {
                       recordService.stopRecord();
      }
    try {
                            File file = new File(RecordUtil.getsaveDirectory() + "temp" + RecordUtil.current + ".mp4");
                            Logger.i("----file exit--->" + file.exists() + "-----file url--->" + file.getAbsolutePath());
                            if (file.exists()) {
                                //上传
                                Logger.e("_________________________存在");
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

The road is still long, go slowly

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324847744&siteId=291194637