天天看點

Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止

對于那些由于視力、聽力或其它身體原因導緻不能友善使用Android智能手機的使用者,Android提供了Accessibility功能和服務幫助這些使用者更加簡單地操作裝置,包括文字轉語音、觸覺回報、手勢操作、軌迹球和搖桿操作。開發者可以搭建自己的Accessibility服務,這可以加強可用性,例如聲音提示,實體回報,和其他可選的操作模式。

     随着Android版本的不斷更新,Android Accessibility功能也越來越強大,Android 4.0版本以前,系統輔助服務功能比較單一,僅僅能過單向擷取視窗元素資訊,比如擷取輸入框使用者輸入内容。到Android 4.1版本以後,系統輔助服務增加了與視窗元素的雙向互動,此時可以通過輔助功能服務操作視窗元素,比如點選按鈕等。

    由于系統輔助服務能夠實時擷取您目前操作應用的視窗元素資訊,這有可能給你帶來隐私資訊的洩露風險,比如擷取非密碼輸入框的輸入内容等。同時通過輔助功能也可以模拟使用者自動化點選應用内元素,也會帶來一定的安全風險。

    本文實作了一種通過系統輔助服務完成應用的自動安裝、解除安裝、強行停止的功能。

1、AndroidManifest.xml檔案配置自己實作的MyAccessibilityService服務。

[html]  view plain  copy  

Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止
Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止
  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.     <uses-sdk  
  7.         android:minSdkVersion="8"  
  8.         android:targetSdkVersion="18" />  
  9.     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />  
  10.     <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />  
  11.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
  12.     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  
  13.     <application  
  14.         android:allowBackup="true"  
  15.         android:icon="@drawable/ic_launcher"  
  16.         android:label="@string/app_name"  
  17.         android:theme="@style/AppTheme" >  
  18.         <activity  
  19.             android:name="com.jack.accessibility.MainActivity"  
  20.             android:label="@string/app_name" >  
  21.             <intent-filter>  
  22.                 <action android:name="android.intent.action.MAIN" />  
  23.                 <category android:name="android.intent.category.LAUNCHER" />  
  24.             </intent-filter>  
  25.         </activity>  
  26.         <service android:label="@string/acc_service_name" android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">  
  27.             <intent-filter>  
  28.                 <action android:name="android.accessibilityservice.AccessibilityService" />  
  29.             </intent-filter>  
  30.             <meta-data android:name="android.accessibilityservice" android:resource="@xml/phone_accessibility" />  
  31.         </service>  
  32.     </application>  
  33. </manifest>  

2、在res/xml/phone_accessibility.xml配置相應的參數資訊。

[html]  view plain  copy  

Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止
Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止
  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  

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

4、MyAccessibilityService中通過自動化點選實作應用安裝、解除安裝、強行停止功能。

