手机App-插入USB时自动授权点击确定按钮-使系统弹出框自动消失
手机App-插入USB时自动授权点击确定按钮-使系统弹出框自动消失
--蓝牙电话SDK自动部署
-
上一篇:App识别安卓系统弹授权框包含某段文字-并自动点击确定按钮
下一篇:ADB识别手机系统弹授权框-如何处理多重弹框叠加和重叠问题
一、前言
经过前面两个篇章《手机app如何跳过无障碍权限实现弹框自动点击-ADB连接专题》和《App识别安卓系统弹授权框包含某段文字-并自动点击确定按钮》的预研和技术探索,我们对Android中,普通应用App对安卓系统授权框和弹出框做自动确认的能力和实现做法有了初步的了解。
在本篇章中,我们将使用前述文章列举的理论和原理,实战一番,看看在这个自动确认过程中要具体如何做,会面临什么问题和难点。最后再将这个功能给统一整合到【蓝牙电话方案-拨号器SDK】中,供有需要的用户和朋友进行体验和试用。
体验和下载地址:
智能拨号器App:http://120.78.211.195:8060/Dialer.apk
拨号器SDK示例app:http://120.78.211.195:8060/sdk/SdkDemo.apk
USB蓝牙配件购买路径(参考):https://item.taobao.com/item.htm?_u=pk10l4ccbcd&id=649368472986
- 二、需求的引入-为何系统会弹框
早年的Android操作系统,对App需要开启哪些权限仅需要在AndroidManifest.xml文件中对权限进行申明,即可在App运行过程中具备对应的使用权限。
后来,Android学坏了。从Android6.0开始,逐步的增加了授权弹框的机制和功能:App的开发者不仅需要在AndroidManifest.xml文件进行申明,还需要在App运行过程中弹出对话框出来,需要用户手动去点击允许或确认,才能获取得到某个它认为比较关键的权限。
(当然,如果我们是Android系统开发者,我们可以在代码中屏蔽此部分的弹框。但对于普通应用开发者而言,这个搞法就比较恶心人了)。
在弹框权限中,我们依照坑爹程度,将授权弹框按弹出的频率进行分类,可以大致分为如下三类:
1、App安装后只会弹一次:允许后哪怕是应用升级也不会再弹新的授权框。此部分弹框包括普通的读取SD卡权限、访问通讯录权限、悬浮窗权限等非常多的常见权限。
2、每次重启手机后,都需要重新获取一次的权限。比如adbd网络映射到5555端口。
3、每次运行都会触发的弹窗授权,比如无障碍模式、比如外置USB配件的拔插等。
在我们的应用中,上述这三种弹窗授权都会碰到。
如果应用App要做成“免装机模式”,安装完后不想人工运行和操作就直接用,那么就应该吧上述这三种弹窗都通过自动化脚本,做成自动确认的模式。
我们本期将针对第三种,即每次运行都会触发的弹窗授权进行自动化操作。(第一第二种的授权,由于弹窗太过复杂,不同品牌手机不同系统版本的界面都有差异,建议还是App安装后使用人工点击一次。)
在【蓝牙电话SDK】中,App运行过程中,每次拔插USB均会弹出USB授权窗口,不确认它就无法识别外置USB配件。非常烦人,本次就搞它,让它自动消失。
- 三、Android弹框时应用能知道吗?
知道的,根据Android的开发规范:应用想要获取某个权限,除了需要在AndroidManifest.xml文件申明<uses-permission />或<uses-feature />之外,需要应用App本身逻辑去主动调用和请求对应的权限,然后Android系统才会做出弹框处理,弹出授权窗口供手机用户进行手动的点击授权。授权成功后才会返回对应的手机权限给到App进行使用。
对于外置USB配件拔插的事件,也是同样的道理。Android会产生对应的广播事件,将插入和拔出消息通知到对应的App,如果App确定要消费这个事件,才会由App去主动请求对应的USB打开请求。然后Android才会做出弹窗提示和处理。
也就是说,Android系统所有的授权框,都是由用户App来进行触发的。只是Android操作系统认为,这个功能比较谨慎,需要由手机用户亲自来做确认,才能开放给普通App。
- 四、应用如何识别当前的弹框是不是自己预期的那个?
由于授权弹框操作是异步的。对于普通应用App而言,它只负责在Activity中重写onRequestPermissionsResult等待返回授权成功/授权失败的结果,然后调用
ActivityCompat.requestPermissions(ctx, permis, requestCode);
接口进行权限的请求即可。
但对于本篇文章的课题而言,我们需要知道当前弹的窗口,到底是不是自己预期的窗口(因为很有可能会弹出了多个窗口形成了覆盖)。由于前面篇章中我们讲到可以使用:
adb shell uiautomator dump /sdcard/window.xml
的指令,提取得到手机最上层界面的所有元素的内容快照。
本篇章中,我们将直接在应用App中读取/sdcard/window.xml文件的字符串,通过关键字的检索等方式,查找和匹对弹出框标题及包含的内容。通过这样的方式来识别出当前最上层的窗口是哪一个,并针对性的做点击处理。
- 五、App如何做自动点击
依照前文《App识别安卓系统弹授权框包含某段文字-并自动点击确定按钮》可知,在Android的App中,可使用【adb shell input tap x y】的指令,向Android手机发送点击事件,实现App的自动点击操作。
事实上,光说【adb shell xxx】指令比较虚。在代码开发中,如果想让应用app实现发送和执行adb指令,需要实现一个自己的adb客户端。
通常来说,安卓App实现adb客户端一般有两种办法:
1、使用Google自带的【com.android.ddmlib】的相关库,进行异步连接和指令收发;
2、使用第三方开源库如adblib来封装adb客户端的逻辑(本质上就是一个socket收发特定格式的tcp数据),开源库路径可参考:
https://github.com/tananaev/adblib
- 六、困难点和关键点
本文的自动点击的方式基于安卓手机的adb命令,通过Socket连接到设备的ADB端口(默认5555)。因此,每次手机重启后,均需要插入USB调试线,使用【adb tcpip】命令将手机的网络ADB调试功能开启:
adb tcpip 5555
或者开启了端口转发:
adb forward tcp:5555 tcp:5555
另外,由于adb命令将连到手机开放的adbd进程中,因此会涉及密钥配对的问题,即手机会自动弹一个框出来,需要允许对方(也是本机)绑定到当前手机的adbd使用:
好消息是:应用App在手机的运行过程只需要弹一次框,后续将RSA密钥指纹存储到手机sdcard中,从此不管应用是否被卸载,均不会再次弹框做提示。
- 七、总结
本文使用前述文章列举的理论和原理,最终实现了【插入外置USB配件后系统弹出USB授权弹窗】的自动点击操作。并将这个功能给统一整合到【蓝牙电话方案-拨号器SDK】中,使基于其上的普通应用App能够对弹窗文本进行识别,识别成功后将自动点击其“确定”或“允许”按钮。
通过在普通App中整合此类功能,可快速通过一些因Android授权弹框而阻塞App自动运行的过程,减少了人工行为的干预从而降低操作复杂度。
最后,在文章末尾简单录制一段【手机中插入USB蓝牙,在App弹出授权窗口中自动点击确认允许】的视频,作为实际效果的展示,仅供参考。
手机中插入USB蓝牙,在App弹出授权窗口中自动点击确认允许