Android通知-如何基于模型属性创建系统

时间:2018-09-17 12:46:24

标签: android kotlin push-notification

我一直在尝试在我的应用中实施通知,但没有成功。以下是我的观察:

要求:

  1. 安排通知后,必须每月重复一次。
  2. 该通知将带有一些模型对象数据,因此需要将该对象传递给通知生成器。

到目前为止,我如何解决该问题:

我创建了一个NotificationScheduler对象,该对象基本上为要触发的通知创建了PendingIntent

object NotificationScheduler {
    fun scheduleNotification(context: Context, model: Model, cal: Calendar) {
        cal.set(Calendar.HOUR_OF_DAY, 11)
        val notificationIntent = Intent(context, NotificationPublisher::class.java)
        notificationIntent.putExtra("model", Utils.parcelToBytes(model))

        val pendingIntent = PendingIntent.getBroadcast(context, 1, notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT)
        val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
    }
}

然后我有一个NotificationPublisher类,应该显示通知并通过再次调用NotificationScheduler来设置下一个通知。

class NotificationPublisher: BroadcastReceiver() {
    var model: Model? = null

    override fun onReceive(context: Context?, intent: Intent?) {
        val modelBytes = intent?.getByteArrayExtra("model")

        if (modelBytes != null) {
            model = Utils.bytesToParcel(modelBytes, Model.CREATOR)
        }

        val notificationBuilder = NotificationBuilder(context!!, model!!)
        val notification = notificationBuilder.buildNotification()

        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.notify(1, notification)

        //schedules the next notification

NotificationScheduler.scheduleNotification(context, model!!, Calendar.getInstance())
        }
    }

NotificationBuilder类仅使用contextmodel并建立通知的地方

class NotificationBuilder(val context: Context, val model: Model) {

    fun buildNotification(): Notification {
        generateNotificationChannel(context)

        val builder = NotificationCompat.Builder(context, "ID")
                .setSmallIcon(R.drawable.sub)
                .setContentTitle(model.title)
                .setPriority(NotificationCompat.PRIORITY_HIGH)

        return builder.build()
    }

    private fun generateNotificationChannel(context: Context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Test"
            val description = "description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            val channel = NotificationChannel("ID", name, importance)
            channel.description = description

            val notificationManager = context.getSystemService(NotificationManager::class.java)
            notificationManager?.createNotificationChannel(channel)
        }
    }

这种方法的问题:

如果我在创建通知后立即有意显示通知,它将起作用,但是每当例如用户重新启动设备或终止进程时,我都会收到NullPointerException。调试时,我发现重新启动设备后,存储在notificationIntentNotificationScheduleronReceive()中的数据在NotificationPublisher的{​​{1}}中不再可用,并且因此将生成一个NPE。

我认为我在这种方法上做错了什么,我希望您能帮助我弄清楚如何实现上述要求。

1 个答案:

答案 0 :(得分:2)

好吧..,我不会详细介绍您的编程问题,也不会帮助您发现错误。.但是我很敏锐地阅读了您的问题,并且也得到了问题及其解决方案.. !!这有点理论上的。但是,正如我所看到的,您的编程技巧是好的..所以您只需要方向和概念上的明确。

我们在这里:

  

如果我故意在创建通知后立即显示通知,则可以使用此通知,但是只要用户reboots他的设备或kills该进程,我都会收到NullPointerException。

这是问题的主要原因。每当系统重新启动或系统杀死该应用程序时。

  

是什么原因造成的...?

每当系统重新启动时,“ AlarmManager设置的所有警报将不再保留,需要由应用程序重新安排”

  

那怎么解决...?

维护计划的警报表。系统一旦启动ON_BOOT_COMPLETE,便会重新安排所有时间。

  

市场上大多数设备不会触发我的ON_BOOT_COMPLETE接收器.. !!

是的,如今大多数设备仅保留googlefacebookwhatsapptwitterinstagram等主要公司的服务,其余所有设备其他的在引导时被丢弃。

  

为什么移动制造商这样做?

这是一项业务,因此还可以提高整个设备的性能和速度。如果他们不允许上述公司重启服务,那么没人会接这种电话。

  

对此有任何解决方案吗??

使用Firebase作业调度程序。让Google Play服务处理您的服务。

如果我错了或者需要对该问题进行进一步的澄清,我希望它可以帮助您并纠正我。谢谢

编辑2

我建议您通过您的mainactivity context创建一个作业计划作业,并让它处理将在every reboot上开始执行作业的Google Play服务。该作业应通过适当的通知调用前台服务。并通过该前台服务再次调用intentservice,它将通过从Sqlite表中逐个读取来re-schedule alarms

编辑:3

即使您遵循此处建议的所有范例,也会有另一个问题。

  

Google Play在重新启动后无法启动我的前台服务.. !!

是的...,如帖子Marshmallowmodified ROMs(包括库存的Android和移动制造商修改的操作系统,如OxygenOs,FunTouchOs,ColorOs等。此列表永远也不会结束)。重启后,任何私有应用程序进程都不会进入内存。

  

现在我有没有办法解决这个问题...?

是。.向用户显示大胆而明亮的警报:

If You want to perform this app normally, 
you must stop optimising battery for this 
app from settings..!!
  

那是我们解决这些许多问题的方法。   了解它没有来自Google的完善文档,也没有示例代码,以防万一,如果您在实现任何sub-point方面需要任何帮助,我也会帮助您实现所有这些子点

感谢您的帮助