Android 實現截屏方式整理linux
可能的需求:android
截本身的屏
截全部的屏
帶導航欄截屏
不帶導航欄截屏
截屏並編輯選取一部分
自動截取某個空間或者佈局
截取長圖
在後臺去截屏
1.只截取本身應用內部界面
1.1 截取除了導航欄以外的屏幕
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) {
}
}
1.2 截取某個控件或者區域
兩種方案:shell
跟上面差很少,只不過view不適用根view,而是使用某個某個控件。
View dView = title;
dView.setDrawingCacheEnabled(true);
dView.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(dView.getDrawingCache());
手動draw
View dView = titleTv;
Bitmap bitmap = Bitmap.createBitmap(dView.getWidth(), dView.getHeight(), Bitmap.Config.ARGB_8888);
//使用Canvas,調用自定義view控件的onDraw方法,繪製圖片
Canvas canvas = new Canvas(bitmap);
dView.draw(canvas);
1.3 截取帶導航欄的整個屏幕
這一小節會將一些理論上能夠,可是實踐會特別複雜,不太推薦使用。能夠學習瞭解。編程
adb 命令canvas
這裏指的不是鏈接電腦進行adb操控,而是在App內部實現adb命令的操控緩存
在APK中調用「adb shell screencap -pfilepath」 命令框架
該命令讀取系統的framebuffer,須要得到系統權限:佈局
(1). 在AndroidManifest.xml文件中添加學習
<uses-permissionandroid:name="android.permission.READ_FRAME_BUFFER"/>測試
(2). 修改APK爲系統權限,將APK放到源碼中編譯, 修改Android.mk
LOCAL_CERTIFICATE := platform
publicvoid takeScreenShot(){
String mSavedPath = Environment.getExternalStorageDirectory()+File. separator + "screenshot.png" ;
try {
Runtime. getRuntime().exec("screencap -p " + mSavedPath);
} catch (Exception e) {
e.printStackTrace();
}
利用系統的隱藏API,實現Screenshot,這部分代碼是系統隱藏的,須要在源碼下編譯。
1).修改Android.mk, 添加系統權限
LOCAL_CERTIFICATE := platform
2).修改AndroidManifest.xml 文件,添加權限
<uses-permissionandroid:name="android.permission.READ_FRAME_BUFFER"/>
public boolean takeScreenShot(String imagePath){
if(imagePath.equals("" )){
imagePath = Environment.getExternalStorageDirectory()+File. separator+"Screenshot.png" ;
}
Bitmap mScreenBitmap;
WindowManager mWindowManager;
DisplayMetrics mDisplayMetrics;
Display mDisplay;
mWindowManager = (WindowManager) mcontext.getSystemService(Context.WINDOW_SERVICE);
mDisplay = mWindowManager.getDefaultDisplay();
mDisplayMetrics = new DisplayMetrics();
mDisplay.getRealMetrics(mDisplayMetrics);
float[] dims = {mDisplayMetrics.widthPixels , mDisplayMetrics.heightPixels };
mScreenBitmap = Surface. screenshot((int) dims[0], ( int) dims[1]);
if (mScreenBitmap == null) {
return false ;
}
try {
FileOutputStream out = new FileOutputStream(imagePath);
mScreenBitmap.compress(Bitmap.CompressFormat. PNG, 100, out);
} catch (Exception e) {
return false ;
}
return true ;
}
Android本地編程(Native Programming)讀取framebuffer
命令行,框架的截屏功能是經過framebuffer來實現的,因此咱們先來介紹一下framebuffer。
framebuffer介紹
幀緩衝(framebuffer)是Linux爲顯示設備提供的一個接口,把顯存抽象後的一種設備,他容許上層應用程序在圖形模式下直接對顯示緩衝區進行 讀寫操做。這種操做是抽象的,統一的。用戶沒必要關心物理顯存的位置、換頁機制等等具體細節。這些都是由Framebuffer設備驅動來完成的。
linux FrameBuffer 本質上只是提供了對圖形設備的硬件抽象,在開發者看來,FrameBuffer 是一塊顯示緩存,往顯示緩存中寫入特定格式的數據就意味着向屏幕輸出內容。因此說FrameBuffer就是一塊白板。例如對於初始化爲16 位色的FrameBuffer 來講, FrameBuffer中的兩個字節表明屏幕上一個點,從上到下,從左至右,屏幕位置與內存地址是順序的線性關係。
幀緩存有個地址,是在內存裏。咱們經過不停的向frame buffer中寫入數據, 顯示控制器就自動的從frame buffer中取數據並顯示出來。所有的圖形都共享內存中同一個幀緩存。
android截屏實現思路Android系統是基於Linux內核的,因此也存在framebuffer這個設備,咱們要實現截屏的話只要能獲取到framebuffer中的數據,而後把數據轉換成圖片就能夠了,android中的framebuffer數據是存放在 /dev/graphics/fb0 文件中的,因此咱們只須要來獲取這個文件的數據就能夠獲得當前屏幕的內容。如今咱們的測試代碼運行時候是經過RC(remote controller)方式來運行被測應用的,那就須要在PC機上來訪問模擬器或者真機上的framebuffer數據,這個的話能夠經過android的ADB命令來實現。