【问题标题】:Android foreground service notification not showingAndroid前台服务通知未显示
【发布时间】:2017-11-23 08:15:15
【问题描述】:

我正在尝试启动前台服务。我收到通知说服务确实启动了,但通知总是被抑制。我仔细检查了该应用程序是否允许在我的设备上的应用程序信息中显示通知。这是我的代码:

private void showNotification() {
    Intent notificationIntent = new Intent(this, MainActivity.class);
    notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);

    Bitmap icon = BitmapFactory.decodeResource(getResources(),
            R.mipmap.ic_launcher);

    Notification notification = new NotificationCompat.Builder(getApplicationContext())
            .setContentTitle("Revel Is Running")
            .setTicker("Revel Is Running")
            .setContentText("Click to stop")
            .setSmallIcon(R.mipmap.ic_launcher)
            //.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
            .setContentIntent(pendingIntent)
            .setOngoing(true).build();
    startForeground(Constants.FOREGROUND_SERVICE,
            notification);
    Log.e(TAG,"notification shown");

}

这是我看到的唯一错误: 06-20 12:26:43.635 895-930/? E/NotificationService: Suppressing notification from the package by user request.

【问题讨论】:

    标签: android notifications


    【解决方案1】:

    这是因为 Android O bg 服务限制。

    所以现在您只需为以startForegroundService() 启动的服务调用startForeground(),并在服务启动后的前5 秒内调用它。

    这里是指南 - https://developer.android.com/about/versions/oreo/background#services

    像这样:

    //Start service:
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
      startForegroundService(new Intent(this, YourService.class));
    } else {
      startService(new Intent(this, YourService.class));
    }
    

    然后创建并显示通知(使用之前假设的频道):

    private void createAndShowForegroundNotification(Service yourService, int notificationId) {
    
        final NotificationCompat.Builder builder = getNotificationBuilder(yourService,
             "com.example.your_app.notification.CHANNEL_ID_FOREGROUND", // Channel id
        NotificationManagerCompat.IMPORTANCE_LOW); //Low importance prevent visual appearance for this notification channel on top 
        builder.setOngoing(true)
        .setSmallIcon(R.drawable.small_icon)
        .setContentTitle(yourService.getString(R.string.title))
        .setContentText(yourService.getString(R.string.content));
    
        Notification notification = builder.build();
    
        yourService.startForeground(notificationId, notification);
    
        if (notificationId != lastShownNotificationId) {
              // Cancel previous notification
              final NotificationManager nm = (NotificationManager) yourService.getSystemService(Activity.NOTIFICATION_SERVICE);
              nm.cancel(lastShownNotificationId);
        }
        lastShownNotificationId = notificationId;
    }
    
    public static NotificationCompat.Builder getNotificationBuilder(Context context, String channelId, int importance) {
        NotificationCompat.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            prepareChannel(context, channelId, importance);
            builder = new NotificationCompat.Builder(context, channelId);
        } else {
            builder = new NotificationCompat.Builder(context);
        }
        return builder;
    }
    
    @TargetApi(26)
    private static void prepareChannel(Context context, String id, int importance) {
        final String appName = context.getString(R.string.app_name);
        String description = context.getString(R.string.notifications_channel_description);
        final NotificationManager nm = (NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);
    
        if(nm != null) {
            NotificationChannel nChannel = nm.getNotificationChannel(id);
    
            if (nChannel == null) {
                nChannel = new NotificationChannel(id, appName, importance);
                nChannel.setDescription(description);
                nm.createNotificationChannel(nChannel);
            }
        }
    }
    

    请记住,即使您使用不同的频道 ID,您的前台通知也会与您的其他通知具有相同的状态,因此它可能会与其他人一起作为一个组被隐藏。使用不同的组来避免它。

    【讨论】:

    • Android O及以上版本如何停止前台服务?
    • 检查这里developer.android.com/reference/android/app/Service,如果您将它作为前台启动 - 使用带有通知 id 或布尔 arg 的“stopForeground()”,否则使用常规 stopService/unbindService 取决于您如何启动和使用它。
    • 也可以使用ContextCompat.startForegroundService(context, intentService)
    • 我需要在启动前台服务的活动上还是在服务类上运行它?有点迷茫,求指教。
    • startForegroundService/startService 从 Activity 或您将启动服务的任何位置。以及来自任何地方的通知块。也许是一些实用类。
    【解决方案2】:

    问题是我使用的是 Android O,它需要更多信息。这是android O的成功代码。

        mNotifyManager = (NotificationManager) mActivity.getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createChannel(mNotifyManager);
        mBuilder = new NotificationCompat.Builder(mActivity, "YOUR_TEXT_HERE").setSmallIcon(android.R.drawable.stat_sys_download).setColor
                (ContextCompat.getColor(mActivity, R.color.colorNotification)).setContentTitle(YOUR_TITLE_HERE).setContentText(YOUR_DESCRIPTION_HERE);
        mNotifyManager.notify(mFile.getId().hashCode(), mBuilder.build());
    
    @TargetApi(26)
    private void createChannel(NotificationManager notificationManager) {
        String name = "FileDownload";
        String description = "Notifications for download status";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
    
        NotificationChannel mChannel = new NotificationChannel(name, name, importance);
        mChannel.setDescription(description);
        mChannel.enableLights(true);
        mChannel.setLightColor(Color.BLUE);
        notificationManager.createNotificationChannel(mChannel);
    }
    

    【讨论】:

    • 有没有更方便的方法来处理这个问题?即支持/兼容风格?在 pre-26 和 26+ 平台上工作的相同代码,无需使用“if”和重复代码。
    • if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {createNotificationChannel(context);} //REST OF CODE HERE
    • 但是在这个新的 sn-p 代码中,我注意到您调用的是 mNotifyManager.notify() 而不是 startForeground()。这种情况下,真的是做服务前台吗?
    • mFile 是什么?
    • 我只是想念这句话.. notificationManager.createNotificationChannel(mChannel);当我写它时,它就像魅力一样。无需定义 startForeground()
    【解决方案3】:

    如果以上都不起作用,您应该检查您的通知 ID 是否为 0 ... 惊喜!!不能为 0。

    非常感谢@Luka Kama 为this 发帖

    startForeground(0, notification); // Doesn't work...
    
    startForeground(1, notification); // Works!!!
    

    【讨论】:

    【解决方案4】:

    对我来说,一切都设置正确(还添加了 FOREGROUND_SERVICE 权限到清单), 但我只需要卸载应用程序并重新安装它。

    【讨论】:

    • 我不知道这是我的问题
    【解决方案5】:

    如果您的目标是 Android 9(Pie) api 级别 28 或更高,则应在清单文件中授予 FOREGROUND_SERVICE 权限。请参阅此链接:https://developer.android.com/about/versions/pie/android-9.0-migration#bfa

    【讨论】:

      【解决方案6】:

      我不敢相信。在我的例子中,在将 'android:name=".App"' 添加到 AndroidManifest.xml 之后,通知开始显示。 示例:

          <application
          android:name=".App"
          android:allowBackup="true"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:roundIcon="@mipmap/ic_launcher_round"
          android:supportsRtl="true"
      

      【讨论】:

        【解决方案7】:

        就我而言,这是由我使用 IntentService 引起的。

        简而言之,如果您想要前台服务,则子类化 Service

        【讨论】:

        • 这与扩展 IntentService 无关
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2019-06-24
        • 1970-01-01
        • 2019-08-05
        • 1970-01-01
        • 1970-01-01
        • 2012-01-21
        相关资源
        最近更新 更多