Android 5.0后截屏,无需root

本文介绍了Android 5.0及更高版本中如何使用官方API实现无root设备的截屏功能。主要涉及MediaProjectionManager、ImageReader等类的使用,包括启动截屏服务、新建虚拟屏幕以及处理虚拟屏幕图像的步骤。同时对比了需要root权限的shell方式截屏。
摘要由CSDN通过智能技术生成

Android5.0截屏,无需root

关于截屏这一块,Android在5.0之后提供了官方的API,关于截屏也不需要使用adb,root,以及去模拟按键又或者去撸隐藏代码了。
主要用到以下几个类:
1. MediaProjection
2. MediaProjectionManager
3. MediaProjection.Callback
4. DisplayManager
5. VirtualDisplay
6. VirtualDisplay.Callback
7. ImageReader
8. Image
9. Bitmap
10. PixelFormat

实现步骤

拿到屏幕上的实时信息

先请求截屏的服务,然后拿到返回来的Intent数据.
这里实现打开一个服务,跟一般的服务不一样,这里的服务会转换为一个MediaProjectionManager,看命名是一个管理器,这个管理器持有MediaProjection,还有一个请求截屏的Intent。有两种方式拿到这个MediaProjectionManager.

Context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
or
Context.getSystemService(MediaProjectionManager.class);

拿到MediaProjectionManager后,就可以拿到它名下的一个Intent,通过启动这个Intent,我们可以拿到另外一个Intent。所以我们必须用 startActivityForResult这种方式来启动这个Intent。
启动这个Intent,系统会向用户申请权限,告知用户接下来会有截屏操作,同时也开始截屏的准备工作了。因为我们是以startActivityForResult方式启动的,所以在onActivityResult里面会返回实时的屏幕的信息(这里的信息不是以图像的形式出现,所以我们拿到信息后还需要自己处理转换成我们需要的图像信息)。(录屏也是这样做的)

    public void requestScreenShot() {
        if (Build.VERSION.SDK_INT >= 21) {
//            MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);  //方式一
            MediaProjectionManager mediaProjectionManager = getSystemService(MediaProjectionManager.class);  //方式二
            startActivityForResult(mediaProjectionManager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);//REQUEST_MEDIA_PROJECTION是我们自己定义的一个int,随便给可以。
        } else {
            Toast.makeText(MainActivity.this, "版本过低,无法截屏", Toast.LENGTH_SHORT).show();
        }
    }

onActivityResult方法里面可以拿到返回的数据,Intent类型。

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case REQUEST_MEDIA_PROJECTION: {
                if (resultCode == -1 && data != null) {
  //这里的resultCode必须为-1(Activity.RESULT_OK),后面也会用到-1(系统返回的-1,只需要记住就可以了);
                    this.data = data;  //记录这里拿到data,是一个Intent,实际上这里记录的只是一个引用,里面的东西是实时在改变的(因为里面记录的是屏幕信息),信息存储在intent里面的bundle,bundle里面记录的是一个用Android专用序列化方式Parcelable序列化过的一个对象。
                }
            }
        }
    }

拿到屏幕信息后,我们需要处理,将其转换成我们需要的PNG或者bitmap格式。
处理分为大抵分为两步,第一步,新建一个虚拟屏幕,将之前拿到的信息显示在虚拟屏幕上;第二步,拿到屏幕上的图像。

新建一个虚拟屏幕

这里还是需要借助MediaProjectionManager,上面有说过,MediaProjectionManager持有MediaProjection,还有一个请求截屏的Intent,Intent我们已经用过了,这里会用到MediaProjection。我们要拿到这个MediaProjection,方法里面有两个参数(一个是上面说的-1(Activity.RESULT_OK),一个是上面拿到的屏幕信息Intent)

if(null==mMediaProjection)
    mMediaProjection = mediaProjectionManager.getMediaProjection(Activity.RESULT_OK,data);
 //这里的mediaProjectionManager 跟上面的不一定是同一个对象,可以自己通过Context重新请求一个MediaProjectionManager

初始化一个ImageReader对象,这个对象会在虚拟化屏幕里面用到,这个ImageReader实际上是屏幕上面的画面。初始化一个ImageReader用到四个参数会。newInstance (int width, int height, int format, int maxImages)分别代表图像的宽、高、图像色彩格式、imagereader里面最多存储几张图像(多了耗费内存),这里格式必须是ImageFormatPixelFormat里面的,当然也并不是说里面的所有格式都支持,ImageFormat.NV21就不支持。

mImageReader = ImageReader.newInstance(
                    getScreenWidth(),  //真实屏幕宽度
                    getScreenHeight(),  //真实屏幕高度
                    PixelFormat.RGBA_8888,// a pixel两节省一些内存 个2个字节 此处RGBA_8888 必须和下面 buffer处理一致的格式
                    1);  //最多存储一张图像

下面是一些获取真实屏幕参数的方法:

//获取真实屏幕宽度(单位px)
private int getScreenWidth() {
        return Resources.getSystem().getDisplayMetrics().widthPixels;
    }
//获取真实屏幕高度(单位px)
private int getScreenHeight() {
        return Resources.getSystem().getDisplayMetrics().heightPixels;
    }
//获取状态栏高度(单位px)
private int getStatusBatHeight(){
        /**
         * 获取状态栏高度——方法1
         * */
       //获取status_bar_height资源的ID
        int resourceId = getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            /
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值