Only restore services when permitted
This commit is contained in:
@@ -48,6 +48,7 @@ class App : Application() {
|
|||||||
// alternative to PreferenceManager.getDefaultSharedPreferencesName(this)
|
// alternative to PreferenceManager.getDefaultSharedPreferencesName(this)
|
||||||
deviceStorage.moveSharedPreferencesFrom(this, PreferenceManager(this).sharedPreferencesName)
|
deviceStorage.moveSharedPreferencesFrom(this, PreferenceManager(this).sharedPreferencesName)
|
||||||
deviceStorage.moveDatabaseFrom(this, AppDatabase.DB_NAME)
|
deviceStorage.moveDatabaseFrom(this, AppDatabase.DB_NAME)
|
||||||
|
BootReceiver.migrateIfNecessary()
|
||||||
} else deviceStorage = this
|
} else deviceStorage = this
|
||||||
Services.init { this }
|
Services.init { this }
|
||||||
|
|
||||||
@@ -92,7 +93,6 @@ class App : Application() {
|
|||||||
})
|
})
|
||||||
EBegFragment.init()
|
EBegFragment.init()
|
||||||
if (DhcpWorkaround.shouldEnable) DhcpWorkaround.enable(true)
|
if (DhcpWorkaround.shouldEnable) DhcpWorkaround.enable(true)
|
||||||
BootReceiver.init()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
|||||||
@@ -5,13 +5,11 @@ import android.content.ComponentName
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.widget.Toast
|
import androidx.annotation.RequiresApi
|
||||||
import be.mygod.librootkotlinx.toByteArray
|
import be.mygod.librootkotlinx.toByteArray
|
||||||
import be.mygod.librootkotlinx.toParcelable
|
import be.mygod.librootkotlinx.toParcelable
|
||||||
import be.mygod.vpnhotspot.App.Companion.app
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
import be.mygod.vpnhotspot.util.readableMessage
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
@@ -30,6 +28,7 @@ class BootReceiver : BroadcastReceiver() {
|
|||||||
set(value) = app.packageManager.setComponentEnabledSetting(componentName,
|
set(value) = app.packageManager.setComponentEnabledSetting(componentName,
|
||||||
if (value) PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
if (value) PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
||||||
else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
|
else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
|
||||||
|
private val userEnabled get() = app.pref.getBoolean(KEY, false)
|
||||||
fun onUserSettingUpdated(shouldStart: Boolean) {
|
fun onUserSettingUpdated(shouldStart: Boolean) {
|
||||||
enabled = shouldStart && try {
|
enabled = shouldStart && try {
|
||||||
config
|
config
|
||||||
@@ -39,7 +38,7 @@ class BootReceiver : BroadcastReceiver() {
|
|||||||
}?.startables?.isEmpty() == false
|
}?.startables?.isEmpty() == false
|
||||||
}
|
}
|
||||||
private fun onConfigUpdated(isNotEmpty: Boolean) {
|
private fun onConfigUpdated(isNotEmpty: Boolean) {
|
||||||
enabled = isNotEmpty && app.pref.getBoolean(KEY, false)
|
enabled = isNotEmpty && userEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val FILENAME = "bootconfig"
|
private const val FILENAME = "bootconfig"
|
||||||
@@ -75,16 +74,19 @@ class BootReceiver : BroadcastReceiver() {
|
|||||||
inline fun <reified T> add(value: Startable) = add(T::class.java.name, value)
|
inline fun <reified T> add(value: Startable) = add(T::class.java.name, value)
|
||||||
inline fun <reified T> delete() = delete(T::class.java.name)
|
inline fun <reified T> delete() = delete(T::class.java.name)
|
||||||
|
|
||||||
fun init() {
|
@RequiresApi(24)
|
||||||
if (Build.VERSION.SDK_INT >= 24) {
|
fun migrateIfNecessary() {
|
||||||
val oldFile = File(app.noBackupFilesDir, FILENAME)
|
val oldFile = File(app.noBackupFilesDir, FILENAME)
|
||||||
if (oldFile.canRead()) try {
|
if (oldFile.canRead()) try {
|
||||||
if (!configFile.exists()) oldFile.copyTo(configFile)
|
if (!configFile.exists()) oldFile.copyTo(configFile)
|
||||||
if (!oldFile.delete()) oldFile.deleteOnExit()
|
if (!oldFile.delete()) oldFile.deleteOnExit()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.w(e)
|
Timber.w(e)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
private var started = false
|
||||||
|
private fun startIfNecessary() {
|
||||||
|
if (started) return
|
||||||
val config = try {
|
val config = try {
|
||||||
synchronized(BootReceiver) { config }
|
synchronized(BootReceiver) { config }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -93,12 +95,11 @@ class BootReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
if (config == null || config.startables.isEmpty()) {
|
if (config == null || config.startables.isEmpty()) {
|
||||||
enabled = false
|
enabled = false
|
||||||
} else for (startable in config.startables.values) try {
|
} else for (startable in config.startables.values) startable.start(app)
|
||||||
startable.start(app)
|
started = true
|
||||||
} catch (e: IllegalStateException) { // ForegroundServiceStartNotAllowedException
|
}
|
||||||
Timber.w(e)
|
fun startIfEnabled() {
|
||||||
Toast.makeText(app, e.readableMessage, Toast.LENGTH_LONG).show()
|
if (started && userEnabled) startIfNecessary()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,5 +110,11 @@ class BootReceiver : BroadcastReceiver() {
|
|||||||
@Parcelize
|
@Parcelize
|
||||||
private data class Config(var startables: MutableMap<String, Startable> = mutableMapOf()) : Parcelable
|
private data class Config(var startables: MutableMap<String, Startable> = mutableMapOf()) : Parcelable
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) { }
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
when (intent.action) {
|
||||||
|
Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_LOCKED_BOOT_COMPLETED, Intent.ACTION_MY_PACKAGE_REPLACED -> {
|
||||||
|
if (userEnabled) startIfNecessary() else enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService(), CoroutineScope {
|
|||||||
override fun onBind(intent: Intent?) = binder
|
override fun onBind(intent: Intent?) = binder
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
BootReceiver.startIfEnabled()
|
||||||
if (binder.iface != null) return START_STICKY
|
if (binder.iface != null) return START_STICKY
|
||||||
binder.iface = ""
|
binder.iface = ""
|
||||||
updateNotification() // show invisible foreground notification to avoid being killed
|
updateNotification() // show invisible foreground notification to avoid being killed
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
|
|||||||
SmartSnackbar.Register(binding.fragmentHolder)
|
SmartSnackbar.Register(binding.fragmentHolder)
|
||||||
WifiDoubleLock.ActivityListener(this)
|
WifiDoubleLock.ActivityListener(this)
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
|
BootReceiver.startIfEnabled()
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
onAppUpdateAvailable(null)
|
onAppUpdateAvailable(null)
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
|
|||||||
* startService Step 1
|
* startService Step 1
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
BootReceiver.startIfEnabled()
|
||||||
if (status != Status.IDLE) return START_NOT_STICKY
|
if (status != Status.IDLE) return START_NOT_STICKY
|
||||||
val channel = channel ?: return START_NOT_STICKY.also { stopSelf() }
|
val channel = channel ?: return START_NOT_STICKY.also { stopSelf() }
|
||||||
status = Status.STARTING
|
status = Status.STARTING
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
|
|||||||
override fun onBind(intent: Intent?) = binder
|
override fun onBind(intent: Intent?) = binder
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
BootReceiver.startIfEnabled()
|
||||||
// call this first just in case we are shutting down immediately
|
// call this first just in case we are shutting down immediately
|
||||||
if (Build.VERSION.SDK_INT >= 26) updateNotification()
|
if (Build.VERSION.SDK_INT >= 26) updateNotification()
|
||||||
launch {
|
launch {
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package be.mygod.vpnhotspot.util
|
package be.mygod.vpnhotspot.util
|
||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
|
import android.content.Intent
|
||||||
import android.content.ServiceConnection
|
import android.content.ServiceConnection
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.service.quicksettings.Tile
|
import android.service.quicksettings.Tile
|
||||||
import android.service.quicksettings.TileService
|
import android.service.quicksettings.TileService
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
|
import be.mygod.vpnhotspot.BootReceiver
|
||||||
|
|
||||||
@RequiresApi(24)
|
@RequiresApi(24)
|
||||||
abstract class KillableTileService : TileService(), ServiceConnection {
|
abstract class KillableTileService : TileService(), ServiceConnection {
|
||||||
@@ -25,4 +27,6 @@ abstract class KillableTileService : TileService(), ServiceConnection {
|
|||||||
onClick()
|
onClick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?) = super.onBind(intent).also { BootReceiver.startIfEnabled() }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user