继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android 10 root用户获取imei

九州编程
关注TA
已关注
手记 475
粉丝 42
获赞 202

IMEI(International Mobile Equipment Identity)是国际移动设备识别码的缩写,由15-17位数字组成,与手机是一一对应的关系。无论刷机还是恢复出厂设置,该设备标识码都不会改变,所以在广告和流量统计等方面特别好用,备受开发者的青睐。

但自从android29之后,通android api的TelephonyManager提供的getImei方法已经无法获取到手机的imei了,那我们又该如何获取的手机的唯一设备标识符呢?

Android开发者文档提供的方式是Android Id,这种获取的方式在大多时候确实是有效的,能满足常规的广告统计需要,但如果遇到手机刷机、系统升级或者恢复出厂后,这个id就会被重置,所以在某些业务场景下(例如要将设备标识作为用户唯一id),就显得捉襟见肘了。

网上有一些解决方案,大多是用mac地址,UUid,或者针对特定的手机厂商去生成唯一标识,那我们真的在android 10系统中就拿不到手机的imei了吗?答案是否定的,例如在root权限下,我们就可以绕过android的api,直接拿到手机的imei。

笔者假设用户的手机已经root,并且已经将手机用android调试桥连接到电脑上去,那我们在电脑终端输入adb命令,便可将手机的imei打印出来:

adb shell service call iphonesubinfo 1

截屏2021-04-20 上午11.26.45.png

我们不妨通过正则表达式,将获取到的imei匹配出来:

adb shell service call iphonesubinfo 3 i32 1 | awk -F "'" '{print $2}' | sed '1 d' | tr -d '.' | awk '{print}' ORS=

截屏2021-04-20 上午11.34.24.png

既然我们在终端中可以获取到imei,那我们只需要把这个命令作为shell,在代码里运行即可,但是需要su的权限,不然也获取不到imei:

public static String getImeiByShell(){
        try {
            String shell = "service call iphonesubinfo 3 i32 1 | awk -F \"'\" '{print $2}' | sed '1 d' | tr -d '.' | awk '{print}' ORS=";
            Process p=Runtime.getRuntime().exec(new String[]{"su","-c",shell});
            BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
            String readLine=br.readLine();
            while(readLine!=null){
                Log.d("execShell",readLine);
                return readLine.trim();
            }
            if(br!=null){
                br.close();
            }
            p.destroy();
            p=null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

如此,我们便可以获取到手机的imei。

作者:凌塘
链接:https://juejin.cn/post/6953079991303143432
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP