Android螢幕截圖方式總結

CharliChen發表於2016-12-20

0、Android螢幕截圖方式:

  1. 藉助PC端工具截圖
  2. Android手機端截圖

1、藉助PC端工具截圖

PC端截圖可用的工具非常之多,從Android SDK提供的adb、ddms工具,到各大第三方助手應用寶、刷機精靈、豌豆莢等等。

工具雖多,但這些它們的實現方式基本都是一樣的,通過執行 adb shell screencap -p xxx.png 或 adb shell screenshot xxx.png 來獲取螢幕截圖。

* screencap和screenshot有什麼區別呢?

screencap是從Android 2.3開始提供的一個系統級的截圖工具,通過原始碼可以瞭解到screencap的實現方式,預設會從底層UI Surface去獲取螢幕截圖,如果失敗則從linux kernel層的display framebuffer(`/dev/graphics/fb0`)去獲取螢幕截圖。

screenshot是從Android 4.0開始提供的另一個截圖的工具, 通過原始碼可以發現screenshot則是直接讀取`/dev/graphics/fb0`去獲取螢幕的影象資料。

* 什麼是/dev/graphics/fb0

簡單來說是linux kernel 2.x開始提供的,一個螢幕資料快取的裝置,理論上凡是使用linux核心的系統都會有這樣一個東東,然後就可以通過讀取裡面的資料來獲取當前螢幕顯示的內容。需要詳細瞭解可以自行谷歌一下。

小結一下:

PC端如何截圖?

1.下載應用寶PC版等工具 
2.安裝Android SDK,使用以下命令:

  • 系統是Android 2.3以上:
  1. adb shell screencap -p xxx.png
  • 系統是Android 4.0以上:
  1. adb shell screenshot xxx.png
  • 系統是Android 2.3以下,腫麼辦?

    1.將screenshot工具從Android原始碼中摳出來,編譯為獨立的工具。然後再通過screenshot進行截圖。 
    2.使用我們沈大雄vincentshen同學開發的gsnapcap截圖工具,已適配各大廠商各種奇葩機型,解決什麼紅屏花屏不在話下,還支援影象壓縮噢。


2、Android手機端截圖

Android手機端截圖分兩種情況,有root許可權和無root許可權。

2.1 有root許可權

在系統已經root的情況下,可以通過在APP程式碼中執行`screencap -p xxx.png` 和 `screenshot xxx.png`來進行螢幕截圖。原理和上述PC端截圖是一樣的,只不過在PC端截圖,手機無需root許可權。如果在APP中執行截圖命令,則需要root許可權。

*任何在adb中可執行的命令,如果想在APP程式碼中執行,基本上都需要有root許可權。例如bugreport、logcat(>=4.1)、screenrecord(>=4.4)等。

程式碼示例:

通過screncap命令截圖

  1. Process process = null;
  2. try{
  3. process = Runtime.getRuntime().exec("su");
  4. PrintStream outputStream = null;
  5. try {
  6. outputStream = new PrintStream(new BufferedOutputStream(process.getOutputStream(), 8192));
  7. outputStream.println("screencap -p " + filePath);
  8. outputStream.flush();
  9. }catch(Exception e){
  10. Log.e(TAG, e);
  11. } finally {
  12. if (outputStream != null) {
  13. outputStream.close();
  14. }
  15. }
  16. process.waitFor();
  17. }catch(Exception e){
  18. Log.e(TAG, e);
  19. }finally {
  20. if(process != null){
  21. process.destroy();
  22. }
  23. }

通過screnshot命令截圖和上面是類似的,另外還可以通過呼叫Bugly自研的gsnapcap工具來進行截圖。

  1. chmod 777 /dev/graphics/fb0
  2. gsnapcap xxx.png /dev/graphics/fb0 1

最後一個引數為影象解析度,1為螢幕原始解析度。

2.2 無root許可權

無root許可權又分兩種:

  • 系統自帶截圖
  • APP內截圖

2.2.1 系統自帶截圖

系統自帶截圖有兩種情況:

  • 同時按住 電源鍵 和 音量下鍵 兩秒鐘
  • 同時按住 電源鍵 和 Home鍵 兩秒鐘

機型不同,系統自帶的截圖方式也不同,但基本上都是以上兩種。

2.2.2 APP內截圖

APP內截圖又分兩種:(-_-!我真的不是黑安卓,太多情況了。)

  • SurfaceView
  • GLSurfaceView

SurfaceView和GLSurfaceView有什麼不同,簡單來說普通應用使用SurfaceView截圖即可。遊戲一般都是通過OpenGL實現的,那麼則需要使用GLSurfaceView的方式進行截圖。

2.2.2.1 SurfaceView

直接上程式碼:

  1. public String takeScreenShot(Activity activity){
  2. String filePath = FileUtils.getInstance().getStorePicFile(activity);
  3. View rootView = activity.getWindow().getDecorView();
  4. rootView.setDrawingCacheEnabled(true);
  5. rootView.buildDrawingCache();
  6. Bitmap bitmap = rootView.getDrawingCache();
  7. File imagePath = new File(filePath);
  8. FileOutputStream fos = null;
  9. try {
  10. fos = new FileOutputStream(imagePath);
  11. bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
  12. fos.flush();
  13. } catch (Exception e) {
  14. }finally {
  15. try{
  16. fos.close();
  17. bitmap.recycle();
  18. bitmap = null;
  19. }catch(Exception e){
  20. }
  21. rootView.destroyDrawingCache();
  22. rootView.setDrawingCacheEnabled(false);
  23. }
  24. return filePath;
  25. }

takeScreenShot的引數必須為Activity類或其子類,不能是Context,這段程式碼是通過獲取Activity的根節點view,並將其DrawingCache儲存為圖片,從而實現對該介面的截圖。這個方法只能對APP自身的介面有效,出了APP就沒有辦法了。


相關文章