通过ijetty获取android设备的截图
16lz
2022-05-22
需求:对于无显示设备的android设备,如何获取到当前设备画面
条件:首先在android设备中搭建一个web服务器,可以参考基于前面介绍的ijetty服务器
实现:
方法1:
参考系统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服务器把图像传出来,可以拿到上面代码中的outputStream,然后拷贝到HttpServletResponse的输出流中。
这个screenshot函数还需要一些其他数据,例如display,metrics,dims等,我们参考Surface类中的实现,得出的可用类代码如下:
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请求就能拿到对应的流了 然后存在本地即可。
方法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();}
代码执行后,再把文件拷到servlet的输出流中就好了。screencap只支持png格式的存储。
以上两种方法都需要添加权限:
并使用system uid
更多相关文章
- Android(安卓)入门到精通 (界面编程#2-Menu)
- Android——最新LitePal使用
- Android的System Server
- Android清除本地数据缓存代码案例
- android 自定义水平和圆形progressbar 只定义一些style就可以
- Android访问服务器出现W/System.err(9302): java.io.FileNotFoun
- android闹钟――原代码
- 搭建Android(安卓)NDK开发环境
- 【Android】ToolBar设置NavigationIcon不显示异常或自定义失败异