Service之startForeground

《Service之startForeground》
一片文章不仅仅是理论的探讨,更多的是应该对实际问题的解决。
写这篇文字的目的是为了解决一个用户体验的问题,如下描述。

部分手机出现下面图片,影响用户体验
《Service之startForeground》

为什么会有如此现象呢?
网友们不停的吐槽,优酷、金山词霸等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上,这种方法已经失效了,所以,这些版本无法解决。
1.更好的方法是startForeground一个真实有效的notification过去。
2.startForeground只要传的id相同,不管是不是一个进程,不管是不是同一个notification,。
都会用最新的notification覆盖旧的,只显示一个。

    原文作者:言午水手
    原文地址: https://blog.csdn.net/xutao123111/article/details/78994383
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