From ffe9935e44be646a8c3dd4ab84b705b89974496e Mon Sep 17 00:00:00 2001 From: Moez Bhatti Date: Fri, 29 Jun 2018 23:19:54 -0400 Subject: [PATCH] Update all scheduled message alarms when device is rebooted --- .../moez/QKSMS/manager/AlarmManagerImpl.kt | 46 +++++++++++++++++++ .../com/moez/QKSMS/receiver/BootReceiver.kt | 39 ++++++++++++++++ .../ScheduledMessageRepositoryImpl.kt | 24 +--------- .../QKSMS/interactor/AddScheduledMessage.kt | 43 +++++++++++++++++ .../UpdateScheduledMessageAlarms.kt | 39 ++++++++++++++++ .../com/moez/QKSMS/manager/AlarmManager.kt | 29 ++++++++++++ presentation/src/main/AndroidManifest.xml | 6 +++ .../QKSMS/feature/compose/ComposeViewModel.kt | 6 ++- .../com/moez/QKSMS/injection/AppModule.kt | 5 ++ .../BroadcastReceiverBuilderModule.kt | 5 ++ 10 files changed, 218 insertions(+), 24 deletions(-) create mode 100644 data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt create mode 100644 data/src/main/java/com/moez/QKSMS/receiver/BootReceiver.kt create mode 100644 domain/src/main/java/com/moez/QKSMS/interactor/AddScheduledMessage.kt create mode 100644 domain/src/main/java/com/moez/QKSMS/interactor/UpdateScheduledMessageAlarms.kt create mode 100644 domain/src/main/java/com/moez/QKSMS/manager/AlarmManager.kt diff --git a/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt b/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt new file mode 100644 index 00000000..a89a8c9b --- /dev/null +++ b/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.manager + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import com.klinker.android.send_message.BroadcastUtils +import javax.inject.Inject + +class AlarmManagerImpl @Inject constructor(private val context: Context) : AlarmManager { + + override fun getScheduledMessageIntent(id: Long): PendingIntent { + val action = "com.moez.QKSMS.SEND_SCHEDULED_MESSAGE" + val intent = Intent(action).putExtra("id", id) + BroadcastUtils.addClassName(context, intent, action) + return PendingIntent.getBroadcast(context, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + } + + override fun setAlarm(date: Long, intent: PendingIntent) { + val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as android.app.AlarmManager + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + alarmManager.setExactAndAllowWhileIdle(android.app.AlarmManager.RTC_WAKEUP, date, intent) + } else { + alarmManager.setExact(android.app.AlarmManager.RTC_WAKEUP, date, intent) + } + } + +} \ No newline at end of file diff --git a/data/src/main/java/com/moez/QKSMS/receiver/BootReceiver.kt b/data/src/main/java/com/moez/QKSMS/receiver/BootReceiver.kt new file mode 100644 index 00000000..e7f739f8 --- /dev/null +++ b/data/src/main/java/com/moez/QKSMS/receiver/BootReceiver.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.receiver + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.moez.QKSMS.interactor.UpdateScheduledMessageAlarms +import dagger.android.AndroidInjection +import javax.inject.Inject + +class BootReceiver : BroadcastReceiver() { + + @Inject lateinit var updateScheduledMessageAlarms: UpdateScheduledMessageAlarms + + override fun onReceive(context: Context, intent: Intent?) { + AndroidInjection.inject(this, context) + + val result = goAsync() + updateScheduledMessageAlarms.execute(Unit) { result.finish() } + } + +} \ No newline at end of file diff --git a/data/src/main/java/com/moez/QKSMS/repository/ScheduledMessageRepositoryImpl.kt b/data/src/main/java/com/moez/QKSMS/repository/ScheduledMessageRepositoryImpl.kt index 0bfccc79..283253dd 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/ScheduledMessageRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/ScheduledMessageRepositoryImpl.kt @@ -1,20 +1,12 @@ package com.moez.QKSMS.repository -import android.app.AlarmManager -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import android.os.Build -import com.klinker.android.send_message.BroadcastUtils import com.moez.QKSMS.model.ScheduledMessage import io.realm.Realm import io.realm.RealmList import io.realm.RealmResults import javax.inject.Inject -class ScheduledMessageRepositoryImpl @Inject constructor( - private val context: Context -) : ScheduledMessageRepository { +class ScheduledMessageRepositoryImpl @Inject constructor() : ScheduledMessageRepository { override fun saveScheduledMessage(date: Long, subId: Int, recipients: List, sendAsGroup: Boolean, body: String, attachments: List) { @@ -26,18 +18,6 @@ class ScheduledMessageRepositoryImpl @Inject constructor( val message = ScheduledMessage(id, date, subId, recipientsRealmList, sendAsGroup, body, attachmentsRealmList) - val action = "com.moez.QKSMS.SEND_SCHEDULED_MESSAGE" - val intent = Intent(action).putExtra("id", id) - BroadcastUtils.addClassName(context, intent, action) - val pendingIntent = PendingIntent.getBroadcast(context, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) - - val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, date, pendingIntent) - } else { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, date, pendingIntent) - } - realm.executeTransaction { realm.insertOrUpdate(message) } } } @@ -46,7 +26,7 @@ class ScheduledMessageRepositoryImpl @Inject constructor( return Realm.getDefaultInstance() .where(ScheduledMessage::class.java) .sort("date") - .findAllAsync() + .findAll() } override fun getScheduledMessage(id: Long): ScheduledMessage? { diff --git a/domain/src/main/java/com/moez/QKSMS/interactor/AddScheduledMessage.kt b/domain/src/main/java/com/moez/QKSMS/interactor/AddScheduledMessage.kt new file mode 100644 index 00000000..955fd08e --- /dev/null +++ b/domain/src/main/java/com/moez/QKSMS/interactor/AddScheduledMessage.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.interactor + +import com.moez.QKSMS.repository.ScheduledMessageRepository +import io.reactivex.Flowable +import javax.inject.Inject + +class AddScheduledMessage @Inject constructor( + private val scheduledMessageRepo: ScheduledMessageRepository, + private val updateScheduledMessageAlarms: UpdateScheduledMessageAlarms +) : Interactor() { + + data class Params(val date: Long, + val subId: Int, + val recipients: List, + val sendAsGroup: Boolean, + val body: String, + val attachments: List) + + override fun buildObservable(params: Params): Flowable<*> { + return Flowable.just(params) + .map { scheduledMessageRepo.saveScheduledMessage(it.date, it.subId, it.recipients, it.sendAsGroup, it.body, it.attachments) } + .flatMap { updateScheduledMessageAlarms.buildObservable(Unit) } + } + +} \ No newline at end of file diff --git a/domain/src/main/java/com/moez/QKSMS/interactor/UpdateScheduledMessageAlarms.kt b/domain/src/main/java/com/moez/QKSMS/interactor/UpdateScheduledMessageAlarms.kt new file mode 100644 index 00000000..674c305d --- /dev/null +++ b/domain/src/main/java/com/moez/QKSMS/interactor/UpdateScheduledMessageAlarms.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.interactor + +import com.moez.QKSMS.manager.AlarmManager +import com.moez.QKSMS.repository.ScheduledMessageRepository +import io.reactivex.Flowable +import javax.inject.Inject + +class UpdateScheduledMessageAlarms @Inject constructor( + private val alarmManager: AlarmManager, + private val scheduledMessageRepo: ScheduledMessageRepository +) : Interactor() { + + override fun buildObservable(params: Unit): Flowable<*> { + return Flowable.just(params) + .map { scheduledMessageRepo.getScheduledMessages() } + .flatMap { messages -> Flowable.fromIterable(messages) } + .map { message -> Pair(message.id, message.date) } + .doOnNext { (id, date) -> alarmManager.setAlarm(date, alarmManager.getScheduledMessageIntent(id)) } + } + +} \ No newline at end of file diff --git a/domain/src/main/java/com/moez/QKSMS/manager/AlarmManager.kt b/domain/src/main/java/com/moez/QKSMS/manager/AlarmManager.kt new file mode 100644 index 00000000..84065563 --- /dev/null +++ b/domain/src/main/java/com/moez/QKSMS/manager/AlarmManager.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 Moez Bhatti + * + * This file is part of QKSMS. + * + * QKSMS is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * QKSMS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with QKSMS. If not, see . + */ +package com.moez.QKSMS.manager + +import android.app.PendingIntent + +interface AlarmManager { + + fun getScheduledMessageIntent(id: Long): PendingIntent + + fun setAlarm(date: Long, intent: PendingIntent) + +} \ No newline at end of file diff --git a/presentation/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml index bce660be..30b8f783 100644 --- a/presentation/src/main/AndroidManifest.xml +++ b/presentation/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ + @@ -75,6 +76,11 @@ + + + + + diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt index 9adbf4ea..08374cf9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt @@ -38,6 +38,7 @@ import com.moez.QKSMS.extensions.isImage import com.moez.QKSMS.extensions.mapNotNull import com.moez.QKSMS.extensions.removeAccents import com.moez.QKSMS.filter.ContactFilter +import com.moez.QKSMS.interactor.AddScheduledMessage import com.moez.QKSMS.interactor.CancelDelayedMessage import com.moez.QKSMS.interactor.ContactSync import com.moez.QKSMS.interactor.DeleteMessages @@ -80,6 +81,7 @@ class ComposeViewModel @Inject constructor( @Named("text") private val sharedText: String, @Named("attachments") private val sharedAttachments: List, private val context: Context, + private val addScheduledMessage: AddScheduledMessage, private val billingManager: BillingManager, private val cancelMessage: CancelDelayedMessage, private val contactFilter: ContactFilter, @@ -93,7 +95,6 @@ class ComposeViewModel @Inject constructor( private val permissionManager: PermissionManager, private val prefs: Preferences, private val retrySending: RetrySending, - private val scheduledMessageRepo: ScheduledMessageRepository, private val sendMessage: SendMessage, private val subscriptionManager: SubscriptionManagerCompat, private val syncContacts: ContactSync @@ -583,7 +584,8 @@ class ComposeViewModel @Inject constructor( state.scheduled != 0L -> { newState { copy(scheduled = 0) } val uris = attachments.map { it.getUri() }.map { it.toString() } - scheduledMessageRepo.saveScheduledMessage(state.scheduled, subId, addresses, state.sendAsGroup, body, uris) + val params = AddScheduledMessage.Params(state.scheduled, subId, addresses, state.sendAsGroup, body, uris) + addScheduledMessage.execute(params) context.toast(R.string.compose_scheduled_toast) } diff --git a/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt b/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt index 26022add..fd049ae9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt +++ b/presentation/src/main/java/com/moez/QKSMS/injection/AppModule.kt @@ -26,6 +26,8 @@ import androidx.lifecycle.ViewModelProvider import com.f2prateek.rx.preferences2.RxSharedPreferences import com.moez.QKSMS.common.ViewModelFactory import com.moez.QKSMS.common.util.NotificationManagerImpl +import com.moez.QKSMS.manager.AlarmManager +import com.moez.QKSMS.manager.AlarmManagerImpl import com.moez.QKSMS.manager.AnalyticsManager import com.moez.QKSMS.manager.AnalyticsManagerImpl import com.moez.QKSMS.manager.ExternalBlockingManager @@ -87,6 +89,9 @@ class AppModule(private var application: Application) { // Manager + @Provides + fun provideAlarmManager(manager: AlarmManagerImpl): AlarmManager = manager + @Provides fun provideAnalyticsManager(manager: AnalyticsManagerImpl): AnalyticsManager = manager diff --git a/presentation/src/main/java/com/moez/QKSMS/injection/BroadcastReceiverBuilderModule.kt b/presentation/src/main/java/com/moez/QKSMS/injection/BroadcastReceiverBuilderModule.kt index 53f918bd..477a7c75 100644 --- a/presentation/src/main/java/com/moez/QKSMS/injection/BroadcastReceiverBuilderModule.kt +++ b/presentation/src/main/java/com/moez/QKSMS/injection/BroadcastReceiverBuilderModule.kt @@ -19,6 +19,7 @@ package com.moez.QKSMS.injection import com.moez.QKSMS.feature.widget.WidgetProvider +import com.moez.QKSMS.receiver.BootReceiver import com.moez.QKSMS.receiver.DefaultSmsChangedReceiver import com.moez.QKSMS.receiver.MarkReadReceiver import com.moez.QKSMS.receiver.MarkSeenReceiver @@ -40,6 +41,10 @@ import dagger.android.ContributesAndroidInjector @Module abstract class BroadcastReceiverBuilderModule { + @ActivityScope + @ContributesAndroidInjector() + abstract fun bindBootReceiver(): BootReceiver + @ActivityScope @ContributesAndroidInjector() abstract fun bindDefaultSmsChangedReceiver(): DefaultSmsChangedReceiver