工作需要,需要背景服務去定時截取前台顯示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,可以截屏,幀率也可以,終于搞定了‘——’