Android 获取屏幕指定坐标的颜色——“按键精灵”基础

原理:借助Android系统提供的ImageReader读取当前屏幕,然后转化为Bitmap对象,Bitmap像素宽高正好和当前屏幕一致,然后调用Bitmap中的getPixel(x, y)方法获取目标点的坐标


创建屏幕扫描器

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_MEDIA_PROJECTION = 1;
    private MediaProjectionManager mMediaProjectionManager;
    private MediaProjection mMediaProjection;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        rootCmd();
        mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        if (mMediaProjectionManager != null) {
            startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
        }
    }

    /**
     * 获取root权限,研究按键精灵中模拟按键功能的童鞋可以添加
     */
    public void rootCmd() {
        Process process = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes("chmod 777 /dev/block/mmcblk0\n");
            os.writeBytes("exit\n");
            os.flush();
            process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (process != null) {
                process.destroy();
            }
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_MEDIA_PROJECTION) {
            if (resultCode != Activity.RESULT_OK) {
                LogUtils.i("User cancelled");
                Toast.makeText(this, "User cancelled!", Toast.LENGTH_SHORT).show();
                return;
            }

            LogUtils.i("Starting screen capture");
            mMediaProjection = mMediaProjectionManager.getMediaProjection(resultCode, data);
            setUpVirtualDisplay();
        }
    }

    private void setUpVirtualDisplay() {
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getRealMetrics(dm);

        final ImageReader imageReader = ImageReader.newInstance(dm.widthPixels, dm.heightPixels, PixelFormat.RGBA_8888, 1);
        mMediaProjection.createVirtualDisplay("ScreenCapture",
            dm.widthPixels, dm.heightPixels, dm.densityDpi,
            DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
            imageReader.getSurface(), null, null);
        GBData.reader = imageReader;
    }

}

根据坐标获取颜色

public class GBData {

    static ImageReader reader;
    private static Bitmap bitmap;

    /**
     * 获取目标点的RGB值
     */
    public static int getColor(int x, int y) {
        if (reader == null) {
            LogUtils.w("reader is null");
            return -1;
        }

        Image image = reader.acquireLatestImage();

        if (image == null) {
            if (bitmap == null) {
                LogUtils.w("image is null");
                return -1;
            }
            return bitmap.getPixel(x, y);
        }
        int width = image.getWidth();
        int height = image.getHeight();
        final Image.Plane[] planes = image.getPlanes();
        final ByteBuffer buffer = planes[0].getBuffer();
        int pixelStride = planes[0].getPixelStride();
        int rowStride = planes[0].getRowStride();
        int rowPadding = rowStride - pixelStride * width;
        if (bitmap == null) {
            bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
        }
        bitmap.copyPixelsFromBuffer(buffer);
        image.close();

        return bitmap.getPixel(x, y);
    }
}

具体业务中使用

int color = GBData.getColor(x,y)
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
LogUtils.d("red:" + r + ",green:" + g + ",blue:" + b);

日志截图

D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:681.0,Y:1152.0:red:105,green:104,blue:120
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:323.0,Y:833.0:red:204,green:224,blue:232
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:961.0,Y:1263.0:red:247,green:254,blue:249
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:993.0,Y:690.0:red:253,green:254,blue:249
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:649.0,Y:1430.0:red:219,green:199,blue:202
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:602.0,Y:1404.0:red:231,green:184,blue:169
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:536.0,Y:1524.0:red:105,green:138,blue:165
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:956.0,Y:692.0:red:217,green:229,blue:228
D/com.jerry.pixscanner:MainActivity.lambda$onCreate$0(L:43): X:643.0,Y:1735.0:red:0,green:92,blue:161

Android 获取屏幕指定坐标的颜色——“按键精灵”基础

github 地址,喜欢星星

https://github.com/wangzhili0803/pixScanner