需求:對(duì)于無顯示設(shè)備的android設(shè)備勃救,如何獲取到當(dāng)前設(shè)備畫面
條件:首先在android設(shè)備中搭建一個(gè)web服務(wù)器宏榕,可以參考基于前面介紹的ijetty服務(wù)器
實(shí)現(xiàn):
方法1:
參考系統(tǒng)hide代碼,android.view.Surface.java
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 ;
}
我們要利用web服務(wù)器把圖像傳出來碱鳞,可以拿到上面代碼中的outputStream桑李,然后拷貝到HttpServletResponse的輸出流中。
這個(gè)screenshot函數(shù)還需要一些其他數(shù)據(jù)窿给,例如display贵白,metrics,dims等崩泡,我們參考Surface類中的實(shí)現(xiàn)戒洼,得出的可用類代碼如下:
public class ScreenshotNative {
private Context mContext;
private WindowManager mWindowManager;
private Display mDisplay;
private DisplayMetrics mDisplayMetrics;
private Matrix mDisplayMatrix;
private Bitmap mScreenBitmap;
private static final Object sLock = new Object();
public ScreenshotNative(Context context) {
mContext = context;
mDisplayMatrix = new Matrix();
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplay = mWindowManager.getDefaultDisplay();
mDisplayMetrics = new DisplayMetrics();
mDisplay.getRealMetrics(mDisplayMetrics);
}
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;
}
public void takeScreenshot(OutputStream out) throws IOException {
// We need to orient the screenshot correctly (and the Surface api seems to take screenshots
// only in the natural orientation of the device :!)
//
mDisplay.getRealMetrics(mDisplayMetrics);
float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
float degrees = getDegreesForRotation(mDisplay.getRotation());
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]);
}
Log.d("takeScreenshot", "takeScreenshot, dims, w-h: " + dims[0] + "-" + dims[1] + "; " +
"dm w-h: " + mDisplayMetrics.widthPixels + mDisplayMetrics.heightPixels +
"Thread=" + Thread.currentThread().getName());
// Take the screenshot
synchronized (sLock) {
mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
if (mScreenBitmap == null) {
throw new IOException("Bitmap is null after taking native screenshot!");
}
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);
// Recycle the previous bitmap
mScreenBitmap.recycle();
mScreenBitmap = ss;
}
// Optimizations
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
mScreenBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
Log.d("takeScreenshot","Thread=" + Thread.currentThread().getName());
mScreenBitmap.recycle();
// Clear any references to the bitmap
mScreenBitmap = null;
}
}
}
使用方法如下:
private void screenshotNative(HttpServletResponse response){
try {
ServletOutputStream outputStream = response.getOutputStream();
new ScreenshotNative(mContext).takeScreenshot(outputStream);
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
這樣在GET請(qǐng)求就能拿到對(duì)應(yīng)的流了 然后存在本地即可。
方法2:
使用screencap工具
public void takeScreenShot(){
String mSavedPath = "/sdcard/" + "screenshot.png" ;
try {
Process p = Runtime. getRuntime().exec("screencap -p " + mSavedPath);
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
代碼執(zhí)行后允华,再把文件拷到servlet的輸出流中就好了圈浇。screencap只支持png格式的存儲(chǔ)。
以上兩種方法都需要添加權(quán)限:
<uses-permission android:name="android.permission.READ_FRAME_BUFFER"/>
并使用system uid