Android中使用程式碼截圖的各種方法總結
1,基於Android SDK的截圖方法
(1)主要就是利用SDK提供的View.getDrawingCache()方法。網上已經有很多的例項了。首先建立一個android project,然後進行Layout,畫一個按鍵(res/layout/main.xml):
<? xml version = "1.0" encoding = "utf-8" ?> android:orientation = "vertical" android:layout_width = "fill_parent" android:layout_height = "fill_parent" > < TextView android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:text = "@string/hello" /> < Button android:text = "NiceButton" android:id = "@+id/my_button" android:layout_width = "fill_parent" android:layout_height = "wrap_content" android:layout_alignParentBottom = "true" ></ Button > </ LinearLayout > |
HelloAndroid.java實現程式碼為:
package com.example.helloandroid; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class HelloAndroid extends Activity
{ private Button
button; /**
Called when the activity is first created. */ @Override public void onCreate(Bundle
savedInstanceState) { super .onCreate(savedInstanceState); this .setContentView(R.layout.main); this .button
= (Button) this .findViewById(R.id.my_button); this .button.setOnClickListener( new OnClickListener()
{ public void onClick(View
v) { SimpleDateFormat
sdf = new SimpleDateFormat( "yyyy-MM-dd_HH-mm-ss" ,
Locale.US); String
fname = "/sdcard/" +
sdf.format( new Date())
+ ".png" ; View
view = v.getRootView(); view.setDrawingCacheEnabled( true ); view.buildDrawingCache(); Bitmap
bitmap = view.getDrawingCache(); if (bitmap
!= null )
{ System.out.println( "bitmap
got!" ); try { FileOutputStream
out = new FileOutputStream(fname); bitmap.compress(Bitmap.CompressFormat.PNG, 100 ,
out); System.out.println( "file
"
+ fname + "output
done." ); } catch (Exception
e) { e.printStackTrace(); } } else { System.out.println( "bitmap
is NULL!" ); } } }); } } |
這個程式碼會在按下app中按鍵的時候自動在手機的/sdcard/目錄下生成一個時間戳命名的png截圖檔案。
這種截圖有一個問題,就是隻能截到一部分,比如電池指示部分就截不出來了。
(2)在APK中呼叫“adb shell screencap -pfilepath” 命令
(1). 在AndroidManifest.xml檔案中新增<uses-permissionandroid:name="android.permission.READ_FRAME_BUFFER"/>(2). 修改APK為系統許可權,將APK放到原始碼中編譯, 修改Android.mkLOCAL_CERTIFICATE := platform
publicvoid takeScreenShot(){
String mSavedPath = Environment.getExternalStorageDirectory()+File. separator + "screenshot.png" ;
try {
Runtime. getRuntime().exec("screencap -p " + mSavedPath);
} catch (Exception e) {
e.printStackTrace();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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 ; }
|
2 基於Android ddmlib進行截圖
- public class ScreenShot {
- private BufferedImage image = null;
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- AndroidDebugBridge.init(false); //
- ScreenShot screenshot = new ScreenShot();
- IDevice device = screenshot.getDevice();
- for (int i = 0; i < 10; i++) {
- Date date=new Date();
- SimpleDateFormat df=new SimpleDateFormat("MM-dd-HH-mm-ss");
- String nowTime = df.format(date);
- screenshot.getScreenShot(device, "Robotium" + nowTime);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- public void getScreenShot(IDevice device,String filename) {
- RawImage rawScreen = null;
- try {
- rawScreen = device.getScreenshot();
- } catch (TimeoutException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (AdbCommandRejectedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- if (rawScreen != null) {
- Boolean landscape = false;
- int width2 = landscape ? rawScreen.height : rawScreen.width;
- int height2 = landscape ? rawScreen.width : rawScreen.height;
- if (image == null) {
- image = new BufferedImage(width2, height2,
- BufferedImage.TYPE_INT_RGB);
- } else {
- if (image.getHeight() != height2 || image.getWidth() != width2) {
- image = new BufferedImage(width2, height2,
- BufferedImage.TYPE_INT_RGB);
- }
- }
- int index = 0;
- int indexInc = rawScreen.bpp >> 3;
- for (int y = 0; y < rawScreen.height; y++) {
- for (int x = 0; x < rawScreen.width; x++, index += indexInc) {
- int value = rawScreen.getARGB(index);
- if (landscape)
- image.setRGB(y, rawScreen.width - x - 1, value);
- else
- image.setRGB(x, y, value);
- }
- }
- try {
- ImageIO.write((RenderedImage) image, "PNG", new File("D:/"
- + filename + ".jpg"));
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- /**
- * 獲取得到device物件
- * @return
- */
- private IDevice getDevice(){
- IDevice device;
- AndroidDebugBridge bridge = AndroidDebugBridge
- .createBridge("adb", true);//如果程式碼有問題請檢視API,修改此處的引數值試一下
- waitDevicesList(bridge);
- IDevice devices[] = bridge.getDevices();
- device = devices[0];
- return device;
- }
- /**
- * 等待查詢device
- * @param bridge
- */
- private void waitDevicesList(AndroidDebugBridge bridge) {
- int count = 0;
- while (bridge.hasInitialDeviceList() == false) {
- try {
- Thread.sleep(500);
- count++;
- } catch (InterruptedException e) {
- }
- if (count > 240) {
- System.err.print("等待獲取裝置超時");
- break;
- }
- }
- }
3 Android本地程式設計(Native Programming)讀取framebuffer
(1)命令列,框架的截圖功能是通過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命令來實現。
/***********************************************************************
*
* ScreenShot.java
***********************************************************************/
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.imageio.ImageIO;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.internal.Base64Encoder;
import com.google.common.io.Closeables;
import com.google.common.io.LittleEndianDataInputStream;
/**
*/
public class ScreenShot {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
try {
//解析度大小,後續可以通過程式碼來獲取到當前的解析度
int xResolution = 320;
int yResolution = 480;
//執行adb命令,把framebuffer中內容儲存到fb1檔案中
Runtime.getRuntime().exec("adb pull /dev/graphics/fb0 C:/fb1");
//等待幾秒保證framebuffer中的資料都被儲存下來,如果沒有儲存完成進行讀取操作會有IO異常
Thread.sleep(15000);
//讀取檔案中的資料
InputStream in = (InputStream)new FileInputStream("C:/fb1");
DataInput frameBuffer = new LittleEndianDataInputStream(in);
BufferedImage screenImage = new BufferedImage(
xResolution, yResolution, BufferedImage.TYPE_INT_ARGB);
int[] oneLine = new int[xResolution];
for (int y = 0; y < yResolution; y++) {
//從frameBuffer中計算出rgb值
convertToRgba32(frameBuffer, oneLine);
//把rgb值設定到image物件中
screenImage.setRGB(0, y, xResolution, 1, oneLine, 0, xResolution);
}
Closeables.closeQuietly(in);
ByteArrayOutputStream rawPngStream = new ByteArrayOutputStream();
try {
if (!ImageIO.write(screenImage, "png", rawPngStream)) {
throw new RuntimeException(
"This Java environment does not support converting to PNG.");
}
} catch (IOException exception) {
// This should never happen because rawPngStream is an in-memory stream.
System.out.println("IOException=" + exception);
}
byte[] rawPngBytes = rawPngStream.toByteArray();
String base64Png = new Base64Encoder().encode(rawPngBytes);
File screenshot = OutputType.FILE.convertFromBase64Png(base64Png);
System.out.println("screenshot==" + screenshot.toString());
screenshot.renameTo(new File("C:\\screenshottemp.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e);
}
}
public static void convertToRgba32(DataInput frameBuffer, int[] into) {
try {
for (int x = 0; x < into.length; x++) {
try{
int rgb = frameBuffer.readShort() & 0xffff;
int red = rgb >> 11;
red = (red << 3) | (red >> 2);
int green = (rgb >> 5) & 63;
green = (green << 2) | (green >> 4);
int blue = rgb & 31;
blue = (blue << 3) | (blue >> 2);
into[x] = 0xff000000 | (red << 16) | (green << 8) | blue;
}catch (EOFException e){
System.out.println("EOFException=" + e);
}
}
} catch (IOException exception) {
System.out.println("convertToRgba32Exception=" + exception);
}
}
}
(2)
- 首先是直接移植SystemUI的程式碼,實現截圖效果,這部分的程式碼就不貼出來了,直接去下載程式碼吧, 關鍵的程式碼沒有幾句,最最主要的是:Surface.screenshot(),請看程式碼吧。
- [java]
- <SPAN style="FONT-SIZE: 16px">package org.winplus.ss;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Matrix;
- import android.os.Bundle;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.Display;
- import android.view.Surface;
- import android.view.WindowManager;
- import android.os.SystemProperties;
- public class SimpleScreenshotActivity extends Activity {
- private Display mDisplay;
- private WindowManager mWindowManager;
- private DisplayMetrics mDisplayMetrics;
- private Bitmap mScreenBitmap;
- private Matrix mDisplayMatrix;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- new Thread(new Runnable() {
- @Override
- public void run() {
- takeScreenshot();
- }
- }).start();
- }
- private float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90:
- return 360f - 90f;
- case Surface.ROTATION_180:
- return 360f - 180f;
- case Surface.ROTATION_270:
- return 360f - 270f;
- }
- return 0f;
- }
- private void takeScreenshot() {
- mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- mDisplay = mWindowManager.getDefaultDisplay();
- mDisplayMetrics = new DisplayMetrics();
- mDisplay.getRealMetrics(mDisplayMetrics);
- mDisplayMatrix = new Matrix();
- float[] dims = { mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels };
- int value = mDisplay.getRotation();
- String hwRotation = SystemProperties.get("ro.sf.hwrotation", "0");
- if (hwRotation.equals("270") || hwRotation.equals("90")) {
- value = (value + 3) % 4;
- }
- float degrees = getDegreesForRotation(value);
- boolean requiresRotation = (degrees > 0);
- if (requiresRotation) {
- // Get the dimensions of the device in its native orientation
- mDisplayMatrix.reset();
- mDisplayMatrix.preRotate(-degrees);
- mDisplayMatrix.mapPoints(dims);
- dims[0] = Math.abs(dims[0]);
- dims[1] = Math.abs(dims[1]);
- }
- mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
- if (requiresRotation) {
- // Rotate the screenshot to the current orientation
- Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(ss);
- c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
- c.rotate(degrees);
- c.translate(-dims[0] / 2, -dims[1] / 2);
- c.drawBitmap(mScreenBitmap, 0, 0, null);
- c.setBitmap(null);
- mScreenBitmap = ss;
- }
- // If we couldn't take the screenshot, notify the user
- if (mScreenBitmap == null) {
- return;
- }
- // Optimizations
- mScreenBitmap.setHasAlpha(false);
- mScreenBitmap.prepareToDraw();
- try {
- saveBitmap(mScreenBitmap);
- } catch (IOException e) {
- System.out.println(e.getMessage());
- }
- }
- public void saveBitmap(Bitmap bitmap) throws IOException {
- String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")
- .format(new Date(System.currentTimeMillis()));
- File file = new File("/mnt/sdcard/Pictures/"+imageDate+".png");
- if(!file.exists()){
- file.createNewFile();
- }
- FileOutputStream out;
- try {
- out = new FileOutputStream(file);
- if (bitmap.compress(Bitmap.CompressFormat.PNG, 70, out)) {
- out.flush();
- out.close();
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- </SPAN>
- package org.winplus.ss;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import android.app.Activity;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Matrix;
- import android.os.Bundle;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.Display;
- import android.view.Surface;
- import android.view.WindowManager;
- import android.os.SystemProperties;
- public class SimpleScreenshotActivity extends Activity {
- private Display mDisplay;
- private WindowManager mWindowManager;
- private DisplayMetrics mDisplayMetrics;
- private Bitmap mScreenBitmap;
- private Matrix mDisplayMatrix;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- new Thread(new Runnable() {
- @Override
- public void run() {
- takeScreenshot();
- }
- }).start();
- }
- private float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90:
- return 360f - 90f;
- case Surface.ROTATION_180:
- return 360f - 180f;
- case Surface.ROTATION_270:
- return 360f - 270f;
- }
- return 0f;
- }
- private void takeScreenshot() {
- mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- mDisplay = mWindowManager.getDefaultDisplay();
- mDisplayMetrics = new DisplayMetrics();
- mDisplay.getRealMetrics(mDisplayMetrics);
- mDisplayMatrix = new Matrix();
- float[] dims = { mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels };
- int value = mDisplay.getRotation();
- String hwRotation = SystemProperties.get("ro.sf.hwrotation", "0");
- if (hwRotation.equals("270") || hwRotation.equals("90")) {
- value = (value + 3) % 4;
- }
- float degrees = getDegreesForRotation(value);
- boolean requiresRotation = (degrees > 0);
- if (requiresRotation) {
- // Get the dimensions of the device in its native orientation
- mDisplayMatrix.reset();
- mDisplayMatrix.preRotate(-degrees);
- mDisplayMatrix.mapPoints(dims);
- dims[0] = Math.abs(dims[0]);
- dims[1] = Math.abs(dims[1]);
- }
- mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
- if (requiresRotation) {
- // Rotate the screenshot to the current orientation
- Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(ss);
- c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
- c.rotate(degrees);
- c.translate(-dims[0] / 2, -dims[1] / 2);
- c.drawBitmap(mScreenBitmap, 0, 0, null);
- c.setBitmap(null);
- mScreenBitmap = ss;
- }
- // If we couldn't take the screenshot, notify the user
- if (mScreenBitmap == null) {
- return;
- }
- // Optimizations
- mScreenBitmap.setHasAlpha(false);
- mScreenBitmap.prepareToDraw();
- try {
- saveBitmap(mScreenBitmap);
- } catch (IOException e) {
- System.out.println(e.getMessage());
- }
- }
- public void saveBitmap(Bitmap bitmap) throws IOException {
- String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")
- .format(new Date(System.currentTimeMillis()));
- File file = new File("/mnt/sdcard/Pictures/"+imageDate+".png");
- if(!file.exists()){
- file.createNewFile();
- }
- FileOutputStream out;
- try {
- out = new FileOutputStream(file);
- if (bitmap.compress(Bitmap.CompressFormat.PNG, 70, out)) {
- out.flush();
- out.close();
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- PS:1、需要在AndroidManifest.xml中加入程式碼:android:sharedUserId="android.uid.system"
- 2、由於呼叫了@hide的API,所以編譯得時候請使用makefile編譯。或者通過在Eclipse中新增Jar檔案通過編譯。
- 3、此程式碼只在Android4.0中使用過,2.3的就沒去做測試了。
4 利用TakeScreenShotService截圖
Android手機一般都自帶有手機螢幕截圖的功能:在手機任何介面(當然手機要是開機點亮狀態),通過按組合鍵,螢幕閃一下,然後咔嚓一聲,截圖的照片會儲存到當前手機的相簿中,真是一個不錯的功能!
以我手頭的測試手機為例,是同時按電源鍵+音量下鍵來實現截圖,蘋果手機則是電源鍵 + HOME鍵,小米手機是選單鍵+音量下鍵,而HTC一般是按住電源鍵再按左下角的“主頁”鍵。那麼Android原始碼中使用組合鍵是如何實現螢幕截圖功能呢?前段時間由於工作的原因仔細看了一下,這兩天不忙,便把相關的知識點串聯起來整理一下,分下面兩部分簡單分析下實現流程:
Android原始碼中對組合鍵的捕獲。
Android原始碼中對按鍵的捕獲位於檔案PhoneWindowManager.java(alps\frameworks\base\policy\src\com\android\internal\policy\impl)中,這個類處理所有的鍵盤輸入事件,其中函式interceptKeyBeforeQueueing()會對常用的按鍵做特殊處理。以我手頭的測試機為例,是同時按電源鍵和音量下鍵來截圖,那麼在這個函式中我們會看到這麼兩段程式碼:
可以看到正是在這裡(響應Down事件)捕獲是否按了音量下鍵和電源鍵的,而且兩個地方都會進入函式interceptScreenshotChord()中,那麼接下來看看這個函式幹了什麼工作:
在這個函式中,用兩個布林變數判斷是否同時按了音量下鍵和電源鍵後,再計算兩個按鍵響應Down事件之間的時間差不超過150毫秒,也就認為是同時按了這兩個鍵後,算是真正的捕獲到螢幕截圖的組合鍵。
附言:檔案PhoneWindowManager.java類是攔截鍵盤訊息的處理類,在此類中還有對home鍵、返回鍵等好多按鍵的處理。
Android原始碼中呼叫螢幕截圖的介面。
捕獲到組合鍵後,我們再看看android原始碼中是如何呼叫螢幕截圖的函式介面。在上面的函式interceptScreenshotChord中我們看到用handler判斷長按組合鍵500毫秒之後,會進入如下函式:
在這裡啟動了一個執行緒來完成截圖的功能,接著看函式takeScreenshot():
可以看到這個函式使用AIDL繫結了service服務到"com.android.systemui.screenshot.TakeScreenshotService",注意在service連線成功時,對message的msg.arg1和msg.arg2兩個引數的賦值。其中在mScreenshotTimeout中對服務service做了超時處理。接著我們找到實現這個服務service的類TakeScreenshotService,看看其實現的流程:
在這個類中,我們主要看呼叫介面,用到了mScreenshot.takeScreenshot()傳遞了三個引數,第一個是個runnable,第二和第三個是之前message傳遞的兩個引數msg.arg1和msg.arg2。最後我們看看這個函式takeScreenshot(),位於檔案GlobalScreenshot.java中(跟之前的函式重名但是檔案路徑不一樣):
這段程式碼的註釋比較詳細,其實看到這裡,我們算是真正看到截圖的操作了,具體的工作包括對螢幕大小、旋轉角度的獲取,然後呼叫Surface類的screenshot方法截圖儲存到bitmap中,之後把這部分點陣圖填充到一個畫布上,最後再啟動一個延遲的拍照動畫效果。如果再往下探究screenshot方法,發現已經是一個native方法了:
使用JNI技術呼叫底層的程式碼,如果再往下走,會發現對映這這個jni函式在檔案android_view_Surface.cpp中,這個真的已經是底層c++語言了,統一呼叫的底層函式是:
由於對C++不熟,我這裡就不敢多言了。其實到這裡,算是對手機android原始碼中通過組合鍵螢幕截圖的整個流程有個大體瞭解了,一般我們在改動中熟悉按鍵的捕獲原理,並且清楚呼叫的截圖函式介面即可,如果有興趣的,可以繼續探究更深的底層是如何實現的。
轉自:http://blog.csdn.net/woshinia/article/details/11520403
相關文章
- android截圖方法總結Android
- Android 截圖的各種騷操作Android
- 關於Android中各種尺寸的總結Android
- LaTeX中各種常用盒子的使用總結
- caffe中各種cblas的函式使用總結函式
- 程式猿的年終總結,各種版本各種殘
- Android螢幕截圖方式總結Android
- android 截圖程式碼段Android
- python中list的各種方法使用Python
- vivo X7如何截圖?vivo X7截圖方法總結
- Android 截圖與 WebView 長圖分享經驗總結AndroidWebView
- 圖論(三)--各種基礎圖演算法總結圖論演算法
- Http協議中的各種長度限制總結HTTP協議
- Maven-POM中的各種scope的行為總結Maven
- 各種排序演算法總結及C#程式碼實現排序演算法C#
- Android ViewTreeObserver使用總結及獲得View高度的幾種方法AndroidViewServer
- Linux 上截圖的三種方法Linux
- 電腦截圖方法只會【Ctrl+Alt+A】!5個電腦軟體輕鬆搞定各種截圖
- Linux Shell中各種括號用法總結!Linux
- Android系統截圖的實現(附程式碼)Android
- Android 截圖實現的幾種方式Android
- css各種佈局總結CSS
- js各種驗證總結JS
- oracle 各種遷移總結Oracle
- iOS 總結遇到的各種坑兒iOS
- Unix各種括號的用法總結
- win10怎麼截圖_win10截圖的幾種方法Win10
- 多種榮耀10截圖方法分享 榮耀10怎麼截圖?
- Java中各種Log的使用Java
- UML 之 各種檢視簡介 & UML類圖幾種關係的總結
- 總結logminer使用及各種問題處理
- 前端各種迴圈用法總結前端
- 九種解決亂碼方法總結
- java中的成員內部類,程式碼截圖Java
- windows電腦怎麼截圖 5種windows電腦截圖方法Windows
- 前端樹形Tree資料結構使用-🤸🏻♂️各種姿勢總結前端資料結構
- casperjs中start方法的使用方法總結JS
- [zt] 總結logminer使用及各種問題處理