利用Surface进行同屏-Android端

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Alin693/article/details/79961629

逆向同屏:

        第一步,单利模式;

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;
}
阅读更多

没有更多推荐了,返回首页