讓你監控Android手機的通知欄
阿新 • • 發佈:2019-02-12
2016.6.12更新
最最主要的原始碼其實就只有下面我提到的這些了,最核心的功能都在上面了,以及可能碰到的坑。
程式碼已經開源到github,地址:
原文:
有段時間沒寫博了,想著還是要寫點東西,免得生疏了,正好前段時間做了一個抓取通知欄的功能,期間也走了一些彎路,
通過網上查資料,看Android原始碼,最終總算解決了監控通知欄的功能。實現的效果如下:
不過在使用通知欄監控之前,首先要進行設定,要讓手機允許你監控通知欄,畢竟這是很隱私的操作,不然如果沒有這個允許動作,那麼Android手機也太危險了,
包括聊天資訊,短訊息都有可能被監控。設定如下:
在輔助功能這裡,開啟NotificationMonitor服務。
接下來來講一下實現方法:
首先寫一個類繼承AccessibilityService,AccessibilityService輔助服務,可以看官方介紹:
http://developer.android.com/reference/android/accessibilityservice/AccessibilityService.html
這個服務執行在後臺,當有定義的的AccessibilityEvent被觸發時,則會進行相應的回撥函式,通知欄需要使用到的事件是:
AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED
也就是通知欄狀態變化事件。
程式碼如下:
public class NeNotificationService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { //判斷輔助服務觸發的事件是否是通知欄改變事件 if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) { //獲取Parcelable物件 Parcelable data = event.getParcelableData(); //判斷是否是Notification物件 if (data instanceof Notification) { Notification notification = (Notification) data; Intent intent = new Intent(); intent.putExtra("NotifyData", notification); intent.putExtra("packageName", event.getPackageName()); intent.setAction(".NeNotificationService"); //進行處理解析通知欄內容的函式 MainActivity.notifyReceive((String)event.getPackageName(), notification); }else { } } /** *Service被啟動的時候會呼叫這個API */ @Override protected void onServiceConnected() { //設定關心的事件型別 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; info.notificationTimeout = 100;//兩個相同事件的超時時間間隔 setServiceInfo(info); } }
這個服務類在使用之前肯定是要先被啟動的,啟動可以放在MainActivity的某個按鈕點選時:
//在MainActivity.onCreate裡初始化
Intent upservice = new Intent(this, NeNotificationService.class);
//按鈕按下時更新或啟動服務
accesscStartNo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateServiceStatus(true);
}
});
//這裡防止多次啟動服務,所以先判斷服務是否在執行中
private void updateServiceStatus(boolean start)
{
boolean bRunning = util.isServiceRunning(this, "com.nis.bcreceiver.NeNotificationService");
//沒有Running則啟動
if (start && !bRunning) {
this.startService(upservice);
} else if(!start && bRunning) {
this.stopService(upservice);
}
}
//另外需要在AndroidManifest.xml檔案中配置
<service android:name="com.nis.bcreceiver.NeNotificationService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:label="NotificationMonitor"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibilityservice" />
</service>
這樣我們基本完成了Notification的監控和抓取,至於如果你想解析出什麼資料,就可以處理這個
notification變數。通過多個程式的測試,發現notification裡比較有用的就是contentView,這是一個直接顯示在
</pre></p><p>介面上的View,我們只要解析它就可以獲取展示的View的標題及文字內容,處理程式碼如下:</p><p><pre name="code" class="java"> private void AnalyzeView(RemoteViews remoteView, String packName) {
try {
//把RemoteView apply後變成當前可以處理的View
View v1 = remoteView.apply(this, rootLayout);
//然後就是列舉處理這個View的內容
EnumGroupViews(v1);
//展示出來
rootLayout.addView(v1);
} catch (Exception e) {
AppLog.e("addToUi excep",e);
}
}
private void EnumGroupViews(View v1)
{
if(v1 instanceof ViewGroup)
{
ViewGroup lav = (ViewGroup)v1;
int lcCnt = lav.getChildCount();
for(int i = 0; i < lcCnt; i++)
{
View c1 = lav.getChildAt(i);
if(c1 instanceof ViewGroup)
EnumGroupViews(c1);//遞迴處理GroupView
else if(c1 instanceof TextView)
{
//TestView則解析裡面文字內容
TextView txt = (TextView)c1;
String str = txt.getText().toString().trim();
if(str.length() > 0)
{
//這裡列印文字內容
}
AppLog.i( "TextView id:"+ txt.getId() + ".text:" + str);
}else
{
AppLog.w("2 other layout:" + c1.toString());
}
}
}
else {
AppLog.w("1 other layout:" + v1.toString());
}
}
通過這個解析,我們基本上完成了從監控、抓取、解析內容的過程。網上也還有其它一些解析處理的方法,大家也可以參考,以上解析remoteView是本人
在檢視其相應原始碼情況下自己琢磨出來的,而且測試了十幾款有推送訊息的應用,都可以正常解析其所有內容。