无法在新的 Android 14 上使用警报接收器服务

问题描述 投票:0回答:1

我试图在用户选定的日期和时间收到通知,但收到此错误: 从 Activity 上下文外部调用 startActivity() 需要 FLAG_ACTIVITY_NEW_TASK 标志。这真的是你想要的吗?

我尝试将标志 FLAG_ACTIVITY_NEW_TASK 添加到意图中,但是如果我添加它,则通知将不会出现。在除 Android 14 之外的所有其他设备中都运行良好,我没有错误,即使应用程序被终止,通知也会显示,但在 Android 14 中它会崩溃。

有人知道如何修复它吗? 这是我的代码

class AlarmReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {

        if ("android.intent.action.BOOT_COMPLETED" == intent.action) {
            AlarmUtil.scheduleAll(context)
            return
        }

        val dayOfWeek = intent.getIntExtra("Day", 2)
        AlarmUtil.scheduleAlarm(context, dayOfWeek, AppPreferences.hourOfDay, AppPreferences.minuteOfDay, true)

        val notificationId = Random().nextInt(60000)

        val notificationManager =
            context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager

        val channelId = App.instance.applicationContext.getString(R.string.message_notification_channel_id)
        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)

        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = App.instance.applicationContext.getString(R.string.message_notification_channel_name)
            val descriptionText = App.instance.applicationContext.getString(R.string.message_notification_channel_name)
            val importance = NotificationManager.IMPORTANCE_HIGH
            val channel = NotificationChannel(channelId, name, importance).apply {
                description = descriptionText
                enableLights(true)
                enableVibration(true)

                if (defaultSoundUri != null) {
                    val att = AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                        .build()
                    setSound(defaultSoundUri, att)
                }

                lightColor = Color.parseColor("#501450")
            }
            notificationManager.createNotificationChannel(channel)
        }

        val newIntent = Intent(context, StartActivity::class.java)
        newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
        newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        newIntent.action = "actionString" + System.currentTimeMillis()
        val pendingIntent =
            PendingIntent.getActivity(context, 0, newIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)

        val notificationBuilder = NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.drawable.ic_notification)//a resource for your custom small icon
            .setColor(Color.parseColor("#222831"))
            .setContentText(App.instance.applicationContext.getString(R.string.remiderNotificationText))//ditto
            .setAutoCancel(true) //dismisses the notification on click
            .setSound(defaultSoundUri)
            .setVibrate(LongArray(0))
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setPriority(NotificationCompat.PRIORITY_MAX)   // heads-up
            .setContentIntent(pendingIntent)

        notificationManager.notify(
            notificationId /* ID of notification */,
            notificationBuilder.build()
        )

    }
}
object AlarmUtil {
    private val alarmManager = App.instance.applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager

    fun scheduleAlarm(context: Context?, dayOfWeek: Int, hourOfTheDay: Int, minuteOfTheDay: Int, repeating: Boolean) {
        val calendar = Calendar.getInstance()
        when(dayOfWeek){
            1 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.MONDAY
            2 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.TUESDAY
            3 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.WEDNESDAY
            4 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.THURSDAY
            5 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.FRIDAY
            6 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.SATURDAY
            7 -> calendar[Calendar.DAY_OF_WEEK] = Calendar.SUNDAY
        }
        calendar[Calendar.HOUR_OF_DAY] = hourOfTheDay
        calendar[Calendar.MINUTE] = minuteOfTheDay
        calendar[Calendar.SECOND] = 0

        if(repeating || calendar.timeInMillis < System.currentTimeMillis()){
            calendar.add(Calendar.DATE, 7)
        }

        val intent = Intent(context, AlarmReceiver::class.java)
        intent.putExtra("Day", dayOfWeek)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        val pendingIntent = PendingIntent.getBroadcast(context, dayOfWeek, intent, PendingIntent.FLAG_IMMUTABLE)

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, pendingIntent)
            return
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            if (!alarmManager.canScheduleExactAlarms()) {
                Intent().also {
                    it.action = Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM
                    it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    context?.startActivity(it)
                }
            }else {
                alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, pendingIntent)
            }
        }
    }

    fun cancelAllAlarms(context: Context?) {
        val intent = Intent(context, AlarmReceiver::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        AppPreferences.selectedDays.fromPrettyJson<Array<String>>().forEach {
            val pendingIntent = PendingIntent.getBroadcast(context, it.toInt(), intent, PendingIntent.FLAG_IMMUTABLE)
            alarmManager.cancel(pendingIntent)
        }
    }

    fun scheduleAll(context: Context?) {
        if(AppPreferences.userNotifications && AppPreferences.specialUserNotifications){
            AppPreferences.selectedDays.fromPrettyJson<ArrayList<String>>().forEach {
                scheduleAlarm(context, it.toInt(), AppPreferences.hourOfDay, AppPreferences.minuteOfDay, false)
            }
        }
    }
}

class ReminderService : Service() {

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }


    override fun onTaskRemoved(rootIntent: Intent) {
        super.onTaskRemoved(rootIntent)
        if(AppPreferences.selectedDays.isNotEmpty()){
            if(AppPreferences.specialUserNotifications) {
                AlarmUtil.scheduleAll(applicationContext)
            } else {
                AlarmUtil.cancelAllAlarms(applicationContext)
            }
        }
        this.stopSelf()
    }
}

class ReminderWorker(appContext: Context, workerParams: WorkerParameters) :
    CoroutineWorker(appContext, workerParams) {

    override suspend fun doWork(): Result {
        // Check if app is in foreground
        if (ProcessLifecycleOwner.get().lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
            val intent = Intent(applicationContext, ReminderService::class.java)
            applicationContext.startService(intent)
        }

        return Result.success()
    }
}
//This is on my main activity:
val workRequest = OneTimeWorkRequestBuilder<ReminderWorker>().build()
            // Enqueue the work request
            WorkManager.getInstance(this).enqueue(workRequest)
android kotlin android-14 software-update
1个回答
0
投票

如果您的项目使用 Android Jetpack,请考虑使用 WorkManager。此 API 提供了一种更结构化的方式来安排后台任务,包括安排通知。

© www.soinside.com 2019 - 2024. All rights reserved.