1.AccessibilityService这个类
需要写一个类继承AccessibilityService这个类,模拟用户点击安装和卸载的界面上的按钮,如下:包括了安装、卸载、清理进程。
package com.jack.accessibility;
import java.util.List;
import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.util.Log;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@SuppressLint("NewApi")
public class MyAccessibilityService extends AccessibilityService {
public static int INVOKE_TYPE = 0;
public static final int TYPE_KILL_APP = 1;
public static final int TYPE_INSTALL_APP = 2;
public static final int TYPE_UNINSTALL_APP = 3;
public static void reset() {
INVOKE_TYPE = 0;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// TODO Auto-generated method stub
this.processAccessibilityEnvent(event);
}
private void processAccessibilityEnvent(AccessibilityEvent event) {
Log.d("test", event.eventTypeToString(event.getEventType()));
if (event.getSource() == null) {
Log.d("test", "the source = null");
} else {
Log.d("test", "event = " + event.toString());
switch (INVOKE_TYPE) {
case TYPE_KILL_APP:
processKillApplication(event);
break;
case TYPE_INSTALL_APP:
processinstallApplication(event);
break;
case TYPE_UNINSTALL_APP:
processUninstallApplication(event);
break;
default:
break;
}
}
}
@Override
protected boolean onKeyEvent(KeyEvent event) {
// TODO Auto-generated method stub
return true;
}
@Override
public void onInterrupt() {
// TODO Auto-generated method stub
}
private void processUninstallApplication(AccessibilityEvent event) {
Log.e("hxk", event.getPackageName().toString());
if (event.getSource() != null) {// 此处是为了适配三星手机
if (event.getPackageName().equals("com.android.packageinstaller") || event.getPackageName().equals("com.samsung.android.packageinstaller")) {
List<AccessibilityNodeInfo> ok_nodes = event.getSource()
.findAccessibilityNodeInfosByText("确定");
if(ok_nodes.size() == 0){
ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确认");
}
if (ok_nodes != null && !ok_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < ok_nodes.size(); i++) {
node = ok_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")
&& node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
ok_nodes = event.getSource().findAccessibilityNodeInfosByText(
"卸载");
if (ok_nodes != null && !ok_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < ok_nodes.size(); i++) {
node = ok_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")
&& node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
}
}
private void processinstallApplication(AccessibilityEvent event) {
if (event.getSource() != null) {
if (event.getPackageName().equals("com.android.packageinstaller")) {
List<AccessibilityNodeInfo> unintall_nodes = event.getSource()
.findAccessibilityNodeInfosByText("安装");
if (unintall_nodes != null && !unintall_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < unintall_nodes.size(); i++) {
node = unintall_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")
&& node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
List<AccessibilityNodeInfo> next_nodes = event.getSource()
.findAccessibilityNodeInfosByText("下一步");
if (next_nodes != null && !next_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < next_nodes.size(); i++) {
node = next_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")
&& node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
List<AccessibilityNodeInfo> ok_nodes = event.getSource()
.findAccessibilityNodeInfosByText("打开");
if (ok_nodes != null && !ok_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < ok_nodes.size(); i++) {
node = ok_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")
&& node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
}
}
private void processKillApplication(AccessibilityEvent event) {
if (event.getSource() != null) {
if (event.getPackageName().equals("com.android.settings")) {
List<AccessibilityNodeInfo> stop_nodes = event.getSource()
.findAccessibilityNodeInfosByText("强行停止");
if (stop_nodes != null && !stop_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < stop_nodes.size(); i++) {
node = stop_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")) {
if (node.isEnabled()) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
List<AccessibilityNodeInfo> ok_nodes = event.getSource()
.findAccessibilityNodeInfosByText("确定");
if (ok_nodes != null && !ok_nodes.isEmpty()) {
AccessibilityNodeInfo node;
for (int i = 0; i < ok_nodes.size(); i++) {
node = ok_nodes.get(i);
if (node.getClassName().equals("android.widget.Button")) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
Log.d("action", "click ok");
}
}
}
}
}
}
}
其中,event.getPackageName()拿到的包名是android系统安装应用包名:com.android.packageinstaller。
但是个别厂商会修改,比如三星手机com.samsung.android.packageinstaller。
2.清单文件配置
- 添加权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- 注册MyAccessibilityService服务:
其中label是手机辅助功能里代表本应用的名字<service android:name="com.jack.accessibility.MyAccessibilityService" <strong>android:label</strong>="@string/acc_service_name" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" > <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" <span style="white-space:pre"> </span> <strong>android:resource</strong>="@xml/phone_accessibility" /> </service>
resource内容为:
description是对本应用开启辅助功能时的描述<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="" android:canRetrieveWindowContent="true" <strong>android:description</strong>="@string/accessibility_service_description" android:notificationTimeout="100" />
3.开始调用此服务来静默安装和卸载
安装和卸载都是正常调用普通的安装和下载方法,需要注意的是给MyAccessibilityService.INVOKE_TYPE赋值
- 静默安装
MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_INSTALL_APP; String fileName = Environment.getExternalStorageDirectory() + "/test.apk"; Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive"); startActivity(intent);
- 静默卸载
MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_UNINSTALL_APP; Uri packageURI = Uri.parse("package:com.example.test"); Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI); startActivity(uninstallIntent);
- kill进程
MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_KILL_APP; Intent killIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri packageURI = Uri.parse("package:com.example.test"); killIntent.setData(packageURI); startActivity(killIntent);