Android截圖機制淺析
的除錯工具DDMS提供截圖功能,很多同步軟體例如豌豆莢也都提供截圖功能,經分析Android截圖原理大致如下:
DDMS是通過adb呼叫裝置端的adbd(ADBdaemon)提供的framebufferservice進行截圖(原始碼在system/core/adb/framebuffer_service.c),在較早版本的Android中,framebuffer service通過直接讀framebuffer 裝置(/dev/graphics/fb0)來截圖,在較新版本的Android中,framebuffer service則呼叫截圖工具screencap來截圖。那些同步軟體也是呼叫screencap實現截圖
screencap是Android原生自帶的工具,是一個C寫的可執行檔案,在裝置上的/system/bin/下面可以找到它,screencap截圖後可儲存為PNG格式檔案或RGBRAW檔案。
screencap的原始碼在frameworks/base/cmds/screencap/,它呼叫SurfaceFlinger提供的截圖介面ScreenshotClient,其原始碼在frameworks/native/libs/gui/SurfaceComposerClient.cpp(該路徑在不同版本的Android原始碼中可能略有差別),ScreenshotClient通過程序間通訊呼叫SurfaceFlinger service的截圖
在各種截圖方法中,讀framebuffer裝置(/dev/graphics/fb0)的方式在某些使用硬體overlay顯示的裝置上可能無法擷取到某些畫面(例如video playback和camera preview畫面),但是SurfaceFlinger提供的上述截圖介面則可以完美擷取任何螢幕畫面,因此相對來說是Android上最正規最完善的截圖方法,使用起來也非常簡單。但需注意,ScreenshotClient等介面在不同Android
此外Android還自帶另一個截圖工具screenshot,原始碼在frameworks/base/cmds/screenshot/,它通過直接讀framebuffer 裝置(/dev/graphics/fb0)來截圖,儲存為PNG格式檔案。screenshot貌似沒有用處。
原文二:(用自己的方式實現截圖)
import Java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
public class ScreenShot {
// 獲取指定Activity的截圖,儲存到png檔案
private static Bitmap takeScreenShot(Activity activity) {
// View是你需要截圖的View
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
// 獲取狀態列高度
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
Log.i("TAG", "" + statusBarHeight);
// 獲取螢幕長和高
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay()
.getHeight();
// 去掉標題欄
// Bitmap b = Bitmap.createBitmap(b1, 0, 25, 320, 455);
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return b;
}
// 儲存到sdcard
private static void savePic(Bitmap b, String strFileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strFileName);
if (null != fos) {
b.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 程式入口
public static void shoot(Activity a) {
ScreenShot.savePic(ScreenShot.takeScreenShot(a), "sdcard/xx.png");
}
}
需要注意的是,shoot方法只能在view已經被載入後方可呼叫。
或者在 @Override
public void onWindowFocusChanged(boolean hasFocus) {
// TODO Auto-generated method stub
super.onWindowFocusChanged(hasFocus);
ScreenShot.shoot(this);
}中呼叫
原文三:
淺談android截圖問題
連結:http://my.oschina.net/JumpLong/blog/75556做了幾個月的截圖開發,稍微瞭解了一下這方面的知識,於是拿來分享一下,也許對你有一些幫助吧。
我是基於android2.3.3系統之上的,想必大家應該知道在android原始碼下面有個檔案叫做screencap吧,位於frameworks\base\services\surfaceflinger\tests\screencap\screencap.cpp,你直接在linux下編譯(就是去screencap的檔案mm,然後儲存在 /system/bin/test-screencap),然後push到手機上再通過電腦去敲命令./test-screencap /mnt/sdcard/scapxx.png就可以實現截圖(不要匯入到/mntsdcard,反正我是匯入到system目錄裡面才可以執行)。
- /*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <utils/Log.h>
- #include <binder/IPCThreadState.h>
- #include <binder/ProcessState.h>
- #include <binder/IServiceManager.h>
- #include <binder/IMemory.h>
- #include <surfaceflinger/ISurfaceComposer.h>
- #include <SkImageEncoder.h>
- #include <SkBitmap.h>
- usingnamespace android;
- int main(int argc, char** argv)
- {
- if (argc != 2) {
- printf("usage: %s path\n", argv[0]);
- exit(0);
- }
- const String16 name("SurfaceFlinger");
- sp<ISurfaceComposer> composer;
- getService(name, &composer);
- sp<IMemoryHeap> heap;
- uint32_t w, h;
- PixelFormat f;
- status_t err = composer->captureScreen(0, &heap, &w, &h, &f, 0, 0);
- if (err != NO_ERROR) {
- fprintf(stderr, "screen capture failed: %s\n", strerror(-err));
- exit(0);
- }
- printf("screen capture success: w=%u, h=%u, pixels=%p\n",
- w, h, heap->getBase());
- printf("saving file as PNG in %s ...\n", argv[1]);
- SkBitmap b;
- b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
- b.setPixels(heap->getBase());
- SkImageEncoder::EncodeFile(argv[1], b,
- SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
- return 0;
- }
其實這個程式真正用到的就是一個叫做capturescreen的函式,而capturescreen會呼叫captureScreenImplLocked這個函式
下面是程式碼:
- status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
- sp<IMemoryHeap>* heap,
- uint32_t* w, uint32_t* h, PixelFormat* f,
- uint32_t sw, uint32_t sh)
- {
- LOGI("captureScreenImplLocked");
- status_t result = PERMISSION_DENIED;
- // only one display supported for now
- if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
- return BAD_VALUE;
- if (!GLExtensions::getInstance().haveFramebufferObject())
- return INVALID_OPERATION;
- // get screen geometry
- const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
- const uint32_t hw_w = hw.getWidth();
- const uint32_t hw_h = hw.getHeight();
- if ((sw > hw_w) || (sh > hw_h))
- return BAD_VALUE;
- sw = (!sw) ? hw_w : sw;
- sh = (!sh) ? hw_h : sh;
- constsize_t size = sw * sh * 4;
- // make sure to clear all GL error flags
- while ( glGetError() != GL_NO_ERROR ) ;
- // create a FBO
- GLuint name, tname;
- glGenRenderbuffersOES(1, &tname);
- glBindRenderbufferOES(GL_RENDERBUFFER_OES, tname);
- glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_RGBA8_OES, sw, sh);
- glGenFramebuffersOES(1, &name);
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
- glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES,
- GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
- GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
- if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
- // invert everything, b/c glReadPixel() below will invert the FB
- glViewport(0, 0, sw, sh);
- glScissor(0, 0, sw, sh);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrthof(0, hw_w, 0, hw_h, 0, 1);
- glMatrixMode(GL_MODELVIEW);
- // redraw the screen entirely...
- glClearColor(0,0,0,1);
- glClear(GL_COLOR_BUFFER_BIT);
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- constsize_t count = layers.size();
- for (size_t i=0 ; i<count ; ++i) {
- const sp<LayerBase>& layer(layers[i]);
- layer->drawForSreenShot();
- }
- // XXX: this is needed on tegra
- glScissor(0, 0, sw, sh);
- // check for errors and return screen capture
- if (glGetError() != GL_NO_ERROR) {
- // error while rendering
- result = INVALID_OPERATION;
- } else {
- // allocate shared memory large enough to hold the
-
相關推薦
Android截圖機制淺析
的除錯工具DDMS提供截圖功能,很多同步軟體例如豌豆莢也都提供截圖功能,經分析Android截圖原理大致如下: DDMS是通過adb呼叫裝置端的adbd(ADBdaemon)提供的framebufferservice進行截圖(原始碼在system/core/adb/framebuffer_service
android截圖
//截圖 private Bitmap generateSpringCard() { View view = getWindow().getDecorView(); view.setDrawingCacheEnabled(true); view.buildDrawingCac
android截圖程式碼實現方法
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
Android 截圖
二、具體實現方式 1),第一種實現方式 /** * 對View進行量測,佈局後截圖 * * @param view * @return */ public Bitmap convertViewTo
Android截圖方案
Android截圖 Android截圖的原理:獲取具體需要截圖的區域的Bitmap,然後繪製在畫布上,儲存為圖片後進行分享或者其它用途 在截圖功能中,有時需要擷取全屏的內容,有時需要擷取超過一屏的內容(比如:Listview,Scrollview,RecyclerVi
Android 截圖(Screenshot)程式碼流程小結
一、基本介紹 在Android 4.0 之前,Android手機上如果要使用截圖功能,只能通過Root手機,且使用第3方截圖軟體來實現截圖功能。 Android4.0中,系統自帶了截圖功能,使用方法是音量下(VOLUME_DOWN
使用python編寫android截圖指令碼
測試的過程中經常需要擷取螢幕,通常的做法是使用手機自帶的截圖功能,然後將截圖檔案複製出來,這種方法的優點是不需要連線資料線就可截圖,缺點則是生成的截圖檔案命名是隨機命名的,複製出來也比較麻煩。另一種方法是使用PC端的手機助手類軟體。 這裡使用python編
Python實現對Android截圖
背景: 測試過程中,總是需要對Android裝置進行截圖,然後在截圖中標註問題描述; 手動方式: 1.使用adb scrrencap /sdcard/screen.png 命令對Android裝置進行截圖 2.然後再使用adb pull /sdcard/scrren.pn
android截圖實現
import android.app.Activity; import android.graphics.Bitmap; import android.graphics.Rect; import android.view.View; import java.io.Fi
Android 截圖到桌面的最佳處理方案-無須ROOT-適用Android 8.0
最近在做測試中發現一些重複性動作費時費力還容易出錯,百度了一圈發現竟然沒有WIN的教程,全是MAC的,既然做自動化方向,能偷懶那就當然自動化一波 準備 安卓手機一部,別是2.2以下,我的方法都支援,不需要root 安裝驅動,老生常談,有Android開
android截圖功能實現
這篇文章實現了擷取當前Activity頁面,並把截圖圖片儲存在SD卡指定路徑下功能(親測可用)。 首先要確保manifest有操作SD卡許可權 <!-- 允許應用內建sd卡 --> <uses-permission android:name="
Android截圖(fb0)
1.申請獲取root許可權,這一步很重要,不然會沒有作用 private void getPermession() { try { Process process = Ru
Android截圖儲存png圖片的例項程式碼(去掉狀態列)
今天開發中遇到了android手機截圖的需求,以下是實現程式碼: 這是截圖工具類: public class ScreenShot { // 獲取指定Activity的截圖,儲存到png檔案
快速新增簡單的Android截圖分享
基於cocos2d-x開發(我的是V2.2.3),分享的方法有很多,例如用SharedSDK,或者直接用各個開發平臺的SDK,但對於android平臺,如果要求不是很高的話,有一種簡單的方式(Intent元件+jni)。 1.假如工程名是LC
Android截圖命令screencap與視訊錄製命令screenrecord
檢視幫助命令[email protected] ~$ adb shell screencap -v screencap: invalid option -- v usage: screencap [-hp] [-d display-id] [FILENAME] -h: this mes
Android截圖如何生成gif動態圖
我們在部落格裡面經常看到有人上傳的截圖是動態的,即gif格式,那麼截圖怎麼生成gif格式的圖片呢? 所需工具 ①視訊截圖工具:用Android Studio開發Android的人,應該都知道,And
Android截圖截圖的幾種方法總結
Android截圖 Android截圖的原理:獲取具體需要截圖的區域的Bitmap,然後繪製在畫布上,儲存為圖片後進行分享或者其它用途 一、Activity截圖 1、截Activity介面(包含空白的狀態列) ? 1 2 3 4
android截圖快捷鍵 截圖工具 音量下鍵+電源鍵
一般來說android手機或者平板,只要用兩個手指同時按下:音量下鍵+電源鍵,一秒鐘即可截圖,截圖圖片儲存到了/sdcard/Pictures/Screenshots資料夾下面。這個方法在nexus s、小米1原生android 4.0和nexus 7裡面都是確切可用的,其他
Android截圖、儲存、分享
原理:將擷取到的Bitmap賦給Dialog上的ImageView,並對Dialog加了彈出和收起的動畫,實現截圖效果。 首先建立一個layout名為show_cut_screen_layout用於彈出截圖對話方塊,上面是一個image,下面是橫向線性佈局的兩個button
Android截圖事件監聽
1. 前言 Android系統沒有直接對截圖事件監聽的介面,也沒有廣播,只能自己動手來豐衣足食,一般有三種方法。 利用FileObserver監聽某個目錄中資源變化情況 利用ContentObserver監聽全部資源的變化 監聽截圖快捷按鍵 由