diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0f7bfcd..e8ed1be 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -118,10 +118,6 @@
-
@@ -154,6 +150,11 @@
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
+
+
diff --git a/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.kt b/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.kt
index abc024e..170e787 100644
--- a/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.kt
+++ b/app/src/main/java/ch/dissem/apps/abit/notification/NetworkNotification.kt
@@ -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()
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/service/BitmessageService.kt b/app/src/main/java/ch/dissem/apps/abit/service/BitmessageService.kt
deleted file mode 100644
index 0add64e..0000000
--- a/app/src/main/java/ch/dissem/apps/abit/service/BitmessageService.kt
+++ /dev/null
@@ -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")
- }
-}
diff --git a/app/src/main/java/ch/dissem/apps/abit/service/CleanupService.kt b/app/src/main/java/ch/dissem/apps/abit/service/CleanupService.kt
new file mode 100644
index 0000000..bd2a869
--- /dev/null
+++ b/app/src/main/java/ch/dissem/apps/abit/service/CleanupService.kt
@@ -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
+}
diff --git a/app/src/main/java/ch/dissem/apps/abit/service/NodeStartupService.kt b/app/src/main/java/ch/dissem/apps/abit/service/NodeStartupService.kt
index 97087fb..9a2b8e2 100644
--- a/app/src/main/java/ch/dissem/apps/abit/service/NodeStartupService.kt
+++ b/app/src/main/java/ch/dissem/apps/abit/service/NodeStartupService.kt
@@ -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")
+ }
}
diff --git a/app/src/main/java/ch/dissem/apps/abit/util/NetworkUtils.kt b/app/src/main/java/ch/dissem/apps/abit/util/NetworkUtils.kt
index 9e0c81e..3ee1836 100644
--- a/app/src/main/java/ch/dissem/apps/abit/util/NetworkUtils.kt
+++ b/app/src/main/java/ch/dissem/apps/abit/util/NetworkUtils.kt
@@ -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 {