Android 开发中:应用关闭时不显示通知

Android Developing: notifications don't show when app is closed

如何在 Android Studio 中发送预定通知? 我得到了这个任务:我想每天在一天中的某个选定时间收到通知。我可以在应用程序运行时轻松获取它们,但是当它的关闭通知没有出现时。

我已经尝试过 JobScheduler、AlarmManager 和 WorkManager,其中 none 效果不佳。 我的项目至少运行 SDK 26 (Android Oreo)。目标 SDK 为 30。最后的代码版本如下所示:

AlertReceiver.java

public class AlertReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        intent = new Intent(context, NotificationService.class);
        context.startService(intent);
    }
}

NotificationService.java

public class NotificationService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        showNotifications();

        return Service.START_STICKY;
    }

    private void showNotifications(){
        NotificationHelper notificationHelper = new NotificationHelper(getApplicationContext());

        NotificationCompat.Builder nb;

        nb = notificationHelper.getChannelNotification("Title", "Description");
        notificationHelper.getManager().notify(123, nb.build());
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

我这样安排提醒:

        ...
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.HOUR_OF_DAY, hours);
        calendar.set(Calendar.MINUTE, minutes);

        AlarmManager alarm_manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, AlertReceiver.class);
        PendingIntent pending_intent = PendingIntent.getBroadcast(this, 0, intent, 0);

        alarm_manager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending_intent);
```

这是我在一个项目中使用的通知(对不起Kotlin语言):

private fun createNotification() {
    val notification = getServiceNotification("")
    notificationManager.notify(NOTIFICATION_ID, notification.build())
}

private fun getServiceNotification(contentText: String): Notification.Builder {
    var notification = Notification.Builder(this)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        createNotificationChannel()
        notification = Notification.Builder(this, NOTIFICATION_SERVICE_CHANNEL_ID)
    }

    val openAppPendingIntent = PendingIntent.getActivity(
        this,
        0,
        Intent(this, MainActivity::class.java),
        PendingIntent.FLAG_UPDATE_CURRENT
    )

    return notification
        .setContentTitle("Notification Title")
        .setContentText(contentText)
        .setSmallIcon(R.drawable.ic_main)
        .setContentIntent(openAppPendingIntent)
}

@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel() {
    val notificationChannel = NotificationChannel(
        NOTIFICATION_SERVICE_CHANNEL_ID,
        NOTIFICATION_SERVICE_CHANNEL_NAME,
        NotificationManager.IMPORTANCE_HIGH
    ).apply {
        lightColor = Color.GREEN
        lockscreenVisibility = Notification.VISIBILITY_PRIVATE
    }

    notificationManager.createNotificationChannel(notificationChannel)
}

问题是fromAndroid8后台调用startService是不允许的:

在此代码中:

public class AlertReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        intent = new Intent(context, NotificationService.class);
        context.startService(intent);
    }
}

您可以更改为:

context.startService(intent);

收件人:

ContextCompat.startForegroundService(getApplicationContext(), intent)

并将其放入您的清单中:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

这将至少允许您的服务在当前实施中从后台运行。

然后您有 5 秒的时间在您的 Service 和 post 中调用 startForeground() 一个 Notification 让用户知道您的服务是 运行 ning 否则将被终止。

另外对于你正在尝试做的事情,我认为你会得到更好的结果:

setExactAndAllowWhileIdle

setAlarmClock

setExact 并不像名字暗示的那样起作用。所有 AlarmManager 文档都需要仔细阅读,我建议在尝试任何依赖于计时的 Service 实现之前详细研究“瞌睡”。