Heim  >  Artikel  >  Datenbank  >  Android Accessibility(辅助功能)

Android Accessibility(辅助功能)

WBOY
WBOYOriginal
2016-06-07 15:36:391284Durchsuche

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

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

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

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


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


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

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jack.accessibility" android:versioncode="1" android:versionname="1.0">

    <uses-sdk android:minsdkversion="8" android:targetsdkversion="18"></uses-sdk>

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"></uses-permission>
    <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
    
    <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:name="com.jack.accessibility.MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"></action>
                <category android:name="android.intent.category.LAUNCHER"></category>
            </intent-filter>
        </activity>
        <service android:label="@string/acc_service_name" android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService"></action>
            </intent-filter>
            <meta-data android:name="android.accessibilityservice" android:resource="@xml/phone_accessibility"></meta-data>
        </service>

    </application>

</manifest>

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

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service android:description="@string/accessibility_service_description" android:accessibilityeventtypes="typeAllMask" android:accessibilityfeedbacktype="feedbackGeneric" android:notificationtimeout="100" android:accessibilityflags="" android:canretrievewindowcontent="true" xmlns:android="http://schemas.android.com/apk/res/android"></accessibility-service>

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<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.isenabled node.performaction private void processinstallapplication event null list> 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.isenabled node.performaction list> 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.isenabled node.performaction list> 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.isenabled node.performaction private void processkillapplication event null list> 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.performaction list> 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.performaction log.d ok><p><br></p>完整DEMO下载地址:http://download.csdn.net/detail/jiazhijun/8251277<br>


</ok_nodes.size></stop_nodes.size></ok_nodes.size></next_nodes.size></unintall_nodes.size></ok_nodes.size></accessibilitynodeinfo>
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn