標籤:
首先要說明的是並未實現,本文講一下自己的思路。
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 參數,可見錄屏結束後會發送一個廣播,用於告訴系統有新檔案產生了:
[email protected]:/sdcard $ screenrecord --verbose --time-limit 10 /sdcard/1.mp4Main display is 720x1280 @59.00fps (orientation=0)Configuring recorder for 720x1280 video/avc at 4.00MbpsContent area is 720x1280 at offset x=0 y=0Time limit reachedEncoder stopping; recorded 6 frames in 10 secondsStopping encoder and muxerExecuting: /system/bin/am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/1.mp4Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///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 reachedEncoder stopping; recorded 0 frames in 3 secondsStopping 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 的時候一直返回錯誤,不停的重複嘗試,直到結束也沒成功錄屏一幀。
這就不知道什麼原因了,還得去看代碼。
先丟這裡,望明白的大神指點。
android 調用 screenrecord 實現錄屏