AndroidAOSP定制之关闭某些app的通知
前言:
最近在做AOSP系统定制时发现gms定制好了后,Google应用商店用不了,提示此设备未获得Play保护机制认证,Google应用和服务无法在此设备上运行,查看官方文档和资料,说是由于Android设备id生成不对引起的,可以通过修改系统属性解决,需求简单描述还是如何默认关闭掉Google Play服务的通知,或者某个app的通知.
1.报错信息如下:
2.解决方法1:
- 源码路径:/frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
- 源码:
- 通过包名判断过滤过需要关闭通知的应用
void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,final int callingPid, final String tag, final int id, final Notification notification,int incomingUserId, boolean postSilently) {if (HwNotificationManagerService.disableNotification()) {return;}if (DBG) {Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id+ " notification=" + notification);}if (pkg == null || notification == null) {throw new IllegalArgumentException("null not allowed: pkg=" + pkg+ " id=" + id + " notification=" + notification);}final int userId = ActivityManager.handleIncomingUser(callingPid,callingUid, incomingUserId, true, false, "enqueueNotification", pkg);final UserHandle user = UserHandle.of(userId);// Can throw a SecurityException if the calling uid doesn't have permission to post// as "pkg"final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId);if (notificationUid == INVALID_UID) {throw new SecurityException("Caller " + opPkg + ":" + callingUid+ " trying to post for invalid pkg " + pkg + " in user " + incomingUserId);}checkRestrictedCategories(pkg, notification);// Fix the notification as best we can.try {fixNotification(notification, pkg, tag, id, userId);} catch (Exception e) {Slog.e(TAG, "Cannot fix notification", e);return;}mUsageStats.registerEnqueuedByApp(pkg);final StatusBarNotification n = new StatusBarNotification(pkg, opPkg, id, tag, notificationUid, callingPid, notification,user, null, mSystemClock.currentTimeMillis());// setup local book-keepingString channelId = notification.getChannelId();if (mIsTelevision && (new Notification.TvExtender(notification)).getChannelId() != null) {channelId = (new Notification.TvExtender(notification)).getChannelId();}String shortcutId = n.getShortcutId();final NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel(pkg, notificationUid, channelId, shortcutId,true /* parent ok */, false /* includeDeleted */);if (channel == null) {final String noChannelStr = "No Channel found for "+ "pkg=" + pkg+ ", channelId=" + channelId+ ", id=" + id+ ", tag=" + tag+ ", opPkg=" + opPkg+ ", callingUid=" + callingUid+ ", userId=" + userId+ ", incomingUserId=" + incomingUserId+ ", notificationUid=" + notificationUid+ ", notification=" + notification;Slog.e(TAG, noChannelStr);boolean appNotificationsOff = mPreferencesHelper.getImportance(pkg, notificationUid)== NotificationManager.IMPORTANCE_NONE;if (!appNotificationsOff) {doChannelWarningToast("Developer warning for package \"" + pkg + "\"\n" +"Failed to post notification on channel \"" + channelId + "\"\n" +"See log for more details");}return;}final NotificationRecord r = new NotificationRecord(getContext(), n, channel);r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));r.setPostSilently(postSilently);r.setFlagBubbleRemoved(false);r.setPkgAllowedAsConvo(mMsgPkgsAllowedAsConvos.contains(pkg));if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {final boolean fgServiceShown = channel.isFgServiceShown();if (((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0|| !fgServiceShown)&& (r.getImportance() == IMPORTANCE_MIN|| r.getImportance() == IMPORTANCE_NONE)) {// Increase the importance of foreground service notifications unless the user had// an opinion otherwise (and the channel hasn't yet shown a fg service).if (TextUtils.isEmpty(channelId)|| NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {r.setSystemImportance(IMPORTANCE_LOW);} else {channel.setImportance(IMPORTANCE_LOW);r.setSystemImportance(IMPORTANCE_LOW);if (!fgServiceShown) {channel.unlockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);channel.setFgServiceShown(true);}mPreferencesHelper.updateNotificationChannel(pkg, notificationUid, channel, false);r.updateNotificationChannel(channel);}} else if (!fgServiceShown && !TextUtils.isEmpty(channelId)&& !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {channel.setFgServiceShown(true);r.updateNotificationChannel(channel);}}ShortcutInfo info = mShortcutHelper != null? mShortcutHelper.getValidShortcutInfo(notification.getShortcutId(), pkg, user): null;if (notification.getShortcutId() != null && info == null) {Slog.w(TAG, "notification " + r.getKey() + " added an invalid shortcut");}r.setShortcutInfo(info);r.setHasSentValidMsg(mPreferencesHelper.hasSentValidMsg(pkg, notificationUid));r.userDemotedAppFromConvoSpace(mPreferencesHelper.hasUserDemotedInvalidMsgApp(pkg, notificationUid));if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r,r.getSbn().getOverrideGroupKey() != null)) {return;}if (info != null) {// Cache the shortcut synchronously after the associated notification is posted in case// the app unpublishes this shortcut immediately after posting the notification. If the// user does not modify the notification settings on this conversation, the shortcut// will be uncached by People Service when all the associated notifications are removed.mShortcutHelper.cacheShortcut(info, user);}// Whitelist pending intents.if (notification.allPendingIntents != null) {final int intentCount = notification.allPendingIntents.size();if (intentCount > 0) {final ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);final long duration = LocalServices.getService(DeviceIdleInternal.class).getNotificationWhitelistDuration();for (int i = 0; i < intentCount; i++) {PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);if (pendingIntent != null) {am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),WHITELIST_TOKEN, duration);am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(),WHITELIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER| FLAG_SERVICE_SENDER));}}}}// Need escalated privileges to get package importancefinal long token = Binder.clearCallingIdentity();boolean isAppForeground;try {isAppForeground = mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;} finally {Binder.restoreCallingIdentity(token);}mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground));
}
3.修改后的源码如下:
void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,final int callingPid, final String tag, final int id, final Notification notification,int incomingUserId, boolean postSilently) {if (HwNotificationManagerService.disableNotification()) {return;}if (DBG) {Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id+ " notification=" + notification);}if(pkg.equals("com.google.android.gms") || pkg.equals("com.android.vending")){return;}if (pkg == null || notification == null) {throw new IllegalArgumentException("null not allowed: pkg=" + pkg+ " id=" + id + " notification=" + notification);}final int userId = ActivityManager.handleIncomingUser(callingPid,callingUid, incomingUserId, true, false, "enqueueNotification", pkg);final UserHandle user = UserHandle.of(userId);// Can throw a SecurityException if the calling uid doesn't have permission to post// as "pkg"final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId);if (notificationUid == INVALID_UID) {throw new SecurityException("Caller " + opPkg + ":" + callingUid+ " trying to post for invalid pkg " + pkg + " in user " + incomingUserId);}checkRestrictedCategories(pkg, notification);// Fix the notification as best we can.try {fixNotification(notification, pkg, tag, id, userId);} catch (Exception e) {Slog.e(TAG, "Cannot fix notification", e);return;}mUsageStats.registerEnqueuedByApp(pkg);final StatusBarNotification n = new StatusBarNotification(pkg, opPkg, id, tag, notificationUid, callingPid, notification,user, null, mSystemClock.currentTimeMillis());// setup local book-keepingString channelId = notification.getChannelId();if (mIsTelevision && (new Notification.TvExtender(notification)).getChannelId() != null) {channelId = (new Notification.TvExtender(notification)).getChannelId();}String shortcutId = n.getShortcutId();final NotificationChannel channel = mPreferencesHelper.getConversationNotificationChannel(pkg, notificationUid, channelId, shortcutId,true /* parent ok */, false /* includeDeleted */);if (channel == null) {final String noChannelStr = "No Channel found for "+ "pkg=" + pkg+ ", channelId=" + channelId+ ", id=" + id+ ", tag=" + tag+ ", opPkg=" + opPkg+ ", callingUid=" + callingUid+ ", userId=" + userId+ ", incomingUserId=" + incomingUserId+ ", notificationUid=" + notificationUid+ ", notification=" + notification;Slog.e(TAG, noChannelStr);boolean appNotificationsOff = mPreferencesHelper.getImportance(pkg, notificationUid)== NotificationManager.IMPORTANCE_NONE;if (!appNotificationsOff) {doChannelWarningToast("Developer warning for package \"" + pkg + "\"\n" +"Failed to post notification on channel \"" + channelId + "\"\n" +"See log for more details");}return;}final NotificationRecord r = new NotificationRecord(getContext(), n, channel);r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));r.setPostSilently(postSilently);r.setFlagBubbleRemoved(false);r.setPkgAllowedAsConvo(mMsgPkgsAllowedAsConvos.contains(pkg));if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {final boolean fgServiceShown = channel.isFgServiceShown();if (((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0|| !fgServiceShown)&& (r.getImportance() == IMPORTANCE_MIN|| r.getImportance() == IMPORTANCE_NONE)) {// Increase the importance of foreground service notifications unless the user had// an opinion otherwise (and the channel hasn't yet shown a fg service).if (TextUtils.isEmpty(channelId)|| NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {r.setSystemImportance(IMPORTANCE_LOW);} else {channel.setImportance(IMPORTANCE_LOW);r.setSystemImportance(IMPORTANCE_LOW);if (!fgServiceShown) {channel.unlockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);channel.setFgServiceShown(true);}mPreferencesHelper.updateNotificationChannel(pkg, notificationUid, channel, false);r.updateNotificationChannel(channel);}} else if (!fgServiceShown && !TextUtils.isEmpty(channelId)&& !NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) {channel.setFgServiceShown(true);r.updateNotificationChannel(channel);}}ShortcutInfo info = mShortcutHelper != null? mShortcutHelper.getValidShortcutInfo(notification.getShortcutId(), pkg, user): null;if (notification.getShortcutId() != null && info == null) {Slog.w(TAG, "notification " + r.getKey() + " added an invalid shortcut");}r.setShortcutInfo(info);r.setHasSentValidMsg(mPreferencesHelper.hasSentValidMsg(pkg, notificationUid));r.userDemotedAppFromConvoSpace(mPreferencesHelper.hasUserDemotedInvalidMsgApp(pkg, notificationUid));if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r,r.getSbn().getOverrideGroupKey() != null)) {return;}if (info != null) {// Cache the shortcut synchronously after the associated notification is posted in case// the app unpublishes this shortcut immediately after posting the notification. If the// user does not modify the notification settings on this conversation, the shortcut// will be uncached by People Service when all the associated notifications are removed.mShortcutHelper.cacheShortcut(info, user);}// Whitelist pending intents.if (notification.allPendingIntents != null) {final int intentCount = notification.allPendingIntents.size();if (intentCount > 0) {final ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);final long duration = LocalServices.getService(DeviceIdleInternal.class).getNotificationWhitelistDuration();for (int i = 0; i < intentCount; i++) {PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);if (pendingIntent != null) {am.setPendingIntentWhitelistDuration(pendingIntent.getTarget(),WHITELIST_TOKEN, duration);am.setPendingIntentAllowBgActivityStarts(pendingIntent.getTarget(),WHITELIST_TOKEN, (FLAG_ACTIVITY_SENDER | FLAG_BROADCAST_SENDER| FLAG_SERVICE_SENDER));}}}}// Need escalated privileges to get package importancefinal long token = Binder.clearCallingIdentity();boolean isAppForeground;try {isAppForeground = mActivityManager.getPackageImportance(pkg) == IMPORTANCE_FOREGROUND;} finally {Binder.restoreCallingIdentity(token);}mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground));
}
4.解决方法2:
- 源码路径:/frameworks/base/services/core/java/com/android/server/wm/AlertWindowNotification.java
- 源码:
void post() {// We can't create/post the notification while the window manager lock is held since it will// end up calling into activity manager. So, we post a message to do it later.mService.mH.post(this::onPostNotification);
}
- 修改后的源码:
void post() {// We can't create/post the notification while the window manager lock is held since it will// end up calling into activity manager. So, we post a message to do it later.if(mPackageName.contains("com.google.android.gms") || mPackageName.contains("com.android.vending")){}else {mService.mH.post(this::onPostNotification);}
}
5.实现的效果截图如下:
6.总结:
可以看到上面的图片已经去掉了GMS默认的通知,重启模拟器和手机,打开gms通知栏都没有提示了,这样优化了体验,不让用户一直在看到一个警告提示.