Android Framework代码屏蔽未接来电振动及声音通知
文章目录
- 需求
- 发广播清除的方式
- 改Framework屏蔽未接来电通知的方法
- 未接来电通知代码定位
- 屏蔽未接来电通知Framework代码修改
需求
有未接来电时,安卓设备开机会有声音或振动通知,如果不看这个通知,每次启动手机/设备都会再通知,想屏蔽这个通知,通过修改framework代码来实现。
有一些手机可以在设置中配置未接来电的通知,但有些手机是没有的,这种就需要改代码了
发广播清除的方式
可以使用广播清除未接来电通知
权限要求:需要具有android.permission.CLEAR_APP_USER_DATA权限,这个权限一般只有系统应用或者具有特殊权限的应用才能拥有。普通应用通常无法直接获取此权限,这是为了防止恶意应用随意清除用户的重要数据。
public class MissedCallsActivity extends Activity {public void clearMissedCalls() {Intent intent = new Intent("android.intent.action.ACTION_CLEAR_MISSED_CALLS");sendBroadcast(intent);// 同时可能还会更新界面显示,清除本地未接来电记录等操作updateUI();clearLocalMissedCallsRecords();}
}
试过直接用adb指令发送广播
adb shell am broadcast -a com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS
实测Android11直接发广播会报错,如下:
W Permission Denial: broadcasting Intent { act=com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS flg=0x400010 } from null (pid=4202, uid=2000) is not exported from uid 1000 due to receiver com.android.server.telecom/.components.TelecomBroadcastReceiver
2025-01-09 15:47:34.933 1004-1445 PowerController.BgClean system_server D saveShellStartedApp: com.android.server.telecom uid:1000
2025-01-09 15:47:34.933 1004-1054 BroadcastQueue system_server D Skipping delivery of ordered [background] BroadcastRecord{9ac5fb5 u0 com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS} for reason described above
就算是有root,通过adb指令发送广播清除也不行
Background execution not allowed: receiving Intent { act=com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS
改Framework屏蔽未接来电通知的方法
也可以直接修改Android SDK代码来实现
未接来电通知代码定位
- 给一张电话卡打电话,电话卡不插,会形成未接来电
- 电话卡插入Android设备中,设备会生成未接来电的通知(声音、振动)
- 查看logcat
enqueueNotificationInternal: pkg=com.android.dialer id=1 notification=Notification(channel=phone_missed_call shortcut=null contentView=null vibrate=default sound=default defaults=0x3 flags=0x219 color=0xff2a56c6 groupKey=MissedCallGroup vis=PRIVATE publicVersion=Notification(channel=null shortcut=null contentView=null vibrate=default sound=null defaults=0x2 flags=0x18 color=0xff2a56c6 groupKey=MissedCallGroup vis=PRIVATE))
onNotificationPosted: StatusBarNotification(pkg=com.android.dialer user=UserHandle{0} id=1 tag=GroupSummary_MissedCall key=0|com.android.dialer|1|GroupSummary_MissedCall|10127: Notification(channel=phone_missed_call shortcut=null contentView=null vibrate=default sound=default defaults=0x3 flags=0x219 color=0xff2a56c6 groupKey=MissedCallGroup vis=PRIVATE publicVersion=Notification(channel=null shortcut=null contentView=null vibrate=default sound=null defaults=0x2 flags=0x18 color=0xff2a56c6 groupKey=MissedCallGroup vis=PRIVATE)))
packageName:com.android.dialer has Notification:(Notification(channel=phone_missed_call shortcut=null contentView=null vibrate=default sound=default defaults=0x3 flags=0x219 color=0xff2a56c6 groupKey=MissedCallGroup vis=PRIVATE publicVersion=Notification(channel=null shortcut=null contentView=null vibrate=default sound=null defaults=0x2 flags=0x18 color=0xff2a56c6 groupKey=MissedCallGroup vis=PRIVATE)))
- 从打印推断出发出通知的应用包名是com.android.dialer,通知channel=phone_missed_call
- 定位到这个包在framework sdk中的位置,并搜索其目录中的文件内容phone_missed_call
比如
cd vendor/sprd/platform/packages/apps/SprdDialer/
grep -nr "phone_missed_call"
得到以下输出
java/com/android/dialer/notification/NotificationChannelId.java:38: String MISSED_CALL = "phone_missed_call";
NotificationChannelId.java代码如下
/** Centralized source of all notification channels used by Dialer. */
@Retention(RetentionPolicy.SOURCE)
@StringDef({NotificationChannelId.INCOMING_CALL,NotificationChannelId.ONGOING_CALL,NotificationChannelId.MISSED_CALL,NotificationChannelId.DEFAULT,
})
public @interface NotificationChannelId {// This value is white listed in the system.// See /vendor/google/nexus_overlay/common/frameworks/base/core/res/res/values/config.xmlString INCOMING_CALL = "phone_incoming_call";String ONGOING_CALL = "phone_ongoing_call";String MISSED_CALL = "phone_missed_call";String DEFAULT = "phone_default";
}
通过NotificationChannelId.MISSED_CALL定位到创建它的代码java/com/android/dialer/app/calllog/MissedCallNotifier.java
private Notification.Builder createNotificationBuilder(@NonNull NewCall call) {Builder builder =createNotificationBuilder().setWhen(call.dateMs).setDeleteIntent(CallLogNotificationsService.createCancelSingleMissedCallPendingIntent(context, call.callsUri)).setContentIntent(createCallLogPendingIntent(call.callsUri));if (BuildCompat.isAtLeastO()) {builder.setChannelId(NotificationChannelId.MISSED_CALL);}return builder;}
屏蔽未接来电通知Framework代码修改
不同芯片厂可能改法不一样,这里以展锐的代码为例,实测过Android11与12。
是把未接来电的通知改成不发出
patch如下:
diff --git a/vendor/sprd/platform/packages/apps/SprdDialer/java/com/android/dialer/app/calllog/MissedCallNotifier.java b/vendor/sprd/platform/packages/apps/SprdDialer/java/com/android/dialer/app/calllog/MissedCallNotifier.java
index 40184955e8..2ed1069a6b 100644
--- a/vendor/sprd/platform/packages/apps/SprdDialer/java/com/android/dialer/app/calllog/MissedCallNotifier.java
+++ b/vendor/sprd/platform/packages/apps/SprdDialer/java/com/android/dialer/app/calllog/MissedCallNotifier.java
@@ -99,6 +99,7 @@ public class MissedCallNotifier implements Worker<Bundle, Void> {@Nullable@Overridepublic Void doInBackground(@Nullable Bundle input) throws Throwable {
+ /*int count = 0;String number = "";String subText = "";
@@ -108,6 +109,7 @@ public class MissedCallNotifier implements Worker<Bundle, Void> {subText = input.getString(MissedCallNotificationReceiver.MAIN_VICE_INFO);}updateMissedCallNotification(count, number, subText);
+ *//* @} */return null;}
就是把updateMissedCallNotification注释掉,改后的源码如下:
@Nullable@Overridepublic Void doInBackground(@Nullable Bundle input) throws Throwable {/*禁止未接电话通知int count = 0;String number = "";String subText = "";if (input != null) {count = input.getInt(MissedCallNotificationReceiver.COUNT);number = input.getString(MissedCallNotificationReceiver.PHONE_NUMBER);subText = input.getString(MissedCallNotificationReceiver.MAIN_VICE_INFO);}updateMissedCallNotification(count, number, subText);*//* @} */return null;}
作者:帅得不敢出门