Android Accessibility(辅助功能) --实现Android应用自动安装、卸载

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

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

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


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


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

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.jack.accessibility"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk  
  8.         android:minSdkVersion="8"  
  9.         android:targetSdkVersion="18" />  
  10.   
  11.     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />  
  12.     <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />  
  13.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
  14.     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  
  15.       
  16.     <application  
  17.         android:allowBackup="true"  
  18.         android:icon="@drawable/ic_launcher"  
  19.         android:label="@string/app_name"  
  20.         android:theme="@style/AppTheme" >  
  21.         <activity  
  22.             android:name="com.jack.accessibility.MainActivity"  
  23.             android:label="@string/app_name" >  
  24.             <intent-filter>  
  25.                 <action android:name="android.intent.action.MAIN" />  
  26.                 <category android:name="android.intent.category.LAUNCHER" />  
  27.             </intent-filter>  
  28.         </activity>  
  29.         <service android:label="@string/acc_service_name" android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">  
  30.             <intent-filter>  
  31.                 <action android:name="android.accessibilityservice.AccessibilityService" />  
  32.             </intent-filter>  
  33.             <meta-data android:name="android.accessibilityservice" android:resource="@xml/phone_accessibility" />  
  34.         </service>  
  35.   
  36.     </application>  
  37.   
  38. </manifest>  

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

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <accessibility-service android:description="@string/accessibility_service_description"  
  3.      android:accessibilityEventTypes="typeAllMask"   
  4.      android:accessibilityFeedbackType="feedbackGeneric"   
  5.      android:notificationTimeout="100"   
  6.      android:accessibilityFlags=""   
  7.      android:canRetrieveWindowContent="true"  
  8.   xmlns:android="http://schemas.android.com/apk/res/android" />  

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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.jack.accessibility;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7.   
  8. import android.net.Uri;  
  9. import android.os.Bundle;  
  10. import android.os.Environment;  
  11. import android.provider.Settings;  
  12. import android.view.View;  
  13. import android.app.Activity;  
  14. import android.content.Intent;  
  15.   
  16. public class MainActivity extends Activity {  
  17.       
  18.     @Override  
  19.     protected void onCreate(Bundle savedInstanceState) {  
  20.         super.onCreate(savedInstanceState);  
  21.         setContentView(R.layout.activity_main);  
  22.         this.findViewById(R.id.activeButton).setOnClickListener(new View.OnClickListener() {  
  23.               
  24.             @Override  
  25.             public void onClick(View arg0) {  
  26.                 // TODO Auto-generated method stub  
  27.                 Intent killIntent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);  
  28.                 startActivity(killIntent);  
  29.             }  
  30.         });  
  31.           
  32.         this.findViewById(R.id.installButton).setOnClickListener(new View.OnClickListener() {  
  33.               
  34.             @Override  
  35.             public void onClick(View arg0) {  
  36.                 // TODO Auto-generated method stub  
  37.                 MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_INSTALL_APP;  
  38.                 String fileName = Environment.getExternalStorageDirectory() + "/test.apk";   
  39.                 File installFile = new File(fileName);  
  40.                 if(installFile.exists()){  
  41.                     installFile.delete();  
  42.                 }  
  43.                 try {  
  44.                     installFile.createNewFile();  
  45.                     FileOutputStream out = new FileOutputStream(installFile);  
  46.                     byte[] buffer = new byte[512];  
  47.                     InputStream in = MainActivity.this.getAssets().open("test.apk");  
  48.                     int count;  
  49.                     while((count= in.read(buffer))!=-1){  
  50.                         out.write(buffer, 0, count);  
  51.                     }  
  52.                     in.close();  
  53.                     out.close();  
  54.                 } catch (IOException e) {  
  55.                     // TODO Auto-generated catch block  
  56.                     e.printStackTrace();  
  57.                 }  
  58.                 Intent intent = new Intent(Intent.ACTION_VIEW);   
  59.                 intent.setDataAndType(Uri.fromFile(new File(fileName)), "application/vnd.android.package-archive");   
  60.                 startActivity(intent);  
  61.                   
  62.             }  
  63.         });  
  64.         this.findViewById(R.id.uninstallButton).setOnClickListener(new View.OnClickListener() {  
  65.               
  66.             @Override  
  67.             public void onClick(View arg0) {  
  68.                 // TODO Auto-generated method stub  
  69.                 MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_UNINSTALL_APP;  
  70.                 Uri packageURI = Uri.parse("package:com.example.test");   
  71.                 Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);   
  72.                 startActivity(uninstallIntent);   
  73.             }  
  74.         });  
  75.         this.findViewById(R.id.killAppButton).setOnClickListener(new View.OnClickListener() {  
  76.               
  77.             @Override  
  78.             public void onClick(View arg0) {  
  79.                 // TODO Auto-generated method stub  
  80.                 MyAccessibilityService.INVOKE_TYPE = MyAccessibilityService.TYPE_KILL_APP;  
  81.                 Intent killIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);  
  82.                 Uri packageURI = Uri.parse("package:com.example.test");   
  83.                 killIntent.setData(packageURI);  
  84.                 startActivity(killIntent);  
  85.             }  
  86.         });  
  87.     }  
  88. }  


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

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.jack.accessibility;  
  2.   
  3. import java.util.List;  
  4.   
  5. import android.accessibilityservice.AccessibilityService;  
  6. import android.annotation.SuppressLint;  
  7. import android.util.Log;  
  8. import android.view.KeyEvent;  
  9. import android.view.accessibility.AccessibilityEvent;  
  10. import android.view.accessibility.AccessibilityNodeInfo;  
  11.   
  12. @SuppressLint("NewApi")  
  13. public class MyAccessibilityService extends AccessibilityService {  
  14.   
  15.     public static int INVOKE_TYPE = 0;  
  16.     public static final int TYPE_KILL_APP = 1;  
  17.     public static final int TYPE_INSTALL_APP = 2;  
  18.     public static final int TYPE_UNINSTALL_APP = 3;  
  19.       
  20.     public static void reset(){  
  21.         INVOKE_TYPE = 0;  
  22.     }  
  23.   
  24.     @Override  
  25.     public void onAccessibilityEvent(AccessibilityEvent event) {  
  26.         // TODO Auto-generated method stub  
  27.         this.processAccessibilityEnvent(event);  
  28.     }  
  29.   
  30.     private void processAccessibilityEnvent(AccessibilityEvent event) {  
  31.   
  32.         Log.d("test", event.eventTypeToString(event.getEventType()));  
  33.         if (event.getSource() == null) {  
  34.             Log.d("test""the source = null");  
  35.         } else {  
  36.             Log.d("test""event = " + event.toString());  
  37.             switch (INVOKE_TYPE) {  
  38.             case TYPE_KILL_APP:  
  39.                 processKillApplication(event);  
  40.                 break;  
  41.             case TYPE_INSTALL_APP:  
  42.                 processinstallApplication(event);  
  43.                 break;  
  44.             case TYPE_UNINSTALL_APP:  
  45.                 processUninstallApplication(event);  
  46.                 break;                
  47.             default:  
  48.                 break;  
  49.             }                         
  50.         }  
  51.     }  
  52.   
  53.     @Override  
  54.     protected boolean onKeyEvent(KeyEvent event) {  
  55.         // TODO Auto-generated method stub  
  56.         return true;  
  57.   
  58.     }  
  59.   
  60.     @Override  
  61.     public void onInterrupt() {  
  62.         // TODO Auto-generated method stub  
  63.   
  64.     }  
  65.   
  66.     private void processUninstallApplication(AccessibilityEvent event) {  
  67.           
  68.         if (event.getSource() != null) {  
  69.             if (event.getPackageName().equals("com.android.packageinstaller")) {  
  70.                 List<AccessibilityNodeInfo> ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确定");  
  71.                 if (ok_nodes!=null && !ok_nodes.isEmpty()) {  
  72.                     AccessibilityNodeInfo node;  
  73.                     for(int i=0; i<ok_nodes.size(); i++){  
  74.                         node = ok_nodes.get(i);  
  75.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  76.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  77.                         }  
  78.                     }  
  79.   
  80.                 }  
  81.             }  
  82.         }  
  83.   
  84.     }  
  85.   
  86.     private void processinstallApplication(AccessibilityEvent event) {  
  87.           
  88.         if (event.getSource() != null) {  
  89.             if (event.getPackageName().equals("com.android.packageinstaller")) {              
  90.                 List<AccessibilityNodeInfo> unintall_nodes = event.getSource().findAccessibilityNodeInfosByText("安装");  
  91.                 if (unintall_nodes!=null && !unintall_nodes.isEmpty()) {  
  92.                     AccessibilityNodeInfo node;  
  93.                     for(int i=0; i<unintall_nodes.size(); i++){  
  94.                         node = unintall_nodes.get(i);  
  95.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  96.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  97.                         }  
  98.                     }  
  99.                 }  
  100.                   
  101.                 List<AccessibilityNodeInfo> next_nodes = event.getSource().findAccessibilityNodeInfosByText("下一步");  
  102.                 if (next_nodes!=null && !next_nodes.isEmpty()) {  
  103.                     AccessibilityNodeInfo node;  
  104.                     for(int i=0; i<next_nodes.size(); i++){  
  105.                         node = next_nodes.get(i);  
  106.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  107.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  108.                         }  
  109.                     }  
  110.                 }  
  111.                   
  112.                 List<AccessibilityNodeInfo> ok_nodes = event.getSource().findAccessibilityNodeInfosByText("打开");  
  113.                 if (ok_nodes!=null && !ok_nodes.isEmpty()) {  
  114.                     AccessibilityNodeInfo node;  
  115.                     for(int i=0; i<ok_nodes.size(); i++){  
  116.                         node = ok_nodes.get(i);  
  117.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  118.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  119.                         }  
  120.                     }     
  121.                 }  
  122.   
  123.   
  124.             }  
  125.         }  
  126.   
  127.     }  
  128.   
  129.     private void processKillApplication(AccessibilityEvent event) {  
  130.           
  131.         if (event.getSource() != null) {  
  132.             if (event.getPackageName().equals("com.android.settings")) {  
  133.                 List<AccessibilityNodeInfo> stop_nodes = event.getSource().findAccessibilityNodeInfosByText("强行停止");  
  134.                 if (stop_nodes!=null && !stop_nodes.isEmpty()) {  
  135.                     AccessibilityNodeInfo node;  
  136.                     for(int i=0; i<stop_nodes.size(); i++){  
  137.                         node = stop_nodes.get(i);  
  138.                         if (node.getClassName().equals("android.widget.Button")) {  
  139.                             if(node.isEnabled()){  
  140.                                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  141.                             }  
  142.                         }  
  143.                     }  
  144.                 }  
  145.   
  146.                 List<AccessibilityNodeInfo> ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确定");  
  147.                 if (ok_nodes!=null && !ok_nodes.isEmpty()) {  
  148.                     AccessibilityNodeInfo node;  
  149.                     for(int i=0; i<ok_nodes.size(); i++){  
  150.                         node = ok_nodes.get(i);  
  151.                         if (node.getClassName().equals("android.widget.Button")) {  
  152.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  153.                             Log.d("action""click ok");  
  154.                         }  
  155.                     }  
  156.   
  157.                 }  
  158.             }  
  159.         }  
  160.     }  
  161.   
  162. }  


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

转载自:http://blog.csdn.net/androidsecurity/article/details/41890369

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值