android 調用 screenrecord 實現錄屏


首先要說明的是並未實現,本文講一下自己的思路。

 

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是沒有權限申請的。

所以說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源碼吧。

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 權限了呢?
經過測試,是可以的。

修改源碼,重新編譯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 dequeueOutputBuffer

 

日志顯示,在輸出 buffer 的時候一直返回錯誤,不停的重復嘗試,直到結束也沒成功錄屏一幀。

這就不知道什么原因了,還得去看代碼。

先丟這里,望明白的大神指點。


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM