android 调用 screenrecord 实现录屏

首先要说明的是并未实现,本文讲一下本身的思路。html

 

adb 使用shell 命令 screenrecord 可录屏。
本身写了个app,经过Process p = Runtime.getRuntime().exec(cmd)的方式调用shell命令,报错:
java.lang.SecurityException: Permission Denial: broadcast asks to run as user -2 but is calling from user 0

须要android.permission.INTERACT_ACROSS_USERS_FULL 或者 android.permission.INTERACT_ACROSS_USERS 权限,而这个权限是system app的权限,第三方app是没有权限申请的。java

因此说4.4的录屏是须要root权限的。5.0 以后的 MediaProjection API, 不须要 root权限(which allows ordinary, unprivileged applications to record the screen)。
 
使用 verbose 参数,可见录屏结束后会发送一个广播,用于告诉系统有新文件产生了:
shell@aries:/sdcard $ screenrecord --verbose --time-limit 10 /sdcard/1.mp4
Main display is 720x1280 @59.00fps (orientation=0)
Configuring recorder for 720x1280 video/avc at 4.00Mbps
Content area is 720x1280 at offset x=0 y=0
Time limit reached
Encoder stopping; recorded 6 frames in 10 seconds
Stopping encoder and muxer
Executing: /system/bin/am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_
FILE -d file:///sdcard/1.mp4
Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=fil
e:///sdcard/1.mp4 }
Broadcast completed: result=0

既然如此看一下screenrecord源码吧。android

frameworks\av\cmds\screenrecord\screenrecord.cpp
*
* Sends a broadcast to the media scanner to tell it about the new video.
*
* This is optional, but nice to have.
*/
static status_t notifyMediaScanner(const char* fileName)
果真有这样一个函数,而后在 main 函数的末尾调用了此函数:
if (err == NO_ERROR) {
    // Try to notify the media scanner. Not fatal if this fails.
    notifyMediaScanner(fileName);
}

 

那么,若是注释掉 notifyMediaScanner(fileName); 这一行,从新编译出来的 screenrecord 可执行程序在录屏时就不会发广播了,是否是就不用 root 权限了呢?
通过测试,是能够的。shell

修改源码,从新编译framework(其实我是编译整个源码,单独编译 framework 并未生成 screenrecord 可执行文件),而后替换掉system/bin/下的 screenrecord(这个操做是须要 root 权限的,因此本文仅仅是为了研究,并不能达到免 root 使用screenrecord 录屏。固然本身作 ROM 的话能够直接把改过的 screenrecord 打包进去),而后确实能够不用root权限执行。可是录屏结果是空文件(大小为0 kb),debug 信息以下:
……
Time limit reached
Encoder stopping; recorded 0 frames in 3 seconds
Stopping encoder and muxer
……
 
继续查看 screenrecord.cpp ,取消 
#define LOG_NDEBUG 0
这一行的注释,即打开 ALOGV 的开关,从新编译,替换手机中的 screenrecord ,app 再次调用 screenrecord 命令,日志以下:

C:\Users\wy>adb logcat | findstr /I "ScreenRecord"
10-17 10:36:17.435 9839 9839 V ScreenRecord: Creating codec
10-17 10:36:17.531 9839 9839 V ScreenRecord: Creating encoder input surface
10-17 10:36:17.533 9839 9839 V ScreenRecord: Starting codec
10-17 10:36:17.618 9839 9839 V ScreenRecord: Codec prepared
10-17 10:36:17.623 9839 9839 V ScreenRecord: Calling dequeueOutputBuffer
10-17 10:36:17.873 9839 9839 V ScreenRecord: dequeueOutputBuffer returned -11
10-17 10:36:17.873 9839 9839 V ScreenRecord: Got -EAGAIN, looping
10-17 10:36:17.873 9839 9839 V ScreenRecord: Calling dequeueOutputBuffer
10-17 10:36:18.124 9839 9839 V ScreenRecord: dequeueOutputBuffer returned -11
10-17 10:36:18.124 9839 9839 V ScreenRecord: Got -EAGAIN, looping
10-17 10:36:18.124 9839 9839 V ScreenRecord: Calling dequeueOutputBufferapp

 

日志显示,在输出 buffer 的时候一直返回错误,不停的重复尝试,直到结束也没成功录屏一帧。ide

这就不知道什么缘由了,还得去看代码。函数

先丢这里,望明白的大神指点。oop

 
相关文章
相关标签/搜索