[java]  view plain  copy  

Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止
Android Accessibility(輔助功能) --實作Android應用自動安裝、解除安裝、強行停止
  1. package com.jack.accessibility;  
  2. import java.util.List;  
  3. import android.accessibilityservice.AccessibilityService;  
  4. import android.annotation.SuppressLint;  
  5. import android.util.Log;  
  6. import android.view.KeyEvent;  
  7. import android.view.accessibility.AccessibilityEvent;  
  8. import android.view.accessibility.AccessibilityNodeInfo;  
  9. @SuppressLint("NewApi")  
  10. public class MyAccessibilityService extends AccessibilityService {  
  11.     public static int INVOKE_TYPE = 0;  
  12.     public static final int TYPE_KILL_APP = 1;  
  13.     public static final int TYPE_INSTALL_APP = 2;  
  14.     public static final int TYPE_UNINSTALL_APP = 3;  
  15.     public static void reset(){  
  16.         INVOKE_TYPE = 0;  
  17.     }  
  18.     @Override  
  19.     public void onAccessibilityEvent(AccessibilityEvent event) {  
  20.         // TODO Auto-generated method stub  
  21.         this.processAccessibilityEnvent(event);  
  22.     }  
  23.     private void processAccessibilityEnvent(AccessibilityEvent event) {  
  24.         Log.d("test", event.eventTypeToString(event.getEventType()));  
  25.         if (event.getSource() == null) {  
  26.             Log.d("test", "the source = null");  
  27.         } else {  
  28.             Log.d("test", "event = " + event.toString());  
  29.             switch (INVOKE_TYPE) {  
  30.             case TYPE_KILL_APP:  
  31.                 processKillApplication(event);  
  32.                 break;  
  33.             case TYPE_INSTALL_APP:  
  34.                 processinstallApplication(event);  
  35.                 break;  
  36.             case TYPE_UNINSTALL_APP:  
  37.                 processUninstallApplication(event);  
  38.                 break;                
  39.             default:  
  40.                 break;  
  41.             }                         
  42.         }  
  43.     }  
  44.     @Override  
  45.     protected boolean onKeyEvent(KeyEvent event) {  
  46.         // TODO Auto-generated method stub  
  47.         return true;  
  48.     }  
  49.     @Override  
  50.     public void onInterrupt() {  
  51.         // TODO Auto-generated method stub  
  52.     }  
  53.     private void processUninstallApplication(AccessibilityEvent event) {  
  54.         if (event.getSource() != null) {  
  55.             if (event.getPackageName().equals("com.android.packageinstaller")) {  
  56.                 List<AccessibilityNodeInfo> ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确定");  
  57.                 if (ok_nodes!=null && !ok_nodes.isEmpty()) {  
  58.                     AccessibilityNodeInfo node;  
  59.                     for(int i=0; i<ok_nodes.size(); i++){  
  60.                         node = ok_nodes.get(i);  
  61.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  62.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  63.                         }  
  64.                     }  
  65.                 }  
  66.             }  
  67.         }  
  68.     }  
  69.     private void processinstallApplication(AccessibilityEvent event) {  
  70.         if (event.getSource() != null) {  
  71.             if (event.getPackageName().equals("com.android.packageinstaller")) {              
  72.                 List<AccessibilityNodeInfo> unintall_nodes = event.getSource().findAccessibilityNodeInfosByText("安裝");  
  73.                 if (unintall_nodes!=null && !unintall_nodes.isEmpty()) {  
  74.                     AccessibilityNodeInfo node;  
  75.                     for(int i=0; i<unintall_nodes.size(); i++){  
  76.                         node = unintall_nodes.get(i);  
  77.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  78.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  79.                         }  
  80.                     }  
  81.                 }  
  82.                 List<AccessibilityNodeInfo> next_nodes = event.getSource().findAccessibilityNodeInfosByText("下一步");  
  83.                 if (next_nodes!=null && !next_nodes.isEmpty()) {  
  84.                     AccessibilityNodeInfo node;  
  85.                     for(int i=0; i<next_nodes.size(); i++){  
  86.                         node = next_nodes.get(i);  
  87.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  88.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  89.                         }  
  90.                     }  
  91.                 }  
  92.                 List<AccessibilityNodeInfo> ok_nodes = event.getSource().findAccessibilityNodeInfosByText("打開");  
  93.                 if (ok_nodes!=null && !ok_nodes.isEmpty()) {  
  94.                     AccessibilityNodeInfo node;  
  95.                     for(int i=0; i<ok_nodes.size(); i++){  
  96.                         node = ok_nodes.get(i);  
  97.                         if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) {  
  98.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  99.                         }  
  100.                     }     
  101.                 }  
  102.             }  
  103.         }  
  104.     }  
  105.     private void processKillApplication(AccessibilityEvent event) {  
  106.         if (event.getSource() != null) {  
  107.             if (event.getPackageName().equals("com.android.settings")) {  
  108.                 List<AccessibilityNodeInfo> stop_nodes = event.getSource().findAccessibilityNodeInfosByText("強行停止");  
  109.                 if (stop_nodes!=null && !stop_nodes.isEmpty()) {  
  110.                     AccessibilityNodeInfo node;  
  111.                     for(int i=0; i<stop_nodes.size(); i++){  
  112.                         node = stop_nodes.get(i);  
  113.                         if (node.getClassName().equals("android.widget.Button")) {  
  114.                             if(node.isEnabled()){  
  115.                                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  116.                             }  
  117.                         }  
  118.                     }  
  119.                 }  
  120.                 List<AccessibilityNodeInfo> ok_nodes = event.getSource().findAccessibilityNodeInfosByText("确定");  
  121.                 if (ok_nodes!=null && !ok_nodes.isEmpty()) {  
  122.                     AccessibilityNodeInfo node;  
  123.                     for(int i=0; i<ok_nodes.size(); i++){  
  124.                         node = ok_nodes.get(i);  
  125.                         if (node.getClassName().equals("android.widget.Button")) {  
  126.                             node.performAction(AccessibilityNodeInfo.ACTION_CLICK);  
  127.                             Log.d("action", "click ok");  
  128.                         }  
  129.                     }  
  130.                 }  
  131.             }  
  132.         }  
  133.     }  
  134. }  

完整DEMO下載下傳位址: http://download.csdn.net/detail/jiazhijun/8251277

繼續閱讀