Refactor services

This commit is contained in:
kitsunyan
2020-06-19 15:20:16 +03:00
parent 561352b685
commit 75928d260d
11 changed files with 56 additions and 49 deletions
@@ -174,9 +174,9 @@ class MainApplication: Application() {
Database.RepositoryAdapter.put(it.copy(lastModified = "", entityTag = "")) Database.RepositoryAdapter.put(it.copy(lastModified = "", entityTag = ""))
} }
} }
Connection<SyncService.Binder>(SyncService::class.java, onBind = { Connection(SyncService::class.java, onBind = { connection, binder ->
it.binder.sync(SyncService.SyncRequest.FORCE) binder.sync(SyncService.SyncRequest.FORCE)
it.connection.unbind(this) connection.unbind(this)
}).bind(this) }).bind(this)
} }
@@ -80,7 +80,7 @@ class EditRepositoryFragment(): Fragment() {
private var saveMenuItem: MenuItem? = null private var saveMenuItem: MenuItem? = null
private var layout: Layout? = null private var layout: Layout? = null
private val syncConnection = Connection<SyncService.Binder>(SyncService::class.java) private val syncConnection = Connection(SyncService::class.java)
private var repositoriesDisposable: Disposable? = null private var repositoriesDisposable: Disposable? = null
private var checkDisposable: Disposable? = null private var checkDisposable: Disposable? = null
@@ -72,10 +72,10 @@ class ProductFragment(): Fragment(), ProductAdapter.Callbacks {
private var productDisposable: Disposable? = null private var productDisposable: Disposable? = null
private var downloadDisposable: Disposable? = null private var downloadDisposable: Disposable? = null
private val downloadConnection = Connection<DownloadService.Binder>(DownloadService::class.java, onBind = { private val downloadConnection = Connection(DownloadService::class.java, onBind = { _, binder ->
updateDownloadState(it.binder.getState(packageName)) updateDownloadState(binder.getState(packageName))
downloadDisposable = it.binder.events(packageName).subscribe { updateDownloadState(it) } downloadDisposable = binder.events(packageName).subscribe { updateDownloadState(it) }
}, onUnbind = { }, onUnbind = { _, _ ->
downloadDisposable?.dispose() downloadDisposable?.dispose()
downloadDisposable = null downloadDisposable = null
}) })
@@ -20,7 +20,7 @@ import nya.kitsunyan.foxydroid.utility.Utils
class RepositoriesFragment: Fragment(), CursorOwner.Callback { class RepositoriesFragment: Fragment(), CursorOwner.Callback {
private var recyclerView: RecyclerView? = null private var recyclerView: RecyclerView? = null
private val syncConnection = Connection<SyncService.Binder>(SyncService::class.java) private val syncConnection = Connection(SyncService::class.java)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.fragment, container, false).apply { return inflater.inflate(R.layout.fragment, container, false).apply {
@@ -43,7 +43,7 @@ class RepositoryFragment(): Fragment() {
private var layout: LinearLayout? = null private var layout: LinearLayout? = null
private val syncConnection = Connection<SyncService.Binder>(SyncService::class.java) private val syncConnection = Connection(SyncService::class.java)
private var repositoryDisposable: Disposable? = null private var repositoryDisposable: Disposable? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@@ -80,7 +80,7 @@ class TabsFragment: Fragment() {
private var category = "" private var category = ""
private var order = ProductItem.Order.NAME private var order = ProductItem.Order.NAME
private val syncConnection = Connection<SyncService.Binder>(SyncService::class.java, onBind = { private val syncConnection = Connection(SyncService::class.java, onBind = { _, _ ->
viewPager?.let { viewPager?.let {
val source = ProductsFragment.Source.values()[it.currentItem] val source = ProductsFragment.Source.values()[it.currentItem]
updateUpdateNotificationBlocker(source) updateUpdateNotificationBlocker(source)
@@ -1,32 +1,33 @@
package nya.kitsunyan.foxydroid.service package nya.kitsunyan.foxydroid.service
import android.app.Service
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.os.IBinder import android.os.IBinder
class Connection<T: IBinder>(private val serviceClass: Class<out Service>, class Connection<B: IBinder, S: ConnectionService<B>>(private val serviceClass: Class<S>,
private val onBind: ((Event<T>) -> Unit)? = null, private val onBind: ((Connection<B, S>, B) -> Unit)? = null,
private val onUnbind: ((Event<T>) -> Unit)? = null): ServiceConnection { private val onUnbind: ((Connection<B, S>, B) -> Unit)? = null): ServiceConnection {
class Event<T: IBinder>(val connection: Connection<T>, val binder: T) var binder: B? = null
var binder: T? = null
private set private set
private fun handleUnbind() {
binder?.let {
binder = null
onUnbind?.invoke(this, it)
}
}
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) { override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
binder as T binder as B
this.binder = binder this.binder = binder
onBind?.invoke(Event(this, binder)) onBind?.invoke(this, binder)
} }
override fun onServiceDisconnected(componentName: ComponentName) { override fun onServiceDisconnected(componentName: ComponentName) {
binder?.let { handleUnbind()
binder = null
onUnbind?.invoke(Event(this, it))
}
} }
fun bind(context: Context) { fun bind(context: Context) {
@@ -35,9 +36,6 @@ class Connection<T: IBinder>(private val serviceClass: Class<out Service>,
fun unbind(context: Context) { fun unbind(context: Context) {
context.unbindService(this) context.unbindService(this)
binder?.let { handleUnbind()
binder = null
onUnbind?.invoke(Event(this, it))
}
} }
} }
@@ -0,0 +1,19 @@
package nya.kitsunyan.foxydroid.service
import android.app.Service
import android.content.Intent
import android.os.IBinder
import nya.kitsunyan.foxydroid.utility.extension.android.Android
abstract class ConnectionService<T: IBinder>: Service() {
abstract override fun onBind(intent: Intent): T
fun startSelf() {
val intent = Intent(this, this::class.java)
if (Android.sdk(26)) {
startForegroundService(intent)
} else {
startService(intent)
}
}
}
@@ -3,7 +3,6 @@ package nya.kitsunyan.foxydroid.service
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -31,7 +30,7 @@ import java.security.MessageDigest
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.math.* import kotlin.math.*
class DownloadService: Service() { class DownloadService: ConnectionService<DownloadService.Binder>() {
companion object { companion object {
private const val ACTION_OPEN = "${BuildConfig.APPLICATION_ID}.intent.action.OPEN" private const val ACTION_OPEN = "${BuildConfig.APPLICATION_ID}.intent.action.OPEN"
private const val ACTION_INSTALL = "${BuildConfig.APPLICATION_ID}.intent.action.INSTALL" private const val ACTION_INSTALL = "${BuildConfig.APPLICATION_ID}.intent.action.INSTALL"
@@ -326,7 +325,7 @@ class DownloadService: Service() {
val task = tasks.removeAt(0) val task = tasks.removeAt(0)
if (!started) { if (!started) {
started = true started = true
startAnyService(Intent(this, this::class.java)) startSelf()
} }
val initialState = State.Connecting(task.packageName, task.name) val initialState = State.Connecting(task.packageName, task.name)
stateNotificationBuilder.setWhen(System.currentTimeMillis()) stateNotificationBuilder.setWhen(System.currentTimeMillis())
@@ -3,7 +3,6 @@ package nya.kitsunyan.foxydroid.service
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.app.PendingIntent import android.app.PendingIntent
import android.app.Service
import android.app.job.JobParameters import android.app.job.JobParameters
import android.app.job.JobService import android.app.job.JobService
import android.content.Intent import android.content.Intent
@@ -35,7 +34,7 @@ import java.lang.ref.WeakReference
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import kotlin.math.* import kotlin.math.*
class SyncService: Service() { class SyncService: ConnectionService<SyncService.Binder>() {
companion object { companion object {
private const val ACTION_CANCEL = "${BuildConfig.APPLICATION_ID}.intent.action.CANCEL" private const val ACTION_CANCEL = "${BuildConfig.APPLICATION_ID}.intent.action.CANCEL"
@@ -77,6 +76,7 @@ class SyncService: Service() {
handleNextTask(cancelledTask?.hasUpdates == true) handleNextTask(cancelledTask?.hasUpdates == true)
if (request != SyncRequest.AUTO && started == Started.AUTO) { if (request != SyncRequest.AUTO && started == Started.AUTO) {
started = Started.MANUAL started = Started.MANUAL
startSelf()
handleSetStarted() handleSetStarted()
currentTask?.lastState?.let { publishForegroundState(true, it) } currentTask?.lastState?.let { publishForegroundState(true, it) }
} }
@@ -273,7 +273,6 @@ class SyncService: Service() {
} }
private fun handleSetStarted() { private fun handleSetStarted() {
startAnyService(Intent(this, this::class.java))
stateNotificationBuilder.setWhen(System.currentTimeMillis()) stateNotificationBuilder.setWhen(System.currentTimeMillis())
} }
@@ -287,6 +286,7 @@ class SyncService: Service() {
val newStarted = if (task.manual || lastStarted == Started.MANUAL) Started.MANUAL else Started.AUTO val newStarted = if (task.manual || lastStarted == Started.MANUAL) Started.MANUAL else Started.AUTO
started = newStarted started = newStarted
if (newStarted == Started.MANUAL && lastStarted != Started.MANUAL) { if (newStarted == Started.MANUAL && lastStarted != Started.MANUAL) {
startSelf()
handleSetStarted() handleSetStarted()
} }
val initialState = State.Connecting(repository.name) val initialState = State.Connecting(repository.name)
@@ -379,22 +379,22 @@ class SyncService: Service() {
class Job: JobService() { class Job: JobService() {
private var syncParams: JobParameters? = null private var syncParams: JobParameters? = null
private var syncDisposable: Disposable? = null private var syncDisposable: Disposable? = null
private val syncConnection = Connection<Binder>(SyncService::class.java, onBind = { private val syncConnection = Connection(SyncService::class.java, onBind = { connection, binder ->
syncDisposable = it.binder.finish.subscribe { _ -> syncDisposable = binder.finish.subscribe {
val params = syncParams val params = syncParams
if (params != null) { if (params != null) {
syncParams = null syncParams = null
syncDisposable?.dispose() syncDisposable?.dispose()
syncDisposable = null syncDisposable = null
it.connection.unbind(this) connection.unbind(this)
jobFinished(params, false) jobFinished(params, false)
} }
} }
it.binder.sync(SyncRequest.AUTO) binder.sync(SyncRequest.AUTO)
}, onUnbind = { }, onUnbind = { _, binder ->
syncDisposable?.dispose() syncDisposable?.dispose()
syncDisposable = null syncDisposable = null
it.binder.cancelAuto() binder.cancelAuto()
val params = syncParams val params = syncParams
if (params != null) { if (params != null) {
syncParams = null syncParams = null
@@ -3,7 +3,6 @@ package nya.kitsunyan.foxydroid.utility.extension.android
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo import android.content.pm.PackageInfo
import android.content.pm.Signature import android.content.pm.Signature
import android.database.Cursor import android.database.Cursor
@@ -25,14 +24,6 @@ fun SQLiteDatabase.execWithResult(sql: String) {
val Context.notificationManager: NotificationManager val Context.notificationManager: NotificationManager
get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager get() = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
fun Context.startAnyService(intent: Intent) {
if (Android.sdk(26)) {
startForegroundService(intent)
} else {
startService(intent)
}
}
val PackageInfo.versionCodeCompat: Long val PackageInfo.versionCodeCompat: Long
get() = if (Android.sdk(28)) longVersionCode else @Suppress("DEPRECATION") versionCode.toLong() get() = if (Android.sdk(28)) longVersionCode else @Suppress("DEPRECATION") versionCode.toLong()