天天看點

安卓截屏初體驗

工作需要,需要背景服務去定時截取前台顯示app的畫面。百度一下,網上很多例程,以為很簡單,然并卵,一路踩坑。。。

踩坑一:使用View.getDrawingCache()方法

View dView = getWindow().getDecorView();
dView.setDrawingCacheEnabled(true);
dView.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(dView.getDrawingCache());
if (bitmap != null) {
  try {
    // 擷取内置SD卡路徑
    String sdCardPath = Environment.getExternalStorageDirectory().getPath();
    // 圖檔檔案路徑
    String filePath = sdCardPath + File.separator + "screenshot.png";
    File file = new File(filePath);
    FileOutputStream os = new FileOutputStream(file);
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
    os.flush();
    os.close();
    DebugLog.d("a7888", "存儲完成");
  } catch (Exception e) {
  }
}
           

寫了個demo,可以截屏,興沖沖的以為搞定了,內建的時候才發現,這個隻能抓取本應用的畫面,失敗。不過也算是學到了,通過該方法可以截取本應用的畫面,或者截取指定控件的畫面。

踩坑二:使用screencap -p指令

publicvoid takeScreenShot(){ 
  String mSavedPath = Environment.getExternalStorageDirectory()+File. separator + "screenshot.png" ; 
try {           
      Runtime. getRuntime().exec("screencap -p " + mSavedPath); 
  } catch (Exception e) { 
      e.printStackTrace(); 
  }
           

代碼很簡單,有兩個注意點,一是權限,

(1). 在AndroidManifest.xml檔案中添加

<uses-permissionandroid:name="android.permission.READ_FRAME_BUFFER"/>
           

(2). 修改APK為系統權限,将APK放到源碼中編譯, 修改Android.mk

LOCAL_CERTIFICATE := platform
           

寫了個demo,可以截屏,興沖沖的以為搞定了,結果又是想多了,截圖的時間太長了,全屏截圖一次需要1s+,還要再想辦法。

第二點是指令中如果有一些特殊字元會導緻指令運作失敗,如“|”、“>>”等,需要使用以下接口:

Runtime.getRuntime().exec( new String[]{"/bin/sh","-c",cmd},null);
           

踩坑三:通過反射使用隐藏接口android.view.SurfaceControl.screenshot

try {
            DisplayMetrics mDisplayMetrics = new DisplayMetrics();
            float[] dims = { mDisplayMetrics.widthPixels,mDisplayMetrics.heightPixels };
            Class<?> demo = null;
            demo = Class.forName("android.view.SurfaceControl");
            Method method=demo.getMethod("screenshot",new Class[]{Rect.class,int.class,int.class,int.class});
            Bitmap mScreenBitmap = (Bitmap) method.invoke(null,new Rect(),(int) dims[0],(int) dims[1],0);
            mScreenBitmap.recycle();
        } catch (Exception e) {
            e.printStackTrace();
        }
           

(1). 在AndroidManifest.xml檔案中添加

<uses-permissionandroid:name="android.permission.READ_FRAME_BUFFER"/>
           

(2). 修改APK為系統權限,将APK放到源碼中編譯, 修改Android.mk

LOCAL_CERTIFICATE := platform
           

同樣要添權重限。同樣一堆坑需要注意,一通過調用SurfaceControl.screenshot() / Surface.screenshot() 截屏,在 API Level 大于 17 使用 SurfaceControl ,小于等于 17 使用 Surface。二"screenshot"還是的參數不同版本不同,當系統提示找不到這個函數的時候,去系統中找下這個檔案,看下這個版本的是什麼接口,檔案路徑/frameworks/base/core/java/android/view/SurfaceControl.java。

寫了個demo,可以截屏,幀率也可以,終于搞定了‘——’