From f557e201eba94f1637ed1c7910c05ab6d2bd4131 Mon Sep 17 00:00:00 2001 From: arm64v8a <48624112+arm64v8a@users.noreply.github.com> Date: Thu, 27 Apr 2023 21:18:04 +0900 Subject: [PATCH] feat: boot receiver --- app/src/main/AndroidManifest.xml | 12 ++++++ .../io/nekohasekai/sagernet/BootReceiver.kt | 42 +++++++++++++++++++ .../java/io/nekohasekai/sagernet/Constants.kt | 2 + .../io/nekohasekai/sagernet/bg/BaseService.kt | 2 + .../io/nekohasekai/sagernet/bg/TileService.kt | 5 ++- .../sagernet/database/DataStore.kt | 1 + app/src/main/res/xml/global_preferences.xml | 6 +++ 7 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/io/nekohasekai/sagernet/BootReceiver.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e10b352b2..fae028dab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -305,6 +305,18 @@ android:authorities="${applicationId}.androidx-startup" tools:node="remove" /> + + + + + + + + diff --git a/app/src/main/java/io/nekohasekai/sagernet/BootReceiver.kt b/app/src/main/java/io/nekohasekai/sagernet/BootReceiver.kt new file mode 100644 index 000000000..fd037ad49 --- /dev/null +++ b/app/src/main/java/io/nekohasekai/sagernet/BootReceiver.kt @@ -0,0 +1,42 @@ +package io.nekohasekai.sagernet + +import android.content.BroadcastReceiver +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import io.nekohasekai.sagernet.bg.SubscriptionUpdater +import io.nekohasekai.sagernet.database.DataStore +import io.nekohasekai.sagernet.ktx.app +import io.nekohasekai.sagernet.ktx.runOnDefaultDispatcher + +class BootReceiver : BroadcastReceiver() { + companion object { + private val componentName by lazy { ComponentName(app, BootReceiver::class.java) } + var enabled: Boolean + get() = app.packageManager.getComponentEnabledSetting(componentName) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED + set(value) = app.packageManager.setComponentEnabledSetting( + componentName, if (value) PackageManager.COMPONENT_ENABLED_STATE_ENABLED + else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP + ) + } + + override fun onReceive(context: Context, intent: Intent) { + runOnDefaultDispatcher { + SubscriptionUpdater.reconfigureUpdater() + } + + if (!DataStore.persistAcrossReboot) { // sanity check + enabled = false + return + } + + val doStart = when (intent.action) { + Intent.ACTION_LOCKED_BOOT_COMPLETED -> false // DataStore.directBootAware + else -> Build.VERSION.SDK_INT < 24 || SagerNet.user.isUserUnlocked + } && DataStore.selectedProxy > 0 + + if (doStart) SagerNet.startService() + } +} diff --git a/app/src/main/java/io/nekohasekai/sagernet/Constants.kt b/app/src/main/java/io/nekohasekai/sagernet/Constants.kt index f63757af4..7f479f361 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/Constants.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/Constants.kt @@ -26,6 +26,8 @@ object Key { const val DB_PUBLIC = "configuration.db" const val DB_PROFILE = "sager_net.db" + const val PERSIST_ACROSS_REBOOT = "isAutoConnect" + const val APP_EXPERT = "isExpert" const val APP_THEME = "appTheme" const val NIGHT_THEME = "nightTheme" diff --git a/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt b/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt index 185bb06d7..5ed6623bf 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/bg/BaseService.kt @@ -29,6 +29,7 @@ import android.net.Network import android.os.* import android.widget.Toast import io.nekohasekai.sagernet.Action +import io.nekohasekai.sagernet.BootReceiver import io.nekohasekai.sagernet.R import io.nekohasekai.sagernet.SagerNet import io.nekohasekai.sagernet.aidl.AppStatsList @@ -503,6 +504,7 @@ class BaseService { val proxy = ProxyInstance(profile, this) data.proxy = proxy + BootReceiver.enabled = DataStore.persistAcrossReboot if (!data.closeReceiverRegistered) { registerReceiver(data.receiver, IntentFilter().apply { addAction(Action.RELOAD) diff --git a/app/src/main/java/io/nekohasekai/sagernet/bg/TileService.kt b/app/src/main/java/io/nekohasekai/sagernet/bg/TileService.kt index 5c56d9e5f..ade70bd70 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/bg/TileService.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/bg/TileService.kt @@ -60,7 +60,7 @@ class TileService : BaseTileService(), SagerConnection.Callback { } override fun onClick() { - toggle() + if (isLocked) unlockAndRun(this::toggle) else toggle() } private fun updateTile(serviceState: BaseService.State, profileName: () -> String?) { @@ -72,15 +72,18 @@ class TileService : BaseTileService(), SagerConnection.Callback { icon = iconBusy state = Tile.STATE_ACTIVE } + BaseService.State.Connected -> { icon = iconConnected label = profileName() state = Tile.STATE_ACTIVE } + BaseService.State.Stopping -> { icon = iconBusy state = Tile.STATE_UNAVAILABLE } + BaseService.State.Stopped -> { icon = iconIdle state = Tile.STATE_INACTIVE diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt b/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt index d724e307d..38d271c96 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt @@ -182,6 +182,7 @@ object DataStore : OnPreferenceDataStoreChangeListener { var bypass by configurationStore.boolean(Key.BYPASS_MODE) { true } var individual by configurationStore.string(Key.INDIVIDUAL) var showDirectSpeed by configurationStore.boolean(Key.SHOW_DIRECT_SPEED) { true } + val persistAcrossReboot by configurationStore.boolean(Key.PERSIST_ACROSS_REBOOT) { false } var requireHttp by configurationStore.boolean(Key.REQUIRE_HTTP) { true } var appendHttpProxy by configurationStore.boolean(Key.APPEND_HTTP_PROXY) { true } diff --git a/app/src/main/res/xml/global_preferences.xml b/app/src/main/res/xml/global_preferences.xml index 7840cb936..31338301a 100644 --- a/app/src/main/res/xml/global_preferences.xml +++ b/app/src/main/res/xml/global_preferences.xml @@ -6,6 +6,12 @@ app:icon="@drawable/ic_baseline_android_24" app:key="nekoPlugins" app:title="@string/neko_plugin" /> +