Android免Root自动安装apk,[Android]使用Android Accessibility实现免Root自动批量安装功能...

freddon

发表于2018-07-26

阅读 1740 |

评论 0

无障碍服务(AccessibilityService)开发指南(多用于抢红包,添加附近好友等功能)

原文来自:[http://www.infoq.com/cn/articles/android-accessibility-installing](http://www.infoq.com/cn/articles/android-accessibility-installing)

对于国内Android设备,应用的自动批量安装/更新一直是一个痛点,在之前,第三方应用商店通常要求设备Root,然后调用系统的PackageManagerService命令行来实现后台安装。最近,豌豆荚利用Android Accessibility(辅助功能)在业内率先实现了免Root自动批量安装功能。

这个功能实现的原理是,在后台批量下载应用后,调用系统的PackageInstaller,获取安装界面的按钮位置,然后通过Accessibility提供的模拟用户点击功能,代替用户自动点击下一步,直到安装结束。

虽然技术看起来不是特别困难,但在实现中还是有不少坑的,豌豆荚工程师向我们分享了该功能的一些技术细节和实践经验。

### Android Accessibility API介绍与调用方法

对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音、触觉反馈、手势操作、轨迹球和手柄操作。开发者可以搭建自己的Accessibility服务,这可以加强应用的可用性,例如声音提示,物理反馈,和其他可选的操作模式。

随着Android系统版本的迭代,Accessibility功能也越来越强大,它能实时地获取当前操作应用的窗口元素信息,并能够双向交互,既能获取用户的输入,也能对窗口元素进行操作,比如点击按钮。更多的介绍见Android开发者官网的Accessibility页面。

调用Android Accessibility API需要三个步骤:申请权限、注册 Service、配置 Accessibility Service Info。使用Accessibility API需要的权限如下:

``````

#### 注册Service

```

android:label="@string/acc_auto_install_service_name"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"

android:enabled="@bool/enable_accessibility">

```

#### 配置Accessibility Service Info

```

xmlns:android="http://schemas.android.com/apk/res/android"

android:description="@string/acc_description" android:accessibilityEventTypes="typeAllMask"

android:accessibilityFlags="flagDefault"

android:accessibilityFeedbackType="feedbackGeneric"

android:notificationTimeout="100"

android:canRetrieveWindowContent="true"

android:settingsActivity="com.your.settingActivity"

android:packageNames="packageName1,packageName2"

/>

```

需要说明的一点是,在配置配置 Accessibility Service Info时,如果明确的知道目标APP的包名,那一定要使用packageNames属性进行设置。举一个例子:

在一些使用虚拟键盘的APP中,经常会出现这样的逻辑

```

Button button = (Button) findViewById(R.id.button);

String num = (String) button.getText();

```

在一般情况下, getText 方法的返回值是 Java.lang.String 类的实例,上面这段代码可以正确运行。但是在开启Accessibility Service之后,如果没有指定packageNames,系统会对所有APP的UI都进行Accessible的处理。在这个例子中的表现就是 getText 方法的返回值变成了 android.text.SpannableString 类的实例( Java.lang.String 和 android.text.SpannableString 都实现了 java.lang.CharSequence 接口),进而造成目标APP崩溃。

所以强烈建议在注册 Accessibility Service 时指定目标APP的packageName,以减少手机上其他应用的莫名崩溃(代码中有这样的逻辑的各位,也请默默的改为调用 toString() 方法吧)。

实现AccessibilityService

继承 android.accessibilityservice.AccessibilityService 并重载 onAccessibilityEvent 及 onInterrupt 方法:

```

public class AccessibilityImpl extends AccessibilityService {

@Override

public void onAccessibilityEvent(AccessibilityEvent event) {}

@Override

public void onInterrupt() {}

}

```

以onAccessibilityEvent与onInterrupt为入口实现业务逻辑代码。

如何获取UI元素

在 onAccessibilityEvent 中,使用参数event的 getSource 方法获取到的 AccessibilityNodeInfo 实例,即为触发这次事件的UI节点。

如果需要获取当前界面上的其它元素,需要获取到当前界面UI Tree的根节点后再使用 findAccessibilityNodeInfosByText 或者 findAccessibilityNodeInfosByViewId 方法进行获取。

需要注意的一点是, findAccessibilityNodeInfosByText 在获取UI元素时的判断逻辑是contains而非equals,在使用时可能要根据具体业务逻辑做进一步的处理。

模拟用户点击

实现AccessibilityService,并获取界面上UI元素之后,可以使用下面的代码来模拟用户点击:

```

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);

```

需要注意的是,在触发事件之前需要确定该UI元素在界面上是否依旧存在。使用该方法还可以模拟用户的其它操作,甚至是复制粘贴这种行为,具体可以参考 [AccessibilityNodeInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo) 。

分类 :日常记录

原文来自:[http://www.infoq.com/cn/articles/android-accessibility-installing](http://www.infoq.com/cn/articles/android-accessibility-installing)

对于国内Android设备,应用的自动批量安装/更新一直是一个痛点,在之前,第三方应用商店通常要求设备Root,然后调用系统的PackageManagerService命令行来实现后台安装。最近,豌豆荚利用Android Accessibility(辅助功能)在业内率先实现了免Root自动批量安装功能。

这个功能实现的原理是,在后台批量下载应用后,调用系统的PackageInstaller,获取安装界面的按钮位置,然后通过Accessibility提供的模拟用户点击功能,代替用户自动点击下一步,直到安装结束。

虽然技术看起来不是特别困难,但在实现中还是有不少坑的,豌豆荚工程师向我们分享了该功能的一些技术细节和实践经验。

### Android Accessibility API介绍与调用方法

对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音、触觉反馈、手势操作、轨迹球和手柄操作。开发者可以搭建自己的Accessibility服务,这可以加强应用的可用性,例如声音提示,物理反馈,和其他可选的操作模式。

随着Android系统版本的迭代,Accessibility功能也越来越强大,它能实时地获取当前操作应用的窗口元素信息,并能够双向交互,既能获取用户的输入,也能对窗口元素进行操作,比如点击按钮。更多的介绍见Android开发者官网的Accessibility页面。

调用Android Accessibility API需要三个步骤:申请权限、注册 Service、配置 Accessibility Service Info。使用Accessibility API需要的权限如下:

``````

#### 注册Service

```

android:label="@string/acc_auto_install_service_name"

android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"

android:enabled="@bool/enable_accessibility">

```

#### 配置Accessibility Service Info

```

xmlns:android="http://schemas.android.com/apk/res/android"

android:description="@string/acc_description" android:accessibilityEventTypes="typeAllMask"

android:accessibilityFlags="flagDefault"

android:accessibilityFeedbackType="feedbackGeneric"

android:notificationTimeout="100"

android:canRetrieveWindowContent="true"

android:settingsActivity="com.your.settingActivity"

android:packageNames="packageName1,packageName2"

/>

```

需要说明的一点是,在配置配置 Accessibility Service Info时,如果明确的知道目标APP的包名,那一定要使用packageNames属性进行设置。举一个例子:

在一些使用虚拟键盘的APP中,经常会出现这样的逻辑

```

Button button = (Button) findViewById(R.id.button);

String num = (String) button.getText();

```

在一般情况下, getText 方法的返回值是 Java.lang.String 类的实例,上面这段代码可以正确运行。但是在开启Accessibility Service之后,如果没有指定packageNames,系统会对所有APP的UI都进行Accessible的处理。在这个例子中的表现就是 getText 方法的返回值变成了 android.text.SpannableString 类的实例( Java.lang.String 和 android.text.SpannableString 都实现了 java.lang.CharSequence 接口),进而造成目标APP崩溃。

所以强烈建议在注册 Accessibility Service 时指定目标APP的packageName,以减少手机上其他应用的莫名崩溃(代码中有这样的逻辑的各位,也请默默的改为调用 toString() 方法吧)。

实现AccessibilityService

继承 android.accessibilityservice.AccessibilityService 并重载 onAccessibilityEvent 及 onInterrupt 方法:

```

public class AccessibilityImpl extends AccessibilityService {

@Override

public void onAccessibilityEvent(AccessibilityEvent event) {}

@Override

public void onInterrupt() {}

}

```

以onAccessibilityEvent与onInterrupt为入口实现业务逻辑代码。

如何获取UI元素

在 onAccessibilityEvent 中,使用参数event的 getSource 方法获取到的 AccessibilityNodeInfo 实例,即为触发这次事件的UI节点。

如果需要获取当前界面上的其它元素,需要获取到当前界面UI Tree的根节点后再使用 findAccessibilityNodeInfosByText 或者 findAccessibilityNodeInfosByViewId 方法进行获取。

需要注意的一点是, findAccessibilityNodeInfosByText 在获取UI元素时的判断逻辑是contains而非equals,在使用时可能要根据具体业务逻辑做进一步的处理。

模拟用户点击

实现AccessibilityService,并获取界面上UI元素之后,可以使用下面的代码来模拟用户点击:

```

nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);

```

需要注意的是,在触发事件之前需要确定该UI元素在界面上是否依旧存在。使用该方法还可以模拟用户的其它操作,甚至是复制粘贴这种行为,具体可以参考 [AccessibilityNodeInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo) 。

评论(0)

先登录,才能发评论哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值