Loading common/src/main/java/com/moez/QKSMS/common/util/extensions/ContextExtensions.kt +5 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ */ package com.moez.QKSMS.common.util.extensions import android.app.job.JobScheduler import android.content.Context import android.content.res.ColorStateList import android.graphics.Color Loading @@ -25,6 +26,7 @@ import android.util.TypedValue import android.widget.Toast import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import com.moez.QKSMS.util.tryOrNull fun Context.getColorCompat(colorRes: Int): Int { Loading Loading @@ -84,3 +86,6 @@ fun Context.isInstalled(packageName: String): Boolean { val Context.versionCode: Int get() = packageManager.getPackageInfo(packageName, 0).versionCode val Context.jobScheduler: JobScheduler get() = getSystemService()!! data/src/main/java/com/moez/QKSMS/repository/MessageRepositoryImpl.kt +13 −0 Original line number Diff line number Diff line Loading @@ -737,4 +737,17 @@ class MessageRepositoryImpl @Inject constructor( } } override fun deleteOldMessages(maxAgeDays: Int) { return Realm.getDefaultInstance().use { realm -> val messages = realm.where(Message::class.java) .lessThan("date", now() - TimeUnit.DAYS.toMillis(maxAgeDays.toLong())) .findAll() val uris = messages.map { it.getUri() } realm.executeTransaction { messages.deleteAllFromRealm() } uris.forEach { uri -> context.contentResolver.delete(uri, null, null) } } } } data/src/main/java/com/moez/QKSMS/service/AutoDeleteService.kt 0 → 100644 +62 −0 Original line number Diff line number Diff line package com.moez.QKSMS.service import android.annotation.SuppressLint import android.app.job.JobInfo import android.app.job.JobParameters import android.app.job.JobService import android.content.ComponentName import android.content.Context import androidx.core.content.getSystemService import com.moez.QKSMS.common.util.extensions.jobScheduler import com.moez.QKSMS.interactor.DeleteOldMessages import dagger.android.AndroidInjection import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import kotlinx.coroutines.Job import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject class AutoDeleteService : JobService() { companion object { private const val JobId = 8120235 @SuppressLint("MissingPermission") // Added in [presentation]'s AndroidManifest.xml fun scheduleJob(context: Context) { Timber.i("Scheduling job") val serviceComponent = ComponentName(context, AutoDeleteService::class.java) val periodicJob = JobInfo.Builder(JobId, serviceComponent) .setPeriodic(TimeUnit.DAYS.toMillis(1)) .setPersisted(true) .build() context.jobScheduler.schedule(periodicJob) } fun cancelJob(context: Context) { Timber.i("Canceling job") context.jobScheduler.cancel(JobId) } } @Inject lateinit var deleteOldMessages: DeleteOldMessages private val disposables = CompositeDisposable() override fun onStartJob(params: JobParameters?): Boolean { Timber.i("onStartJob") AndroidInjection.inject(this) disposables += deleteOldMessages deleteOldMessages.execute(Unit) { jobFinished(params, false) } return true } override fun onStopJob(params: JobParameters?): Boolean { Timber.i("onStopJob") disposables.dispose() return true } } domain/src/main/java/com/moez/QKSMS/interactor/DeleteOldMessages.kt 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com> * * 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 <http://www.gnu.org/licenses/>. */ package com.moez.QKSMS.interactor import com.moez.QKSMS.repository.ConversationRepository import com.moez.QKSMS.repository.MessageRepository import com.moez.QKSMS.util.Preferences import io.reactivex.Flowable import timber.log.Timber import javax.inject.Inject class DeleteOldMessages @Inject constructor( private val conversationRepo: ConversationRepository, private val messageRepo: MessageRepository, private val prefs: Preferences ) : Interactor<Unit>() { override fun buildObservable(params: Unit): Flowable<*> = Flowable.fromCallable { val maxAge = prefs.autoDelete.get().takeIf { it > 0 } ?: return@fromCallable val counts = messageRepo.getOldMessageCounts(maxAge) val threadIds = counts.keys.toLongArray() Timber.d("Deleting ${counts.values.sum()} old messages from ${threadIds.size} conversations") messageRepo.deleteOldMessages(maxAge) conversationRepo.updateConversations(*threadIds) } } domain/src/main/java/com/moez/QKSMS/repository/MessageRepository.kt +5 −0 Original line number Diff line number Diff line Loading @@ -107,4 +107,9 @@ interface MessageRepository { */ fun getOldMessageCounts(maxAgeDays: Int): Map<Long, Int> /** * Deletes all messages older than [maxAgeDays] */ fun deleteOldMessages(maxAgeDays: Int) } Loading
common/src/main/java/com/moez/QKSMS/common/util/extensions/ContextExtensions.kt +5 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ */ package com.moez.QKSMS.common.util.extensions import android.app.job.JobScheduler import android.content.Context import android.content.res.ColorStateList import android.graphics.Color Loading @@ -25,6 +26,7 @@ import android.util.TypedValue import android.widget.Toast import androidx.annotation.StringRes import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import com.moez.QKSMS.util.tryOrNull fun Context.getColorCompat(colorRes: Int): Int { Loading Loading @@ -84,3 +86,6 @@ fun Context.isInstalled(packageName: String): Boolean { val Context.versionCode: Int get() = packageManager.getPackageInfo(packageName, 0).versionCode val Context.jobScheduler: JobScheduler get() = getSystemService()!!
data/src/main/java/com/moez/QKSMS/repository/MessageRepositoryImpl.kt +13 −0 Original line number Diff line number Diff line Loading @@ -737,4 +737,17 @@ class MessageRepositoryImpl @Inject constructor( } } override fun deleteOldMessages(maxAgeDays: Int) { return Realm.getDefaultInstance().use { realm -> val messages = realm.where(Message::class.java) .lessThan("date", now() - TimeUnit.DAYS.toMillis(maxAgeDays.toLong())) .findAll() val uris = messages.map { it.getUri() } realm.executeTransaction { messages.deleteAllFromRealm() } uris.forEach { uri -> context.contentResolver.delete(uri, null, null) } } } }
data/src/main/java/com/moez/QKSMS/service/AutoDeleteService.kt 0 → 100644 +62 −0 Original line number Diff line number Diff line package com.moez.QKSMS.service import android.annotation.SuppressLint import android.app.job.JobInfo import android.app.job.JobParameters import android.app.job.JobService import android.content.ComponentName import android.content.Context import androidx.core.content.getSystemService import com.moez.QKSMS.common.util.extensions.jobScheduler import com.moez.QKSMS.interactor.DeleteOldMessages import dagger.android.AndroidInjection import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import kotlinx.coroutines.Job import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject class AutoDeleteService : JobService() { companion object { private const val JobId = 8120235 @SuppressLint("MissingPermission") // Added in [presentation]'s AndroidManifest.xml fun scheduleJob(context: Context) { Timber.i("Scheduling job") val serviceComponent = ComponentName(context, AutoDeleteService::class.java) val periodicJob = JobInfo.Builder(JobId, serviceComponent) .setPeriodic(TimeUnit.DAYS.toMillis(1)) .setPersisted(true) .build() context.jobScheduler.schedule(periodicJob) } fun cancelJob(context: Context) { Timber.i("Canceling job") context.jobScheduler.cancel(JobId) } } @Inject lateinit var deleteOldMessages: DeleteOldMessages private val disposables = CompositeDisposable() override fun onStartJob(params: JobParameters?): Boolean { Timber.i("onStartJob") AndroidInjection.inject(this) disposables += deleteOldMessages deleteOldMessages.execute(Unit) { jobFinished(params, false) } return true } override fun onStopJob(params: JobParameters?): Boolean { Timber.i("onStopJob") disposables.dispose() return true } }
domain/src/main/java/com/moez/QKSMS/interactor/DeleteOldMessages.kt 0 → 100644 +44 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com> * * 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 <http://www.gnu.org/licenses/>. */ package com.moez.QKSMS.interactor import com.moez.QKSMS.repository.ConversationRepository import com.moez.QKSMS.repository.MessageRepository import com.moez.QKSMS.util.Preferences import io.reactivex.Flowable import timber.log.Timber import javax.inject.Inject class DeleteOldMessages @Inject constructor( private val conversationRepo: ConversationRepository, private val messageRepo: MessageRepository, private val prefs: Preferences ) : Interactor<Unit>() { override fun buildObservable(params: Unit): Flowable<*> = Flowable.fromCallable { val maxAge = prefs.autoDelete.get().takeIf { it > 0 } ?: return@fromCallable val counts = messageRepo.getOldMessageCounts(maxAge) val threadIds = counts.keys.toLongArray() Timber.d("Deleting ${counts.values.sum()} old messages from ${threadIds.size} conversations") messageRepo.deleteOldMessages(maxAge) conversationRepo.updateConversations(*threadIds) } }
domain/src/main/java/com/moez/QKSMS/repository/MessageRepository.kt +5 −0 Original line number Diff line number Diff line Loading @@ -107,4 +107,9 @@ interface MessageRepository { */ fun getOldMessageCounts(maxAgeDays: Int): Map<Long, Int> /** * Deletes all messages older than [maxAgeDays] */ fun deleteOldMessages(maxAgeDays: Int) }