編輯:關於Android編程
許多Android使用者因為各種情況導致他們要以不同的方式與手機交互。這包括了在有些用戶在視力上、身體上、年齡上的問題導致他們不能看清完整的屏幕或者使用觸屏。也包括了無法很好接收到語音信息和提示的聽力能力比較弱的用戶。
Android提供了Accessibility功能和服務來幫助這些用戶更簡單的操作折欸,包括文字轉語音(這個不支持中文),觸覺反饋、手勢操作、軌跡球和手柄操作。
。Accesssibility叫做Android中的鉤子。在Windows中,鉤子的含義就是能夠監聽到一切你想監聽的內容,而Android中的AccessibilityService也可以監聽到我們需要的某些功能。AccessibilityService是一個輔助類,可以監聽我們手機的焦點、窗口變化、按鈕點擊等。實現它的服務需要在手機設置裡->輔助功能在這裡邊找到自己實現的輔助類,然後打開它就可以進行我們一些列的監聽了。
輔助服務的聲明周期只能被系統管理,啟動或者停止這個服務必須由明確的用戶通過啟用或停用設備的設定
AccessiblityService的功能其實就可以概括為兩句話:
- 尋找我們想要的View節點
- 模擬點擊,實現特定的功能
我們知道Android的View體系是一個樹形結構,每一個View就是一個結點,所以我們可以找到指定的結點。那麼我們該如何查找我們想要的結點呢?這裡首先看一下輔助功能AccessibilityService的用法。
我們繼承實現了一個Service,當然service要在AndroidManifest.xml中聲明:
需要注意的地方
1 這個服務需要注明一個權限
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
當然還有一個meta-data聲明,這個聲明是對AccessibilityService的一些配置,我們看一下這個配置文件的內容。
我們以此介紹一下這些常用的配置
android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged"
指定時間的類型,即輔助服務響應的事件。這些事件是在AccessibilityEvent類中定義的。我們看一下這個累的源碼
@Deprecated
public static final int MAX_TEXT_LENGTH = 500;
/**
* Represents the event of clicking on a {@link android.view.View} like
* {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
*/
public static final int TYPE_VIEW_CLICKED = 0x00000001;
/**
* Represents the event of long clicking on a {@link android.view.View} like
* {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc.
*/
public static final int TYPE_VIEW_LONG_CLICKED = 0x00000002;
/**
* Represents the event of selecting an item usually in the context of an
* {@link android.widget.AdapterView}.
*/
public static final int TYPE_VIEW_SELECTED = 0x00000004;
/**
* Represents the event of setting input focus of a {@link android.view.View}.
*/
public static final int TYPE_VIEW_FOCUSED = 0x00000008;
/**
* Represents the event of changing the text of an {@link android.widget.EditText}.
*/
public static final int TYPE_VIEW_TEXT_CHANGED = 0x00000010;
/**
* Represents the event of opening a {@link android.widget.PopupWindow},
* {@link android.view.Menu}, {@link android.app.Dialog}, etc.
*/
public static final int TYPE_WINDOW_STATE_CHANGED = 0x00000020;
/**
* Represents the event showing a {@link android.app.Notification}.
*/
public static final int TYPE_NOTIFICATION_STATE_CHANGED = 0x00000040;
/**
* Represents the event of a hover enter over a {@link android.view.View}.
*/
public static final int TYPE_VIEW_HOVER_ENTER = 0x00000080;
/**
* Represents the event of a hover exit over a {@link android.view.View}.
*/
public static final int TYPE_VIEW_HOVER_EXIT = 0x00000100;
/**
* Represents the event of starting a touch exploration gesture.
*/
public static final int TYPE_TOUCH_EXPLORATION_GESTURE_START = 0x00000200;
/**
* Represents the event of ending a touch exploration gesture.
*/
public static final int TYPE_TOUCH_EXPLORATION_GESTURE_END = 0x00000400;
/**
* Represents the event of changing the content of a window and more
* specifically the sub-tree rooted at the event's source.
*/
public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
/**
* Represents the event of scrolling a view.
*/
public static final int TYPE_VIEW_SCROLLED = 0x00001000;
/**
* Represents the event of changing the selection in an {@link android.widget.EditText}.
*/
public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
/**
* Represents the event of an application making an announcement.
*/
public static final int TYPE_ANNOUNCEMENT = 0x00004000;
/**
* Represents the event of gaining accessibility focus.
*/
public static final int TYPE_VIEW_ACCESSIBILITY_FOCUSED = 0x00008000;
/**
* Represents the event of clearing accessibility focus.
*/
public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
/**
* Represents the event of traversing the text of a view at a given movement granularity.
*/
public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
/**
* Represents the event of beginning gesture detection.
*/
public static final int TYPE_GESTURE_DETECTION_START = 0x00040000;
/**
* Represents the event of ending gesture detection.
*/
public static final int TYPE_GESTURE_DETECTION_END = 0x00080000;
/**
* Represents the event of the user starting to touch the screen.
*/
public static final int TYPE_TOUCH_INTERACTION_START = 0x00100000;
/**
* Represents the event of the user ending to touch the screen.
*/
public static final int TYPE_TOUCH_INTERACTION_END = 0x00200000;
/**
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
* The type of change is not defined.
*/
public static final int CONTENT_CHANGE_TYPE_UNDEFINED = 0x00000000;
/**
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
* A node in the subtree rooted at the source node was added or removed.
*/
public static final int CONTENT_CHANGE_TYPE_SUBTREE = 0x00000001;
/**
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
* The node's text changed.
*/
public static final int CONTENT_CHANGE_TYPE_TEXT = 0x00000002;
/**
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
* The node's content description changed.
*/
public static final int CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION = 0x00000004;
比如在剛在的配置中,我們選擇響應通知欄事件和窗口狀態改變事件。如果要響應所有的類型,可以這樣設置
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackSpoken"
設置回饋給用戶的方式,有語音播出和振動。可以配置一些TTS引擎,讓它實現發音。
android:notificationTimeout="100"
響應時間的設置就不用多說了
android:packageNames="com.example.android.apis"
可以指定響應某個應用的事件,這裡因為要響應所有應用的事件,所以不填,默認就是響應所有應用的事件。比如我們寫一個微信搶紅包的輔助程序,就可以在這裡填寫微信的包名,便可以監聽微信產生的事件了。
比如我們要監聽通知欄消息的事件
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType();
switch (eventType) {
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
//.......
}
}
系統提供了兩哥方法來讓我們查找想要的結點
- 通過結點View的Text內容來查找
findAccessibilityNodeInfosByText("查找的內容")
返回的結果是List,我們需要for循環來處理
- 通過結點View在布局中的id名稱來查找
findAccessibilityNodeInfosByViewId("@id/xxx");
我們可以DDMS工具裡的Dump View Hierarchy For UI Automator 來分析一個UI的結構
雖然返回值也是 List, 但其實結果只有一個
我們找到我們想要的View結點之後,調用方法模擬點擊:
performAction(AccessibilityNodeInfo.ACTION_CLICK)
調用這個方法即可,當然這裡的參數就是事件的名稱和操作, 這裡是模擬點擊事件,我們當然可以去模擬滾動事件、長按事件等。
我們看一下AccessibilityNodeInfo的介紹, 官方介紹是以這樣
This class represents a node of the window content as well as actions that can be requested from its source.
這個類封裝了一些窗口的結點和這個結點的動作。
首先,先回想一下微信紅包的領取流程。
- 1.通知欄出現微信紅包的消息
- 2.點擊通知欄,進入領取紅包界面
- 3.點擊領取紅包,領取成功後,進入拆紅包界面
- 4.拆紅包,顯示獲得金額
- 5.等待下一個紅包
其實看一下手機360手機助手就可以看到我們能用AccService實現哪些功能
- 1 靜默安裝
如果有了輔助功能,我們就可以很容易實現靜默安裝,如愛奇藝的靜默安裝。
- 2 關閉後台進程
- 3 後台卸載
- 4 Android自動化測試
在平時開發過程中,MD5加密是一個比較常用的算法,最常見的使用場景就是在帳號注冊時,用戶輸入的密碼經md5加密後,傳輸至服務器保存起來。雖然md5加密經常用,但是md5的
前言Android應用中的APK安全性一直遭人诟病,市面上充斥著各種被破解或者漢化的應用,破解者可以非常簡單的通過破解工具就能對一個APK進行反編譯、破解、漢化等等,這樣
在前文中,我們分析了Android應用程序窗口的運行上下文環境的創建過程。由此可知,每一個Activity組件都有一
在Android應用程序框架中,Activity和Service類都繼承了ContextWrapper類,因此,我們可以在Activity或者Service的子類中調用r