对于那些由于视力、听力或其它身体原因导致不能方便使用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-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"/>        <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" />                <category android:name="android.intent.category.LAUNCHER" />            </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" />            </intent-filter>            <meta-data android:name="android.accessibilityservice" android:resource="@xml/phone_accessibility" />        </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" />

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 {    @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);this.findViewById(R.id.activeButton).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubIntent killIntent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);startActivity(killIntent);}});this.findViewById(R.id.installButton).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubMyAccessibilityService.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 blocke.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() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubMyAccessibilityService.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() {@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubMyAccessibilityService.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;}@Overridepublic void onAccessibilityEvent(AccessibilityEvent event) {// TODO Auto-generated method stubthis.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;}}}@Overrideprotected boolean onKeyEvent(KeyEvent event) {// TODO Auto-generated method stubreturn true;}@Overridepublic 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.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");}}}}}}}


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

更多相关文章

  1. Android搜索自动提示功能
  2. Android位图操作
  3. Android 4.0 Launcher2源码分析——Laucher界面元素分解(主布局文
  4. Android背后的设计思想——功能共享机制
  5. 【Android 内存优化】Android Profiler 工具常用功能 ( 监测内存

随机推荐

  1. 在一些页面中使用P和L定向生成PDF文档。
  2. 安装的Moodle字体在其他浏览器中不起作用
  3. TextView显示html样式的文字
  4. 在HTML / PHP联系表单上出现404/405错误(
  5. 急死我了!我以前用DREAMWEAVER编写的HTML
  6. HTML,CSS - 长表的行中断需要修复
  7. 样式通常以相同的组合出现:创建单个类还是
  8. 如何在Java Swing中的JPanel中呈现基本的
  9. 单个元素html上的多个类
  10. 如何使用jQuery在我的网站演示中自动填写