效果
要开启辅助功能并且,并且android版本在api-14或者以上.
GitHub
Afra55/TrainingFirstApp
https://github.com/Afra55/TrainingFirstApp/tree/master
参考文章
最近看到应用宝最新版也加了新功能“省心装”,觉得这玩意挺不错,就研究了下,奈何网上资料少的渣渣,便参考了如下几篇文章自己动手简单实现了下。
(1)使用Android Accessibility实现免Root自动批量安装功能
http://www.infoq.com/cn/articles/android-accessibility-installing?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global
(2)专访豌豆荚「自动装」开发团队:无需Root即可批量点击「下一步」-CSDN.NET
http://www.csdn.net/article/1970-01-01/2824737
(3)https://developer.android.com/intl/zh-cn/guide/topics/ui/accessibility/services.html
添加权限
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"/>
在清单文件里注册service
<!--省心装-->
<service android:name=".module.accessibility_service.MAcessibilityService"
android:label="@string/acc_auto_install_service_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:enabled="@bool/atLeastIceCreamSandwich">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_config" />
</service>
atLeastIceCreamSandwich”是判定当前系统是否api-14及以上版本,14以下的便自己手动安装吧>~<:
accessibility_config是配置文件,在res的xml文件夹下:
配置文件
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/acc_auto_install_service_description"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagDefault"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:packageNames="com.android.packageinstaller"
/>
- description:是描述,在辅助功能里展示。
- packageNames:就是要监听的包名,可以有多个,中间用逗号隔开。比如 “packageName1, packageName2”。
自定义服务
/**
* Created by yangshuai in the 11:43 of 2015.10.22 .
* https://developer.android.com/intl/zh-cn/guide/topics/ui/accessibility/services.html
* 省心装服务
*/
public class MAcessibilityService extends AccessibilityService{
/* 完成安装flag*/
private final static int FINISH_INSTALL = 1009;
/* 检测安装过程flag*/
private final static int CHECK_INSTALL = 1008;
/* 是否执行*/
private static boolean enable = false;
/* 正在模拟点击*/
private boolean clicking = false;
/* 模拟点击的次数, 完成安装后的返回没有计算在里面*/
private static int onClickCount = 0;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case CHECK_INSTALL:
btnPerformClick((List<AccessibilityNodeInfo>)msg.obj);
break;
case FINISH_INSTALL:
enable = false;
AccessibilityService service = (AccessibilityService) msg.obj;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
service.performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
break;
}
}
};
/**
* 设置是否监测
* @param ok
*/
public static void setEnable(boolean ok){
enable = ok;
onClickCount = 0;
}
/**
* Callback for {@link AccessibilityEvent}s.
*
* @param event An event.
*/
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// 如果不监测,和正在模拟点击中
if (!enable || clicking) return;
AccessibilityNodeInfo nodeInfo = event.getSource();
if (nodeInfo == null) {
return;
}
/**
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
Log.d("MAcessibilityService", "nodeInfo.getChild(i):" + nodeInfo.getChild(i).getText());
}
**/
List<AccessibilityNodeInfo> nextBtn = null;
if ((nextBtn = nodeInfo.findAccessibilityNodeInfosByText(getString(R.string.installing))) != null && (nextBtn.size() > 0)){ // 如果正在安装
Log.d("wahaha", "正在安装");
nextBtn.get(0).recycle();
}else if((((nextBtn = nodeInfo.findAccessibilityNodeInfosByText(getString(R.string.next)))!=null && nextBtn.size() > 0) || // 获取下一步按钮控件
((nextBtn = nodeInfo.findAccessibilityNodeInfosByText(getString(R.string.install))) !=null && nextBtn.size() > 0)|| // 获取安装按钮控件
((nextBtn = nodeInfo.findAccessibilityNodeInfosByText(getString(R.string.done))) !=null && nextBtn.size() > 0)) // 获取完成按钮控件
) {
// 模拟点击flag设置为true
clicking = true;
Message message = new Message();
message.obj = nextBtn;
message.what = CHECK_INSTALL;
handler.sendMessageDelayed(message, 500);
}else {
// 判断是否完成安装
handler.removeMessages(FINISH_INSTALL);
Message message = new Message();
message.what = FINISH_INSTALL;
message.obj = this;
handler.sendMessageDelayed(message, 1800);
}
nodeInfo.recycle();
}
/**
* 模拟点击
* @param nextBtn
* @return
*/
private boolean btnPerformClick(List<AccessibilityNodeInfo> nextBtn) {
Log.d("MAcessibilityService", "onClickCount:" + ++onClickCount);
AccessibilityNodeInfo nextInfo = nextBtn.get(nextBtn.size() - 1);
if (nextInfo == null) {
return true;
}
nextInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
nextInfo.recycle();
clicking = false;
return false;
}
/**
* Callback for interrupting the accessibility feedback.
*/
@Override
public void onInterrupt() {
}
}
自定义服务中的字符串
values/strings
<!-- 省心装-->
<string name="install">INSTALL</string>
<string name="installing">Installing…</string>
<string name="done">DONE</string>
<string name="next">NEXT</string>
values-zh-rCN/strings
<!-- 省心装-->
<string name="install">安装</string>
<string name="installing">正在安装...</string>
<string name="done">完成</string>
<string name="next">下一步</string>
总结
如上,很简单就实现了自动安装的功能,当然这里没有对所有机型进行适配。在使用的时候要注意一点是,在使用的时候添加如下一行代码,这样服务才会进行检查:
MAcessibilityService.setEnable(true);
博客地址:http://blog.csdn.net/yang786654260/article/details/49422687