From 852e38b97d31eb0cae6382cb46ce07de6ad3f373 Mon Sep 17 00:00:00 2001 From: Christian Basler Date: Sat, 19 Aug 2017 08:17:52 +0200 Subject: [PATCH] Use JobScheduler to make the "WiFi-only" feature work properly newer Android versions. I'm considering dropping support for KitKat, as we have now double the code for the same feature. --- app/src/main/AndroidManifest.xml | 11 ++- .../ch/dissem/apps/abit/MainActivity.java | 17 +---- .../abit/dialog/FullNodeDialogActivity.java | 6 ++ .../notification/NewMessageNotification.kt | 2 +- .../notification/ProofOfWorkNotification.kt | 2 +- .../abit/service/BitmessageIntentService.java | 75 ------------------- .../abit/service/BitmessageIntentService.kt | 63 ++++++++++++++++ .../apps/abit/service/ProofOfWorkService.kt | 2 +- .../apps/abit/service/StartServiceReceiver.kt | 18 +++++ .../abit/service/StartupNodeOnWifiService.kt | 31 ++++++++ .../ch/dissem/apps/abit/util/NetworkUtils.kt | 65 ++++++++++++++++ app/src/main/res/values-v21/attrs.xml | 5 ++ app/src/main/res/values/attrs.xml | 5 ++ build.gradle | 2 +- 14 files changed, 211 insertions(+), 93 deletions(-) delete mode 100644 app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.java create mode 100644 app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.kt create mode 100644 app/src/main/java/ch/dissem/apps/abit/service/StartServiceReceiver.kt create mode 100644 app/src/main/java/ch/dissem/apps/abit/service/StartupNodeOnWifiService.kt create mode 100644 app/src/main/java/ch/dissem/apps/abit/util/NetworkUtils.kt create mode 100644 app/src/main/res/values-v21/attrs.xml create mode 100644 app/src/main/res/values/attrs.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e9e5a28..45aef4f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -174,11 +174,20 @@ android:exported="false"/> - + + + + + + + = Build.VERSION_CODES.LOLLIPOP) { + NetworkUtils.scheduleNodeStart(getApplicationContext()); + } finish(); } }); diff --git a/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.kt b/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.kt index c603684..e1c40f2 100644 --- a/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.kt +++ b/app/src/main/java/ch/dissem/apps/abit/notification/NewMessageNotification.kt @@ -37,7 +37,7 @@ import ch.dissem.bitmessage.entity.Plaintext import android.app.PendingIntent.FLAG_UPDATE_CURRENT import ch.dissem.apps.abit.MainActivity.EXTRA_REPLY_TO_MESSAGE import ch.dissem.apps.abit.MainActivity.EXTRA_SHOW_MESSAGE -import ch.dissem.apps.abit.service.BitmessageIntentService.EXTRA_DELETE_MESSAGE +import ch.dissem.apps.abit.service.BitmessageIntentService.Companion.EXTRA_DELETE_MESSAGE import ch.dissem.apps.abit.util.Drawables.toBitmap class NewMessageNotification(ctx: Context) : AbstractNotification(ctx) { diff --git a/app/src/main/java/ch/dissem/apps/abit/notification/ProofOfWorkNotification.kt b/app/src/main/java/ch/dissem/apps/abit/notification/ProofOfWorkNotification.kt index eae9640..541e837 100644 --- a/app/src/main/java/ch/dissem/apps/abit/notification/ProofOfWorkNotification.kt +++ b/app/src/main/java/ch/dissem/apps/abit/notification/ProofOfWorkNotification.kt @@ -91,7 +91,7 @@ class ProofOfWorkNotification(ctx: Context) : AbstractNotification(ctx) { } } - fun finished(item: ProofOfWorkService.PowItem) { + fun finished() { timer?.cancel() progress = 0 progressMax = 0 diff --git a/app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.java b/app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.java deleted file mode 100644 index ad17d9d..0000000 --- a/app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.java +++ /dev/null @@ -1,75 +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.IntentService; -import android.content.Intent; - -import ch.dissem.apps.abit.dialog.FullNodeDialogActivity; -import ch.dissem.apps.abit.util.Preferences; -import ch.dissem.bitmessage.BitmessageContext; -import ch.dissem.bitmessage.entity.Plaintext; - -import static ch.dissem.apps.abit.MainActivity.updateNodeSwitch; - -/** - * @author Christian Basler - */ - -public class BitmessageIntentService extends IntentService { - public static final String EXTRA_DELETE_MESSAGE = "ch.dissem.abit.DeleteMessage"; - public static final String EXTRA_STARTUP_NODE = "ch.dissem.abit.StartFullNode"; - public static final String EXTRA_SHUTDOWN_NODE = "ch.dissem.abit.StopFullNode"; - - private BitmessageContext bmc; - - public BitmessageIntentService() { - super("BitmessageIntentService"); - } - - @Override - public void onCreate() { - super.onCreate(); - bmc = Singleton.getBitmessageContext(this); - } - - @Override - protected void onHandleIntent(Intent intent) { - if (intent.hasExtra(EXTRA_DELETE_MESSAGE)) { - Plaintext item = (Plaintext) intent.getSerializableExtra(EXTRA_DELETE_MESSAGE); - bmc.labeler().delete(item); - bmc.messages().save(item); - Singleton.getMessageListener(this).resetNotification(); - } - if (intent.hasExtra(EXTRA_STARTUP_NODE)) { - if (Preferences.isConnectionAllowed(this)) { - Preferences.setFullNodeActive(this, true); - startService(new Intent(this, BitmessageService.class)); - updateNodeSwitch(); - } else { - Intent dialogIntent = new Intent(this, FullNodeDialogActivity.class); - dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(dialogIntent); - sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); - } - } - if (intent.hasExtra(EXTRA_SHUTDOWN_NODE)) { - Preferences.setFullNodeActive(this, false); - stopService(new Intent(this, BitmessageService.class)); - } - } -} diff --git a/app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.kt b/app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.kt new file mode 100644 index 0000000..6b52178 --- /dev/null +++ b/app/src/main/java/ch/dissem/apps/abit/service/BitmessageIntentService.kt @@ -0,0 +1,63 @@ +/* + * 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.IntentService +import android.content.Intent + +import ch.dissem.apps.abit.dialog.FullNodeDialogActivity +import ch.dissem.apps.abit.util.NetworkUtils +import ch.dissem.apps.abit.util.Preferences +import ch.dissem.bitmessage.BitmessageContext +import ch.dissem.bitmessage.entity.Plaintext + +import ch.dissem.apps.abit.MainActivity.updateNodeSwitch + +/** + * @author Christian Basler + */ + +class BitmessageIntentService : IntentService("BitmessageIntentService") { + + private lateinit var bmc: BitmessageContext + + override fun onCreate() { + super.onCreate() + bmc = Singleton.getBitmessageContext(this) + } + + override fun onHandleIntent(intent: Intent?) { + if (intent!!.hasExtra(EXTRA_DELETE_MESSAGE)) { + val item = intent.getSerializableExtra(EXTRA_DELETE_MESSAGE) as Plaintext + bmc.labeler.delete(item) + bmc.messages.save(item) + Singleton.getMessageListener(this).resetNotification() + } + if (intent.hasExtra(EXTRA_STARTUP_NODE)) { + NetworkUtils.enableNode(this) + } + if (intent.hasExtra(EXTRA_SHUTDOWN_NODE)) { + NetworkUtils.disableNode(this) + } + } + + companion object { + const val EXTRA_DELETE_MESSAGE = "ch.dissem.abit.DeleteMessage" + const val EXTRA_STARTUP_NODE = "ch.dissem.abit.StartFullNode" + const val EXTRA_SHUTDOWN_NODE = "ch.dissem.abit.StopFullNode" + } +} diff --git a/app/src/main/java/ch/dissem/apps/abit/service/ProofOfWorkService.kt b/app/src/main/java/ch/dissem/apps/abit/service/ProofOfWorkService.kt index 443e59c..25e4731 100644 --- a/app/src/main/java/ch/dissem/apps/abit/service/ProofOfWorkService.kt +++ b/app/src/main/java/ch/dissem/apps/abit/service/ProofOfWorkService.kt @@ -73,7 +73,7 @@ class ProofOfWorkService : Service() { val startTime = System.currentTimeMillis() engine.calculateNonce(item.initialHash, item.targetValue, object : ProofOfWorkEngine.Callback { override fun onNonceCalculated(initialHash: ByteArray, nonce: ByteArray) { - notification.finished(item) + notification.finished() val time = System.currentTimeMillis() - startTime PowStats.addPow(this@ProofOfWorkService, time, item.targetValue) try { diff --git a/app/src/main/java/ch/dissem/apps/abit/service/StartServiceReceiver.kt b/app/src/main/java/ch/dissem/apps/abit/service/StartServiceReceiver.kt new file mode 100644 index 0000000..2d9bec6 --- /dev/null +++ b/app/src/main/java/ch/dissem/apps/abit/service/StartServiceReceiver.kt @@ -0,0 +1,18 @@ +package ch.dissem.apps.abit.service + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import ch.dissem.apps.abit.util.NetworkUtils +import ch.dissem.apps.abit.util.Preferences + +/** + * Created by chrigu on 18.08.17. + */ +class StartServiceReceiver : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent?) { + if (Preferences.isFullNodeActive(context)) { + NetworkUtils.enableNode(context, false) + } + } +} diff --git a/app/src/main/java/ch/dissem/apps/abit/service/StartupNodeOnWifiService.kt b/app/src/main/java/ch/dissem/apps/abit/service/StartupNodeOnWifiService.kt new file mode 100644 index 0000000..ef4d7c5 --- /dev/null +++ b/app/src/main/java/ch/dissem/apps/abit/service/StartupNodeOnWifiService.kt @@ -0,0 +1,31 @@ +package ch.dissem.apps.abit.service + +import android.app.job.JobParameters +import android.app.job.JobService +import android.content.Intent +import android.os.Build +import android.support.annotation.RequiresApi +import ch.dissem.apps.abit.util.Preferences + +/** + * Created by chrigu on 18.08.17. + */ +@RequiresApi(Build.VERSION_CODES.LOLLIPOP) +class StartupNodeOnWifiService : JobService() { + override fun onStartJob(params: JobParameters?): Boolean { + val bmc = Singleton.getBitmessageContext(this) + if (Preferences.isFullNodeActive(this) && !bmc.isRunning()) { + applicationContext.startService(Intent(this, BitmessageService::class.java)) + } + return true + } + + override fun onStopJob(params: JobParameters?): Boolean { + if (Preferences.isWifiOnly(this)) { + Singleton.getBitmessageContext(this).shutdown() + return Preferences.isFullNodeActive(this) + } else { + return false + } + } +} 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 new file mode 100644 index 0000000..e566e47 --- /dev/null +++ b/app/src/main/java/ch/dissem/apps/abit/util/NetworkUtils.kt @@ -0,0 +1,65 @@ +package ch.dissem.apps.abit.util + +import android.app.Activity +import android.app.job.JobInfo +import android.app.job.JobScheduler +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.os.Build +import android.support.annotation.RequiresApi +import ch.dissem.apps.abit.MainActivity.updateNodeSwitch +import ch.dissem.apps.abit.dialog.FullNodeDialogActivity +import ch.dissem.apps.abit.service.BitmessageService +import ch.dissem.apps.abit.service.StartupNodeOnWifiService + + +/** + * Created by chrigu on 18.08.17. + */ +object NetworkUtils { + + @JvmStatic + @JvmOverloads + fun enableNode(ctx: Context, ask: Boolean = true) { + Preferences.setFullNodeActive(ctx, true) + if (Preferences.isWifiOnly(ctx)) { + if (Preferences.isConnectionAllowed(ctx)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + scheduleNodeStart(ctx) + } else { + ctx.startService(Intent(ctx, BitmessageService::class.java)) + updateNodeSwitch() + } + } else if (ask) { + val dialogIntent = Intent(ctx, FullNodeDialogActivity::class.java) + if (ctx !is Activity) { + dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + ctx.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) + } + ctx.startActivity(dialogIntent) + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + scheduleNodeStart(ctx) + } + } else { + ctx.startService(Intent(ctx, BitmessageService::class.java)) + updateNodeSwitch() + } + } + + @JvmStatic + fun disableNode(ctx: Context) { + Preferences.setFullNodeActive(ctx, false) + ctx.stopService(Intent(ctx, BitmessageService::class.java)) + } + + @JvmStatic + @RequiresApi(Build.VERSION_CODES.LOLLIPOP) + fun scheduleNodeStart(ctx: Context) { + val serviceComponent = ComponentName(ctx, StartupNodeOnWifiService::class.java) + val builder = JobInfo.Builder(0, serviceComponent) + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) + val jobScheduler = ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler + jobScheduler.schedule(builder.build()); + } +} diff --git a/app/src/main/res/values-v21/attrs.xml b/app/src/main/res/values-v21/attrs.xml new file mode 100644 index 0000000..1c22dab --- /dev/null +++ b/app/src/main/res/values-v21/attrs.xml @@ -0,0 +1,5 @@ + + + false + true + diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..f79595e --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,5 @@ + + + true + false + diff --git a/build.gradle b/build.gradle index 8364eed..2a2253a 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ configurations.all { } buildscript { - ext.kotlin_version = '1.1.3-2' + ext.kotlin_version = '1.1.4-2' ext.anko_version = '0.10.1' repositories { jcenter()