👻 Clean up services
This commit is contained in:
parent
ccfdff7fd8
commit
6128fd32f9
@ -118,10 +118,6 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".service.BitmessageService"
|
||||
android:description="@string/bitmessage_service_description"
|
||||
android:exported="false" />
|
||||
<service
|
||||
android:name=".service.ProofOfWorkService"
|
||||
android:exported="false" />
|
||||
@ -154,6 +150,11 @@
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service
|
||||
android:name=".service.CleanupService"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
<service
|
||||
android:name=".service.BatchProcessorService"
|
||||
android:exported="false" />
|
||||
|
@ -25,7 +25,7 @@ import android.support.v4.app.NotificationCompat
|
||||
import ch.dissem.apps.abit.MainActivity
|
||||
import ch.dissem.apps.abit.R
|
||||
import ch.dissem.apps.abit.service.BitmessageIntentService
|
||||
import ch.dissem.apps.abit.service.BitmessageService
|
||||
import ch.dissem.apps.abit.service.NodeStartupService
|
||||
import java.util.*
|
||||
import kotlin.concurrent.fixedRateTimer
|
||||
|
||||
@ -51,9 +51,9 @@ class NetworkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
|
||||
@SuppressLint("StringFormatMatches")
|
||||
private fun update(): Boolean {
|
||||
val running = BitmessageService.isRunning
|
||||
val running = NodeStartupService.isRunning
|
||||
builder.setOngoing(running)
|
||||
val connections = BitmessageService.status.getProperty("network", "connections")
|
||||
val connections = NodeStartupService.status.getProperty("network", "connections")
|
||||
if (!running) {
|
||||
builder.setSmallIcon(R.drawable.ic_notification_full_node_disconnected)
|
||||
builder.setContentText(ctx.getString(R.string.connection_info_disconnected))
|
||||
@ -112,7 +112,6 @@ class NetworkNotification(ctx: Context) : AbstractNotification(ctx) {
|
||||
timer = fixedRateTimer(initialDelay = 10000, period = 10000) {
|
||||
if (!update()) {
|
||||
cancel()
|
||||
ctx.stopService(Intent(ctx, BitmessageService::class.java))
|
||||
}
|
||||
super@NetworkNotification.show()
|
||||
}
|
||||
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.service
|
||||
|
||||
import android.app.Service
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.Handler
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.utils.Property
|
||||
import org.jetbrains.anko.doAsync
|
||||
|
||||
/**
|
||||
* Define a Service that returns an IBinder for the
|
||||
* sync adapter class, allowing the sync adapter framework to call
|
||||
* onPerformSync().
|
||||
*/
|
||||
class BitmessageService : Service() {
|
||||
|
||||
private val bmc: BitmessageContext by lazy { Singleton.getBitmessageContext(this) }
|
||||
private lateinit var notification: NetworkNotification
|
||||
|
||||
private val connectivityReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
if (bmc.isRunning() && !preferences.connectionAllowed) {
|
||||
bmc.shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val cleanupHandler = Handler()
|
||||
private val cleanupTask: Runnable = object : Runnable {
|
||||
override fun run() {
|
||||
bmc.cleanup()
|
||||
if (isRunning) {
|
||||
cleanupHandler.postDelayed(this, 24 * 60 * 60 * 1000L) // once a day
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
registerReceiver(
|
||||
connectivityReceiver,
|
||||
IntentFilter().apply {
|
||||
addAction(ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
addAction(Intent.ACTION_BATTERY_CHANGED)
|
||||
}
|
||||
)
|
||||
notification = NetworkNotification(this)
|
||||
running = false
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (!isRunning) {
|
||||
running = true
|
||||
notification.connecting()
|
||||
if (!bmc.isRunning()) {
|
||||
bmc.startup()
|
||||
}
|
||||
notification.show()
|
||||
cleanupHandler.postDelayed(cleanupTask, 24 * 60 * 60 * 1000L)
|
||||
}
|
||||
return Service.START_STICKY
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (bmc.isRunning()) {
|
||||
bmc.shutdown()
|
||||
}
|
||||
running = false
|
||||
notification.showShutdown()
|
||||
cleanupHandler.removeCallbacks(cleanupTask)
|
||||
doAsync {
|
||||
bmc.cleanup()
|
||||
}
|
||||
unregisterReceiver(connectivityReceiver)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent) = null
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var running = false
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = running && Singleton.bitmessageContext?.isRunning() == true
|
||||
|
||||
val status: Property
|
||||
get() = Singleton.bitmessageContext?.status() ?: Property("bitmessage context")
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package ch.dissem.apps.abit.service
|
||||
|
||||
import android.app.job.JobParameters
|
||||
import android.app.job.JobService
|
||||
import org.jetbrains.anko.doAsync
|
||||
|
||||
class CleanupService : JobService() {
|
||||
|
||||
override fun onStartJob(params: JobParameters?): Boolean {
|
||||
doAsync {
|
||||
Singleton.getBitmessageContext(this@CleanupService).cleanup()
|
||||
jobFinished(params, false)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onStopJob(params: JobParameters?) = false
|
||||
}
|
@ -2,8 +2,17 @@ package ch.dissem.apps.abit.service
|
||||
|
||||
import android.app.job.JobParameters
|
||||
import android.app.job.JobService
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification
|
||||
import ch.dissem.apps.abit.util.network
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.utils.Property
|
||||
import org.jetbrains.anko.doAsync
|
||||
|
||||
/**
|
||||
* Starts the full node if
|
||||
@ -13,14 +22,55 @@ import ch.dissem.apps.abit.util.preferences
|
||||
* And stops it when the preconditions for the job (unmetered network) aren't met anymore.
|
||||
*/
|
||||
class NodeStartupService : JobService() {
|
||||
private val bmc: BitmessageContext by lazy { Singleton.getBitmessageContext(this) }
|
||||
|
||||
private lateinit var notification: NetworkNotification
|
||||
|
||||
private val connectivityReceiver: BroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
if (bmc.isRunning() && !preferences.connectionAllowed) {
|
||||
bmc.shutdown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartJob(params: JobParameters?): Boolean {
|
||||
if (preferences.online) {
|
||||
network.scheduleNodeStart()
|
||||
registerReceiver(
|
||||
connectivityReceiver,
|
||||
IntentFilter().apply {
|
||||
addAction(ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
addAction(Intent.ACTION_BATTERY_CHANGED)
|
||||
}
|
||||
)
|
||||
notification = NetworkNotification(this)
|
||||
NodeStartupService.running = false
|
||||
|
||||
if (!isRunning) {
|
||||
running = true
|
||||
notification.connecting()
|
||||
if (!bmc.isRunning()) {
|
||||
bmc.startup()
|
||||
}
|
||||
notification.show()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (bmc.isRunning()) {
|
||||
bmc.shutdown()
|
||||
}
|
||||
running = false
|
||||
notification.showShutdown()
|
||||
doAsync {
|
||||
bmc.cleanup()
|
||||
}
|
||||
unregisterReceiver(connectivityReceiver)
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't actually stop the service, otherwise it will be stopped after 1 or 10 minutes
|
||||
* depending on Android version.
|
||||
@ -30,4 +80,14 @@ class NodeStartupService : JobService() {
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var running = false
|
||||
|
||||
val isRunning: Boolean
|
||||
get() = running && Singleton.bitmessageContext?.isRunning() == true
|
||||
|
||||
val status: Property
|
||||
get() = Singleton.bitmessageContext?.status() ?: Property("bitmessage context")
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,17 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import ch.dissem.apps.abit.dialog.FullNodeDialogActivity
|
||||
import ch.dissem.apps.abit.service.BitmessageService
|
||||
import ch.dissem.apps.abit.service.CleanupService
|
||||
import ch.dissem.apps.abit.service.NodeStartupService
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
val Context.network get() = NetworkUtils.getInstance(this)
|
||||
|
||||
class NetworkUtils internal constructor(private val ctx: Context) {
|
||||
|
||||
private val jobScheduler by lazy { ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler }
|
||||
|
||||
fun enableNode(ask: Boolean = true) {
|
||||
if (ask && !ctx.preferences.connectionAllowed) {
|
||||
// Ask for connection
|
||||
@ -31,24 +34,32 @@ class NetworkUtils internal constructor(private val ctx: Context) {
|
||||
}
|
||||
|
||||
fun disableNode() {
|
||||
ctx.stopService(Intent(ctx, BitmessageService::class.java))
|
||||
jobScheduler.cancelAll()
|
||||
}
|
||||
|
||||
fun scheduleNodeStart() {
|
||||
val jobScheduler = ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
||||
val serviceComponent = ComponentName(ctx, NodeStartupService::class.java)
|
||||
val builder = JobInfo.Builder(0, serviceComponent)
|
||||
when {
|
||||
ctx.preferences.wifiOnly ->
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ->
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NOT_ROAMING)
|
||||
else ->
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||
JobInfo.Builder(0, ComponentName(ctx, NodeStartupService::class.java)).let { builder ->
|
||||
when {
|
||||
ctx.preferences.wifiOnly ->
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ->
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NOT_ROAMING)
|
||||
else ->
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||
}
|
||||
builder.setRequiresCharging(ctx.preferences.requireCharging)
|
||||
builder.setPersisted(true)
|
||||
|
||||
jobScheduler.schedule(builder.build())
|
||||
}
|
||||
|
||||
JobInfo.Builder(1, ComponentName(ctx, CleanupService::class.java)).let { builder ->
|
||||
builder.setPeriodic(TimeUnit.DAYS.toMillis(1))
|
||||
builder.setRequiresDeviceIdle(true)
|
||||
builder.setRequiresCharging(true)
|
||||
|
||||
jobScheduler.schedule(builder.build())
|
||||
}
|
||||
builder.setRequiresCharging(ctx.preferences.requireCharging)
|
||||
builder.setPersisted(true)
|
||||
jobScheduler.schedule(builder.build())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
Loading…
Reference in New Issue
Block a user