當我們不希望某一應用的通知在通知欄上提示時,我們可以通過xposed來實作攔截它的操作。以支付寶為例,當支付寶切換到背景時,資訊會以通知欄的形式顯示。若要攔截它,大緻有兩個思路來實作:1、反編譯支付寶代碼,将相關代碼hook掉。然而這個工程對我等小碼仔來說,太難實作。2、攔截系統所有的通知資訊,對其進行過濾,當資訊是來自我們想要攔截的應用時,hook掉它。本文記錄一下對第二種方法的簡單實作。
基于面向google(baidu)程式設計,這裡決定hook NotificationManager中notify方法,源碼如下:
/**
* Post a notification to be shown in the status bar. If a notification with
* the same tag and id has already been posted by your application and has not yet been
* canceled, it will be replaced by the updated information.
*
* @param tag A string identifier for this notification. May be {@code null}.
* @param id An identifier for this notification. The pair (tag, id) must be unique
* within your application.
* @param notification A {@link Notification} object describing what to
* show the user. Must not be null.
*/
public void notify(String tag, int id, Notification notification)
{
notifyAsUser(tag, id, notification, new UserHandle(UserHandle.myUserId()));
}
notify方法的三個入參,其中notification就是要在通知欄上顯示的資訊。代碼如下(測試時使用QQ來測試,是以注釋中有QQ的包名):
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.eg.android.AlipayGphone")
&& !lpparam.processName.equals("com.eg.android.AlipayGphone"))
return;
if (lpparam.packageName.equals("com.eg.android.AlipayGphone")) {
// if (!lpparam.packageName.equals("com.tencent.mobileqq")
// && !lpparam.processName.equals("com.tencent.mobileqq"))
// return;
// if (lpparam.packageName.equals("com.tencent.mobileqq")) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
XposedHelpers.findAndHookMethod("android.app.NotificationManager"
, lpparam.classLoader, "notify"
, String.class, int.class, Notification.class
, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("methodHookParam.args: " + Arrays.toString(param.args));
//通過param拿到第三個入參notification對象
Notification notification = (Notification) param.args[2];
//獲得包名
String aPackage = notification.contentView.getPackage();
String title = "--";
String text = "--";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Bundle bundle = notification.extras;
title = (String) bundle.get("android.title");
text = (String) bundle.get("android.text");
}
// if ("com.tencent.mobileqq".equals(aPackage)) {
if ("com.eg.android.AlipayGphone".equals(aPackage)
&& title.equals("支付寶消息") &&
text.endsWith("已成功向你轉了1筆錢")) {
param.setResult(null);
return;
}
super.beforeHookedMethod(param);
}
});
}
}
上面代碼實作的是攔截支付寶的到賬通知(支付寶還會正常到賬,打開支付寶後也會有到賬消息,隻是攔截了通知欄的提示不影響正常功能),通過notification.extra可以獲得要顯示在通知欄的資訊内容。
Bundle[{android.title=leon, android.subText=null, android.showChronometer=false, android.icon=2130837513,
android.text=leon:九分風好 大, android.progress=0, android.progressMax=0,
android.rebuild.contentViewActionCount=41, android.showWhen=true,
android.rebuild.applicationInfo=ApplicationInfo {1a3b2b0 com.eg.android.AlipayGphone},
[email protected], android.infoText=null, android.originatingUserId=0,
android.progressIndeterminate=false}]
可以看到這是一個bundle對象,其中android.title是通知欄顯示的标題,android.text是通知欄顯示的内容。這條是支付寶接收到使用者發送消息時的内容,下面看一下接收到轉賬提示時的内容。
Bundle[{android.title=支付寶消息, android.subText=null, android.showChronometer=false, android.icon=2130837513,
android.text=leon已成功向你轉了1筆錢, android.progress=0, android.progressMax=0,
android.rebuild.contentViewActionCount=41, android.showWhen=true,
android.rebuild.applicationInfo=ApplicationInfo{1a3b2b0 com.eg.android.AlipayGphone},
android.larg[email protected], android.infoText=null,
android.originatingUserId=0,android.progressIndeterminate=false}]
可以看到當資訊來自支付寶轉賬時,android.title的内容固定為支付寶消息,android.text的内容為XXX已成功想你轉了1筆錢,其餘内容全部相同。我們就可以考慮判斷這兩個字段的值,來對到賬消息進行攔截的同時不影響正常功能的使用。代碼在上面,很簡單的實作了對支付寶到賬資訊的攔截,若有需要對到賬資訊統計的話,可以在統計到賬的次數與轉賬人,但是無法統計到賬金額,畢竟隻是對系統方法進行hook,支付寶也不會把金額資訊給顯示在通知欄中。