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" />
+