欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

Android Accessibility(辅助功能)

程序员文章站 2022-06-10 09:54:43
...

对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Android提供了Accessibility 功能 和服务帮助这些用户更加简单地操作设备,包括文字转语音、触觉反

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

随着Android版本的不断升级,Android Accessibility功能也越来越强大,Android 4.0版本以前,系统辅助服务功能比较单一,仅仅能过单向获取窗口元素信息,比如获取输入框用户输入内容。到Android 4.1版本以后,系统辅助服务增加了与窗口元素的双向交互,此时可以通过辅助功能服务操作窗口元素,比如点击按钮等。

由于系统辅助服务能够实时获取您当前操作应用的窗口元素信息,这有可能给你带来隐私信息的泄露风险,比如获取非密码输入框的输入内容等。同时通过辅助功能也可以模拟用户自动化点击应用内元素,也会带来一定的安全风险。


本文实现了一种通过系统辅助服务完成应用的自动安装、卸载、强行停止的功能


1、AndroidManifest.xml文件配置自己实现的MyAccessibilityService服务。


2、在res/xml/phone_accessibility.xml配置相应的参数信息。


3、MainActivity实现安装、卸载、强行停止动作的发起。

package com.jack.accessibility;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.View;
import android.app.Activity;
import android.content.Intent;

public class MainActivity extends Activity {
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		this.findViewById(R.id.activeButton).setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				Intent killIntent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
				startActivity(killIntent);
			}
		});
		
		this.findViewById(R.id.installButton).setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_INSTALL_APP;
				String fileName = Environment.getExternalStorageDirectory() + "/test.apk"; 
				File installFile = new File(fileName);
				if(installFile.exists()){
					installFile.delete();
				}
				try {
					installFile.createNewFile();
					FileOutputStream out = new FileOutputStream(installFile);
					byte[] buffer = new byte[512];
					InputStream in = MainActivity.this.getAssets().open("test.apk");
					int count;
					while((count= in.read(buffer))!=-1){
						out.write(buffer, 0, count);
					}
					in.close();
					out.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				Intent intent = new Intent(Intent.ACTION_VIEW); 
				intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive"); 
				startActivity(intent);
				
			}
		});
		this.findViewById(R.id.uninstallButton).setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				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); 
			}
		});
		this.findViewById(R.id.killAppButton).setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				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);
			}
		});
	}
}


4、MyAccessibilityService中通过自动化点击实现应用安装、卸载、强行停止功能

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) {
		
		if (event.getSource() != null) {
			if (event.getPackageName().equals("com.android.packageinstaller")) {
				List ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确定");
				if (ok_nodes!=null && !ok_nodes.isEmpty()) {
					AccessibilityNodeInfo node;
					for(int i=0; i unintall_nodes = event.getSource().findAccessibilityNodeInfosByText("安装");
				if (unintall_nodes!=null && !unintall_nodes.isEmpty()) {
					AccessibilityNodeInfo node;
					for(int i=0; i next_nodes = event.getSource().findAccessibilityNodeInfosByText("下一步");
				if (next_nodes!=null && !next_nodes.isEmpty()) {
					AccessibilityNodeInfo node;
					for(int i=0; i ok_nodes = event.getSource().findAccessibilityNodeInfosByText("打开");
				if (ok_nodes!=null && !ok_nodes.isEmpty()) {
					AccessibilityNodeInfo node;
					for(int i=0; i stop_nodes = event.getSource().findAccessibilityNodeInfosByText("强行停止");
				if (stop_nodes!=null && !stop_nodes.isEmpty()) {
					AccessibilityNodeInfo node;
					for(int i=0; i ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确定");
				if (ok_nodes!=null && !ok_nodes.isEmpty()) {
					AccessibilityNodeInfo node;
					for(int i=0; i


完整DEMO下载地址:http://download.csdn.net/detail/jiazhijun/8251277