高仿豌豆荚免Root自动安装(AccessibilityService)

对于那些由于视力、听力或其它身体原因导致不能方便使用 Android 智能手机的用户,Android 提供了 Accessibility 功能和服务帮助这些用户更加简单地操作设备,包括文字转语音、触觉反馈、手势操作、轨迹球和手柄操作。开发者可以搭建自己的 Accessibility 服务,这可以加强应用的可用性,例如声音提示,物理反馈,和其他可选的操作模式。- 随着Android系统版本的迭代,Accessibility功能也越来越强大,它能实时地获取当前操作应用的窗口元素信息,并能够双向交互,既能获取用户的输入,也能对窗口元素进行操作,比如点击按钮。更多的介绍见Android开发者官网的Accessibility页面。

  • 话不多说直接开始,首先使用Android Accessibility 需要三个步骤:
    1、申请权限
    2、注册服务
    3、配置 AccessibilityService Info首先需要申请权限
    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
    注册服务
<service        
        android:name=".Your Accessibility Name"       
        android:enabled="true"        
        android:exported="true"        
        android:label="Your Service Title"      
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
        android:process=":accessibility">        
        <intent-filter>            
                <action android:name="android.accessibilityservice.AccessibilityService" />       
         </intent-filter>        
        <meta-data            
        android:name="android.accessibilityservice"            
        android:resource="@xml/accessibility_config" />
</service>

配置 AccessibilityService Info

<accessibility-service    xmlns:android="http://schemas.android.com/apk/res/android"    android:accessibilityEventTypes="typeViewScrolled|typeWindowContentChanged|typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:accessibilityFlags="flagDefault|flagReportViewIds"
    android:canRetrieveWindowContent="true"
    android:description="@string/auto_service_des"
    android:packageNames="com.android.packageinstaller,com.google.android.packageinstaller,com.samsung.android.packageinstaller,com.lenovo.safecenter,com.lenovo.security" />

在这里需要注意的是packageNames是AccessibilityService所监听的应用的包名。可以监听多个,在自动安装的时候箭筒不同的包名用于做适配。源码中会有所要适配的包名,包含了大部分安装程序的包名。该程序实现自动装的原理分析:首先我们可以用 getRootInActiveWindow(),和event.getSource()均可以得到AccessibilityNodeInfo的实例,即为触发这次事件的UI节点。
重写AccessibilityService服务,实现onAccessibilityEvent方法,该方法是监听服务监听到界面变化会调用因此,我们从该方法去做实现我们的自动安装功能。
那么我们如何找到UI元素呢?
1、findAccessibilityNodeInfosByText(String text) 该方法可以根据控件显示的文本得到控件。所注意的是该方法的逻辑是包含(contains)而不是等于(equal)。
例如:参数我们传递 "安装" ,那么像,"是否安装?","安装",都会得到,所以需要我们去处理。最后我们使用模拟用户点击实现自动点击效果

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);

实现的基本流程就是这样,但是这只是刚刚开始,我们需要更严格的逻辑去处理,现在可以看下onAccessibilityEvent方法我是怎么实现的,

private void doAccessibilityEvent(AccessibilityEvent event) {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { 
       String className = event.getClassName().toString(); 
       if (uninstallPkgSet.contains(className)) {
            isInstallOrUninstall = false;
        }        
if(installViewSet.contains(event.getClassName().toString())) {
            isInstallOrUninstall = true;        
}        
if (installViewSet.contains(event.getPackageName().toString())) {
            isInstallOrUninstall = true; 
       } 
       AccessibilityNodeInfo rootNodeInfo = getRootInActiveWindow();
        if (rootNodeInfo != null && isInstallOrUninstall) {
            String pkgName = (String) rootNodeInfo.getPackageName();
            if (installPkgSet.contains(pkgName)) { 
               for (int i = 0; i < nodeContents.size(); i++) {
                    List<AccessibilityNodeInfo> textNodeInfo = new ArrayList<>(); 
                   for (int k = 0; k < completeTexts.size(); k++) {                       
                      textNodeInfo.addAll(rootNodeInfo.findAccessibilityNodeInfosByText(completeTexts.get(k))); 
                   } 
                   if (textNodeInfo.size() > 0) {
                        for (int j = 0; j < textNodeInfo.size(); j++) { 
                           String text = textNodeInfo.get(j).getText().toString();
                            if (completeTexts.contains(text)) {
                                clickInstall(textNodeInfo.get(j));
                            } 
                       }
                    } 
               } 
           }
        }
        AccessibilityNodeInfo nodeInfo = event.getSource();
        if (nodeInfo != null && isInstallOrUninstall) {
            for (int i = 0; i < nodeContents.size(); i++) {
                List<AccessibilityNodeInfo> textNodeInfo = nodeInfo.findAccessibilityNodeInfosByText(nodeContents.get(i)); 
               List<AccessibilityNodeInfo> installNodeInfo = new ArrayList<>();
                for (int k = 0; k < completeTexts.size(); k++) {
                    installNodeInfo.addAll(nodeInfo.findAccessibilityNodeInfosByText(installTexts.get(k)));
                } 
               boolean isInstall = installNodeInfo.size() != 0; 
               if (textNodeInfo != null && textNodeInfo.size() > 0) {
                    for (int j = 0; j < textNodeInfo.size(); j++) { 
                       String text = textNodeInfo.get(j).getText().toString(); 
                       if (nodeContents.contains(text) && isInstall) { 
                           clickInstall(textNodeInfo.get(j)); 
                       }
                    }
                } 
           } 
       } 
   }}

在这里我是根据豌豆荚所兼容的android手机都进行了兼容处理,并对多语言进行处理。大家看到我对单个文字也进行了list话不理解的话,想想多语言,估计就理解了。目前测试国内及国外手机几乎都能实现自动装。目前有一个AppInstall的管理类,实现了Root安装,及accessibility安装的管理。让使用起来更加方便。
项目地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,510评论 25 707
  • 走过人生的山河与岁月,每一程山水都有不同的风景,每一段岁月都有不同的颜色,无论是沧桑还是美好,都是岁月给我们的馈赠...
    门前折柳阅读 207评论 0 0
  • 常说自律即自由。我们往往只看到自由,却忽略自律。
    Patsang阅读 327评论 0 0
  • 是一个自己总是记不太清的属性: 几个相同的元素,添加同样的一个点击事件处理程序来做处理,需要将元素自身 传递给事件...
    秋夜已凉阅读 2,160评论 0 2