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

 
相關文章
相關標籤/搜索