在 API>25 中应用程序对前台服务 运行(可见)时是否必须通知

Is notification mandatory while app is running(visible) for the foreground service in API>25

从 Whosebug 和许多博客中,我肯定了解到前台服务永远不会 运行 在 API>25 中没有通知。但我仍然感到困惑,当应用程序 运行ning 在屏幕上或可见时,通知是强制性的。 例如。当用户站在应用程序内时无需通知。 那么这是否可以在应用 运行ning 时删除通知? 在役 class

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    ......
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

        Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
                .setContentTitle(getString(R.string.app_name))
                .setContentText(text)
                .setAutoCancel(true);

        Notification notification = builder.build();
        startForeground(1, notification);

    } 
return START_NOT_STICKY;
}

在activity

Intent myService = new Intent(this, MyService.class);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(myService);
    } else {
        startService(myService);
    }

不,这是强制性的,即使您的应用 运行 在前台,您的前台服务也需要通知。

您将无法隐藏它。

为什么: 您可以使用任何其他后台任务处理程序,如 Intent 服务、作业 sclr,但事情是为前台服务而设计的,您的用户理解该事件我将关闭,其中一个进度将保持 运行,但事情与后台不同service 你知道它会在后台做一些事情,但是当系统决定最好的时候不要在你的应用程序想要的时候做它(就像在前台服务中一样)。

还有一个例子: 假设您的应用程序在前台的电池电量低于用户或系统的预期,您的前台服务无论如何都会立即执行,所以让您的用户知道这是 运行 并占用我的资源(电池、数据等)很重要

希望你明白我的意思

无法在前台服务为 运行 时删除通知,但 可以将您的前台服务改回 "regular"服务。这消除了通知的需要。其实要用的函数,

stopForeground(boolean removeNotification)

...包含一个 removeNotification 参数只是为了这个目的。您的服务可以根据需要从 "foreground" 切换到 "regular",方法是交替调用 startForeground()stopForeground()

如果不清楚,您可能希望在至少有一个 Activity 处于 "started" 状态时调用 stopForeground()。这是您必须手动跟踪的内容。然后,当 "started" 活动数达到 0 时,您将调用 startForeground().

编辑

一种方法是使用绑定服务。然后,在需要时调用 stopForeground() 就很容易了。

假设您有一个 Activity。您可以将其绑定到服务(参见 this doc or use one of these examples)。那么您的 onServiceConnected() 函数可能如下所示(改编自 Google 示例):

//MyActivity.java:

@Override
public void onServiceConnected(ComponentName className, IBinder service) {
    LocalBinder binder = (LocalBinder) service;
    mService = binder.getService();
    mService.stopForeground(true);      //This makes the notification go away
    bound = true;
}

...

@Override
protected void onStart() {
    super.onStart();
    // Bind to the service
    bindService(new Intent(this, MyService.class), this, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    super.onStop();
    // Unbind from the service
    if (bound) {
        Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
            .setContentTitle(getString(R.string.app_name))
            .setContentText(text)
            .setAutoCancel(true);

        Notification notification = builder.build();
        mService.startForeground(1, notification);    //This brings the notification back! Service is already running, and continues to run.        

        unbindService(this);
        bound = false;
    }
}