从 Android API 级别 26 开始, 前台服务。此要求旨在防止 可能会对系统资源提出过多需求的服务,包括 尤其是电池此要求可能会带来潜在问题:如果应用 没有仔细管理通知,因此 如果它在所有服务之间共享,则可以有多个永久性 不可关闭的通知,导致有效列表中的 通知。
当您使用 Navigation 等 SDK
SDK,它们独立于应用本身运行前台服务,
单独的持续性通知,这使得它们难以整合。
为了解决这些问题,Navigation SDK v1.11 引入了一个简单的 API,
帮助管理整个应用中的永久通知,包括在 SDK 内显示的通知。
组件
前台服务管理器提供 Android 前台使用的封装容器 服务类和持久性通知类。这个封装容器的主要 功能是强制重复使用通知 ID, 使用该管理器在所有前台服务之间共享。
Navigation SDK 包含用于初始化和获取
ForegroundServiceManager
单例。此单例只能初始化
在 Navigation SDK 的生命周期内触发一次。因此,如果您使用
初始化调用(initForegroundServiceManagerMessageAndIntent()
或
initForegroundServiceManagerProvider()
),则应该将
请使用 try-catch 代码块,以防用户再次进入该路径。Navigation SDK
则会抛出运行时异常,除非您
首先清除对 ForegroundServiceManager
的所有引用,然后调用
clearForegroundServiceManager()
,然后再进行后续调用。
initForegroundServiceManagerMessageAndIntent()
的四个参数为
application
、notificationId
、defaultMessage
和resumeIntent
。如果
最后三个参数为 null,则通知是标准
Navigation SDK 通知。仍然可以隐藏其他前景
。notificationId
参数
指定应该用于通知的通知 ID。如果
null,则使用任意值。您可以明确将其设置为在
与其他 SDK 的通知(如来自其他 SDK 的通知)冲突。通过
defaultMessage
是一个字符串,系统会在
导航。resumeIntent
是在通知发出时触发的 intent
。如果 resumeIntent
为 null,则点击通知
将会被忽略。
initForegroundServiceManagerProvider()
的三个参数为
application
、notificationId
和notificationProvider
。如果最后一个
两个参数为 null,则通知是标准 Navigation SDK
通知。notificationId
参数用于指定
。如果该值为 null,则任意值
。您可以明确设置该属性以解决与其他
通知,例如来自其他 SDK 的通知。如果 notificationProvider
为
那么提供程序会始终负责
生成要呈现的通知。
Navigation SDK getForegroundServiceManager()
方法会返回
前台服务管理器单例。如果您尚未生成代码,则
相当于调用 initForegroundServiceManagerMessageAndIntent()
为 notificationId
、defaultMessage
和
resumeIntent
。
ForegroundServiceManager
有三种简单的方法。前两项是针对
将服务移入和移出前台,通常由
创建 Deployment 清单使用这些方法可确保
与共享的常驻通知相关联。最后一个
方法 updateNotification()
,用于标记通知具有的管理器
并且应重新呈现
如果您需要完全控制共享的常驻通知,
该 API 会提供 NotificationContentProvider
接口,用于定义
通知提供程序,其中包含用于接收通知的单一方法
与当前内容相关联。它还提供了一个基类,您可以
您可以视需要使用,以帮助定义提供程序。基类的一个主类
其目的在于,它提供了一种在不使用updateNotification()
需要访问ForegroundServiceManager
。如果您使用
通知提供程序以接收新通知消息,您可以调用此
内部方法直接呈现消息在通知中。
使用场景
本部分详细介绍了使用共享永久性磁盘 通知。
- 隐藏其他应用前台服务的常驻通知
- 最简单的方案是保留当前行为,并且仅使用
用于呈现 Navigation SDK 信息的常驻通知。其他服务
可以使用前台服务管理器隐藏此通知
startForeground()
和stopForeground()
方法。 - 隐藏其他应用前台服务的常驻通知,但已设置 不浏览时显示的默认文字
- 第二种最简单的场景是保留当前行为,仅使用
用于呈现 Navigation SDK 信息的常驻通知,但以下情况除外:
。当系统未进行导航时,
提供给
initForegroundServiceManagerMessageAndIntent()
的字符串 而不是提及 “Google 地图”。您还可以使用此调用来设置 在用户点击通知时触发。 - 完全控制常驻通知的呈现
- 最后一种情况需要定义并创建通知提供程序
并使用以下代码将其传递给
ForegroundServiceManager
:initForegroundServiceManagerProvider()
。通过这个选项 可以完全控制通知中呈现的内容, 会断开 Navigation SDK 通知信息与 从而删除了 通知。Google 没有提供一种简单的方法来检索此内容, 信息,并将其插入通知。
通知提供程序示例
以下代码示例演示了如何创建和返回通知 使用简单的通知内容提供程序。
public class NotificationContentProviderImpl
extends NotificationContentProviderBase
implements NotificationContentProvider {
private String channelId;
private Context context;
private String message;
/** Constructor */
public NotificationContentProviderImpl(Application application) {
super(application);
message = "-- uninitialized --";
channelId = null;
this.context = application;
}
/**
* Sets message to display in the notification. Calls updateNotification
* to display the message immediately.
*
* @param msg The message to display in the notification.
*/
public void setMessage(String msg) {
message = msg;
updateNotification();
}
/**
* Returns the notification as it should be rendered.
*/
@Override
public Notification getNotification() {
Notification notification;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Spanned styledText = Html.fromHtml(message, FROM_HTML_MODE_LEGACY);
String channelId = getChannelId(context);
notification =
new Notification.Builder(context, channelId)
.setContentTitle("Notifications Demo")
.setStyle(new Notification.BigTextStyle()
.bigText(styledText))
.setSmallIcon(R.drawable.ic_navigation_white_24dp)
.setTicker("ticker text")
.build();
} else {
notification = new Notification.Builder(context)
.setContentTitle("Notification Demo")
.setContentText("testing non-O text")
.build();
}
return notification;
}
// Helper to set up a channel ID.
private String getChannelId(Context context) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
if (channelId == null) {
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(
"default", "navigation", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("For navigation persistent notification.");
notificationManager.createNotificationChannel(channel);
channelId = channel.getId();
}
return channelId;
} else {
return "";
}
}
}
创建 NotificationContentProviderImpl
后,您需要将
Navigation SDK 使用以下代码:
ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);
注意事项和未来的计划
- 请务必提前调用
initForegroundServiceManagerMessageAndIntent()
或initForegroundServiceManagerProvider()
, 明确了预期的使用场景您必须调用此方法 然后再创建新的导航器。 - 请务必捕获对
initForegroundServiceManagerMessageAndIntent()
或initForegroundServiceManagerProvider()
(如果代码路径是 多次输入。在 Navigation SDK v2.0 中,调用此方法 则会抛出已检查的异常,而不是运行时异常。 - Google 可能仍需做一些工作,以确保在 与标题样式匹配的通知的生命周期。
- 定义通知提供程序时,您可以控制浮动通知行为 相应的优先级
- Google 没有提供一种简单的方法用于检索精细导航信息 通知提供程序可能在通知中插入的信息。