一片文章不仅仅是理论的探讨,更多的是应该对实际问题的解决。 写这篇文字的目的是为了解决一个用户体验的问题,如下描述。
部分手机出现下面图片,影响用户体验
为什么会有如此现象呢?
网友们不停的吐槽,优酷、金山词霸等App都有如此现象,连微信、QQ都曾经有过。 哥们惊呆了,还是深深的挖掘一下吧!
void startForeground(int id, Notification notification); 使此服务在前台运行,提供正在进行的服务在此状态下向用户显示的通知。 默认情况下是后台服务,这意味着service在系统回收内存(比如在浏览器里显示大图片)的时候可以被kill掉。如果你比较在意这个service的挂掉,比如像后台音乐播放器这种突然挂了会影响用户的情况,就可以使用ForegroundService来提示用户。
startForeground
-> com.android.server.am.ActivityManagerService#setServiceForeground
-> com.android.server.am.ActiveServices#setServiceForegroundLocked
在其中先获取对应的ServiceRecord:
ServiceRecord r = findServiceLocked(className, token, userId);
r.foregroundNoti = notification;
r.isForeground = true;
r.postNotification();
在postNotification()方法中: 判断notification的mSmallIcon == null,如果是打印日志 Slog.v(TAG, "Attempted to start a foreground service ("+ name + ") with a broken notification (no icon: " + localForegroundNoti + ")");
然后构建一个新的Notification,
标题填上“appName is running”,
内容填上“Tap for more information or to stop the app.”
然后通过NotificationManagerService.enqueueNotification()更新通知。
结果,就看到这么一个东西。
使用场景: 一般这个是为了让Service不容易被杀死,才设置一个notification。 但是此时又不想让用户看到这个通知,该怎么做呢?
最好的办法是没有这个需求。
经过查找源码:
SDK_INT< 18, postNotification()没有判断iflocalForegroundNoti.icon;
18 =< SDK_INT < 23, postNotification()中if (localForegroundNoti.icon == 0);
23 =< SDK_INT, postNotification()中if (localForegroundNoti.getSmallIcon() == null);
小于APi 18,传一个new Notification()是不会显示通知的。
大于等于18就不行了,但是可能通过在启动一个service,然后startForeground一个相同的id, 然后立刻stopForeground(true),可以将其消失(注意:这其实是google的bug)。
实测android 6.0生效。
但是在7.1.2上,这种方法已经失效了,所以,这些版本无法解决。
尝试了各种反射调用之后,使用外部的notificationManager始终无法去掉由此产生的通知。
因为NotificationManagerService中做了权限检查的限制,无法绕过。
结论:
1.更好的方法是startForeground一个真实有效的notification过去。
2.startForeground只要传的id相同,不管是不是一个进程,不管是不是同一个notification, 都会用最新的notification覆盖旧的,只显示一个。
言午水手 发布了12 篇原创文章 · 获赞 15 · 访问量 4万+ 私信 关注