Уведомление Android - Как создать систему на основе свойств модели - PullRequest
0 голосов
/ 17 сентября 2018

Я пытался реализовать Уведомления в моем приложении, но безуспешно.Ниже приведены мои наблюдения:

Требования:

  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 просто берет context и model и создает уведомление

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 всякий раз, когда пользователь, например, перезагружает свое устройство или завершает процесс.Во время отладки я обнаружил, что данные, которые я храню в notificationIntent в NotificationScheduler, после перезагрузки устройства больше не доступны в onReceive() в NotificationPublisher и, следовательно, будут генерировать NPE.

Я думаю, что я делаю что-то концептуально неправильное с этим подходом, и я хотел бы, чтобы вы помогли мне понять, как выполнить вышеупомянутые требования.

1 Ответ

0 голосов
/ 19 сентября 2018

Ну, я не буду вдаваться в детали ваших проблем с программированием и не помогу вам найти ошибку. Но я внимательно прочитал ваш вопрос и тоже понял проблему и ее решение .. !! Это немного теоретически ... Но, как я вижу, ваши навыки программирования хороши ... так что вам просто нужно направление и прояснение концепции.

Вот и мы:

Это работает, если я намеренно отображаю уведомление, как только оно создано, но я получаю исключение NullPointerException всякий раз, когда пользователь, например, reboots свое устройство или kills процесс.

Это основная причина проблемы. Всякий раз, когда система перезагружается или когда система убивает приложение.

Что вызвало это ...?

Всякий раз, когда система перезагружается "Все аварийные сигналы, установленные AlarmManager, больше не сохраняются и должны быть повторно запланированы приложением"

Что тогда обходится ...?

Вести таблицу запланированных сигналов тревоги. Как только система сработает, ON_BOOT_COMPLETE перепланирует все заново.

Большинство устройств на рынке не запускают мой ON_BOOT_COMPLETE приемник .. !!

Да, большинство устройств в наши дни поддерживают только услуги таких крупных компаний, как google, facebook, whatsapp, twitter, instagram, а все остальные все отбрасываются во время загрузки.

Почему производители мобильных телефонов делают это?

Поскольку это бизнес, он также повышает производительность и скорость работы всего устройства. И если они не разрешают услуги упомянутых компаний при перезагрузке .., то никто не будет брать такие телефоны .. !!

Любое решение для этого ..?

Использовать диспетчер заданий Firebase. Позвольте сервисам Google play обработать ваш сервис.

Надеюсь, это поможет вам и исправит меня, если я ошибаюсь или если понадобятся какие-либо дополнительные разъяснения по этому вопросу. Спасибо

РЕДАКТИРОВАТЬ 2

Я бы предложил создать график работы по вашей основной деятельности context и позволить ему обрабатывать сервисы Google Play, которые начнут выполнять работу на every reboot. Эта работа должна вызвать службу переднего плана с надлежащим уведомлением. И через эту службу переднего плана снова вызовите intentservice, который будет re-schedule всех alarms, считывая из таблицы Sqlite одну за другой.

Редактировать: 3

Даже если вы будете следовать всем этим парадигмам, предложенным здесь ... Есть другая проблема, которую вы заметите ..

Google play не запускает службу My foreground при перезагрузке .. !!

Да ..., As Post Marshmallow и modified ROMs (включая штатные Android и производителей мобильных устройств, модифицированные ОС, такие как OxygenO, FunTouchO, ColorOs, ... Этот список также никогда не заканчивается) Поскольку батарея оптимизирована и нет частных приложений процессы могут войти в память при перезагрузке .. !!

Теперь есть ли способ, которым я тоже могу решить эту проблему ...?

Да .. Покажите пользователю смелое и яркое предупреждение:

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

Вот как мы можем решить эти многочисленные проблемы ... Да, я Я понимаю, что у него нет хорошей документации от Google и нет примеров кода. Тем не менее, если вам потребуется какая-либо помощь в реализации любого sub-point, я также помогу вам в реализации всех этих подпунктов

Спасибо, что помогли

...