逆向同屏:
第一步,单利模式;
private static ScreenShot instance; private float[] dims; static ScreenShot getInstance(Context context) { synchronized (ScreenShot.class) { if (instance == null) { instance = new ScreenShot(); instance.dims = instance.getPixel(context); } } return instance; } void takeScreenshot(String host, int port) { try { Socket socket = new Socket(host, port); Thread send = new Thread(new SendScreenShot(socket)); Thread receive = new Thread(new ReceiveCommand(socket)); send.start(); receive.start(); send.join(); receive.join(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } }
第二步,屏幕截图;
/** 屏幕截图 */ private byte[] getBitmapByte(){ return qualityZoom(areaZoom(screenShot((int) dims[0], (int) dims[1]))); } /** 质量缩放 */ private byte[] qualityZoom(Bitmap bitmap) { Bitmap mutable = bitmap.copy(Bitmap.Config.RGB_565, true); ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); mutable.compress(Bitmap.CompressFormat.JPEG, 20, byteStream); return byteStream.toByteArray(); } /** 面积缩放 */ private Bitmap areaZoom(Bitmap image) { Matrix matrix = new Matrix(); matrix.setScale(0.5f, 0.5f); return Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), matrix, true); } private Bitmap screenShot(int width, int height) { try { return (Bitmap) getSurfaceClass().invoke(null, width, height); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } private Method getSurfaceClass(){ Class<?> surfaceClass; Method method = null; try { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) { surfaceClass = Class.forName("android.view.SurfaceControl"); } else { surfaceClass = Class.forName("android.view.Surface"); } method = surfaceClass.getDeclaredMethod("screenshot", int.class, int.class); method.setAccessible(true); } catch (Exception e) { Log.e("ScreenShot", e.toString()); } return method; } private float[] getPixel(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); assert wm != null; Display mDisplay = wm.getDefaultDisplay(); DisplayMetrics mDisplayMetrics = new DisplayMetrics(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { mDisplay.getRealMetrics(mDisplayMetrics); } return new float[]{ mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels }; }
第三步,进行线程实例;
private class SendScreenShot implements Runnable { private Socket socket; SendScreenShot(Socket socket) { this.socket = socket; } @Override public void run() { try { BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); while (socket.isConnected()) { byte[] img = getBitmapByte(); byte[] byteLen = intToBytes(img.length); bos.write(byteLen); bos.write(img); } socket.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } } private class ReceiveCommand implements Runnable { private Socket socket; ReceiveCommand(Socket socket) { this.socket = socket; } @Override public void run() { try { BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); while (socket.isConnected()) { byte[] byteLen = new byte[4]; int len; int count = 0; int result; while ((result = bis.read(byteLen, count, 4 - count)) != -1) { count += result; if (count == 4) { count = 0; break; } } len = bytesToInt(byteLen, 0); if (len <= 0) { back(); continue; } byte[] coordinate = new byte[len]; while ((result = bis.read(coordinate, count, len - count)) != -1) { count += result; if (count == len) { break; } } Point[] points = new Point[len / 8]; for (int i = 0, l = 0; i < len; i += 4, l = i / 8) { Point point = points[l]; if (point == null) { points[l] = new Point(); } else { point.setX(bytesToInt(coordinate, l * 8)); point.setY(bytesToInt(coordinate, l * 8 + 4)); } } executeSwipe(points); } } catch (IOException e) { e.printStackTrace(); } } }
第四步,传回命令执行;
private void back() { try { Instrumentation inst = new Instrumentation(); inst.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK); } catch (Exception e) { e.printStackTrace(); } } private void executeSwipe(Point[] points) { Point start = points[0]; Point end = points[1]; int x = (end.getX() - start.getX()) / 10; int y = (end.getY() - start.getY()) / 10; Instrumentation inst = new Instrumentation(); long dowTime = SystemClock.uptimeMillis(); inst.sendPointerSync(MotionEvent.obtain(dowTime, dowTime, MotionEvent.ACTION_DOWN, start.getX(), start.getY(), 0)); for (int i = 0; i < 10; i++) { inst.sendPointerSync(MotionEvent.obtain(dowTime, dowTime + i * 10, MotionEvent.ACTION_MOVE, start.getX() + x * i, start.getY() + y * i, 0)); } inst.sendPointerSync(MotionEvent.obtain(dowTime, dowTime + 100, MotionEvent.ACTION_UP, end.getX(), end.getY(), 0)); } private class Point { private int x; private int y; Point() { } int getX() { return x; } void setX(int x) { this.x = x; } int getY() { return y; } void setY(int y) { this.y = y; } @Override public String toString() { return "Point{" + "x=" + x + ", y=" + y + '}'; } } static byte[] intToBytes(int value) { byte[] des = new byte[4]; des[0] = (byte) (value & 0xff); // 低位(右边)的8个bit位 des[1] = (byte) ((value >> 8) & 0xff); //第二个8 bit位 des[2] = (byte) ((value >> 16) & 0xff); //第三个 8 bit位 /* * (byte)((value >> 24) & 0xFF); * value向右移动24位, 然后和0xFF也就是(11111111)进行与运算 * 在内存中生成一个与 value 同类型的值 * 然后把这个值强制转换成byte类型, 再赋值给一个byte类型的变量 des[3] */ des[3] = (byte) ((value >> 24) & 0xff); //第4个 8 bit位 return des; } static int bytesToInt(byte[] des, int offset) { int value; value = des[offset] & 0xff | ((des[offset + 1] & 0xff) << 8) | ((des[offset + 2] & 0xff) << 16) | (des[offset + 3] & 0xff) << 24; return value; }