Code Monkey home page Code Monkey logo

screenrecorder's Introduction

ScreenRecorder

Android 5.0+ 屏幕录制

从 Android 4.4 开始支持手机端本地录屏,但首先需要获取 root 权限才行,Android 5.0 引入 MediaProject, 可以不用 root 就可以录屏,但需要弹权限获取窗口,需要用户允许才行,这里主要介绍 Android 5.0+ 利用 MediaProject 在非 root 情况下实现屏幕录制。

基本原理

在 Android 5.0,Google 终于开放了视频录制的接口,其实严格来说,是屏幕采集的接口,也就是 MediaProjection 和 MediaProjectionManager。

具体实现步骤

1 申请权限

在 AndroidManifest 中添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

Android 6.0 加入的动态权限申请,如果应用的 targetSdkVersion 是 23,申请敏感权限还需要动态申请

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

2 获取 MediaProjectionManager 实例

MediaProjectionManager 也是系统服务的一种,通过 getSystemService 来获取实例

MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);

3 发起屏幕捕捉请求

Intent captureIntent= projectionManager.createScreenCaptureIntent(); 
startActivityForResult(captureIntent, REQUEST_CODE);

4 获取 MediaProjection

通过 onActivityResult 返回结果获取 MediaProjection

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
    mediaProjection = projectionManager.getMediaProjection(resultCode, data);
  }
}

5 创建虚拟屏幕

这一步就是通过 MediaProject 录制屏幕的关键所在,VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 参数是指创建屏幕镜像,所以我们实际录制内容的是屏幕镜像,但内容和实际屏幕是一样的,并且这里我们把 VirtualDisplay 的渲染目标 Surface 设置为 MediaRecordergetSurface,后面我就可以通过 MediaRecorder 将屏幕内容录制下来,并且存成 video 文件

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

6 录制屏幕数据

这里利用 MediaRecord 将屏幕内容保存下来,当然也可以利用其它方式保存屏幕内容,例如:ImageReader

private void initRecorder() {
  File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".mp4");
  mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
  mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
  mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
  mediaRecorder.setOutputFile(file.getAbsolutePath());
  mediaRecorder.setVideoSize(width, height);
  mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
  mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
  mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
  mediaRecorder.setVideoFrameRate(30);
  try {
    mediaRecorder.prepare();
  } catch (IOException e) {
    e.printStackTrace();
  }
}

public boolean startRecord() {
  if (mediaProjection == null || running) {
    return false;
  }
  initRecorder();
  createVirtualDisplay();
  mediaRecorder.start();
  running = true;
  return true;
}

screenrecorder's People

Contributors

glt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

screenrecorder's Issues

java.lang.ArrayIndexOutOfBoundsException

Here will case ArrayIndexOutOfBoundsException in MainActivity

if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {

exception


E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.glgjing.recorder, PID: 12158
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.glgjing.recorder/com.glgjing.recorder.MainActivity}: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
                      at android.app.ActivityThread.-wrap12(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6077)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
                   Caused by: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
                      at com.glgjing.recorder.MainActivity.onRequestPermissionsResult(MainActivity.java:87)
                      at android.app.Activity.requestPermissions(Activity.java:4116)
                      at android.support.v4.app.ActivityCompatApi23.requestPermissions(ActivityCompat23.java:32)
                      at android.support.v4.app.ActivityCompat.requestPermissions(ActivityCompat.java:316)
                      at com.glgjing.recorder.MainActivity.onCreate(MainActivity.java:59)
                      at android.app.Activity.performCreate(Activity.java:6664)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
                      at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6077) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

stop error

java.lang.RuntimeException: stop failed.
at android.media.MediaRecorder.stop(Native Method)
the saved mp4 can not play.

能不能不唤醒activity

我想将这个功能做到悬浮窗中,但是每次都会唤醒应用的activity,我猜想可能是startActivityForResult在activity中调用的缘故。但是service又无法调用startActivityForResult函数。不知道有没有方案可以在service中录屏,或者不唤醒activity?

部分机型SURFACE找不到异常

mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
报错:
setVideoSource failed
机型:华为HRY-AL00a 安卓10.0.0

minSdkVersion error

Should update minSdkVersion to 21 in ScreenRecorder/recorder/build.gradle

...
    minSdkVersion 9
...

老哥我想请教下你的强力监测app

获取应用大小,我在网上看8.0一下通过aidl 反射就可以获取到。 8.0向上需要授权检测别的应用运行情况。老哥你是怎么做啊?我看你并不需要授权这个步骤

录屏代码太复杂了 有封装好的吗

录屏代码太复杂了 有封装好的吗
直接弄3个函数
一个start录屏
一个stop录屏
一个获取录屏结果 可以保存成文件 可以变成流媒体传给服务器
求大佬看看 谢谢谢谢🙏🙏🙏🙏🙏

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.