android非root方式静默安装和卸载

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服务:
    <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>
    其中label是手机辅助功能里代表本应用的名字
    resource内容为:
    <?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" />
    description是对本应用开启辅助功能时的描述

3.开始调用此服务来静默安装和卸载

安装和卸载都是正常调用普通的安装和下载方法,需要注意的是给MyAccessibilityService.INVOKE_TYPE赋值
  1. 静默安装
    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); 

  2. 静默卸载
    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); 

  3. 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);

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值