Add ignore battery optimizations card

This commit is contained in:
世界
2023-07-16 13:29:55 +08:00
parent f9fef233ca
commit 948312e9e4
6 changed files with 269 additions and 169 deletions

View File

@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission <uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES" android:name="android.permission.QUERY_ALL_PACKAGES"

View File

@@ -4,6 +4,7 @@ import android.app.Application
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.os.PowerManager
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import go.Seq import go.Seq
import io.nekohasekai.sfa.bg.UpdateProfileWork import io.nekohasekai.sfa.bg.UpdateProfileWork
@@ -35,6 +36,7 @@ class Application : Application() {
val notification by lazy { application.getSystemService<NotificationManager>()!! } val notification by lazy { application.getSystemService<NotificationManager>()!! }
val connectivity by lazy { application.getSystemService<ConnectivityManager>()!! } val connectivity by lazy { application.getSystemService<ConnectivityManager>()!! }
val packageManager by lazy { application.packageManager } val packageManager by lazy { application.packageManager }
val powerManager by lazy { application.getSystemService<PowerManager>()!! }
} }
} }

View File

@@ -268,7 +268,8 @@ class DashboardFragment : Fragment(), CommandClientHandler {
return return
} }
runCatching { runCatching {
Libbox.newStandaloneCommandClient(mainActivity.filesDir.absolutePath).serviceReload() Libbox.newStandaloneCommandClient(mainActivity.filesDir.absolutePath)
.serviceReload()
}.onFailure { }.onFailure {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
mainActivity.errorDialogBuilder(it).show() mainActivity.errorDialogBuilder(it).show()

View File

@@ -1,14 +1,19 @@
package io.nekohasekai.sfa.ui.main package io.nekohasekai.sfa.ui.main
import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.isGone
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.microsoft.appcenter.AppCenter import com.microsoft.appcenter.AppCenter
import com.microsoft.appcenter.distribute.Distribute import com.microsoft.appcenter.distribute.Distribute
import io.nekohasekai.libbox.Libbox import io.nekohasekai.libbox.Libbox
import io.nekohasekai.sfa.Application
import io.nekohasekai.sfa.R import io.nekohasekai.sfa.R
import io.nekohasekai.sfa.constant.EnabledType import io.nekohasekai.sfa.constant.EnabledType
import io.nekohasekai.sfa.database.Settings import io.nekohasekai.sfa.database.Settings
@@ -35,6 +40,14 @@ class SettingsFragment : Fragment() {
return binding.root return binding.root
} }
private val requestIgnoreBatteryOptimizations = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { _ ->
lifecycleScope.launch(Dispatchers.IO) {
reloadSettings()
}
}
private fun onCreate() { private fun onCreate() {
val activity = activity as MainActivity? ?: return val activity = activity as MainActivity? ?: return
binding.versionText.text = Libbox.version() binding.versionText.text = Libbox.version()
@@ -80,6 +93,17 @@ class SettingsFragment : Fragment() {
Settings.disableMemoryLimit = !newValue Settings.disableMemoryLimit = !newValue
} }
} }
binding.dontKillMyAppButton.setOnClickListener {
it.context.launchCustomTab("https://dontkillmyapp.com/")
}
binding.requestIgnoreBatteryOptimizationsButton.setOnClickListener {
requestIgnoreBatteryOptimizations.launch(
Intent(
android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
Uri.parse("package:${Application.application.packageName}")
)
)
}
binding.communityButton.setOnClickListener { binding.communityButton.setOnClickListener {
it.context.launchCustomTab("https://community.sagernet.org/") it.context.launchCustomTab("https://community.sagernet.org/")
} }
@@ -96,6 +120,8 @@ class SettingsFragment : Fragment() {
) )
val appCenterEnabled = Settings.analyticsAllowed == Settings.ANALYSIS_ALLOWED val appCenterEnabled = Settings.analyticsAllowed == Settings.ANALYSIS_ALLOWED
val checkUpdateEnabled = Settings.checkUpdateEnabled val checkUpdateEnabled = Settings.checkUpdateEnabled
val removeBackgroudPermissionPage =
Application.powerManager.isIgnoringBatteryOptimizations(Application.application.packageName)
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
binding.dataSizeText.text = dataSize binding.dataSizeText.text = dataSize
binding.appCenterEnabled.text = EnabledType.from(appCenterEnabled).name binding.appCenterEnabled.text = EnabledType.from(appCenterEnabled).name
@@ -105,6 +131,7 @@ class SettingsFragment : Fragment() {
binding.checkUpdateEnabled.setSimpleItems(R.array.enabled) binding.checkUpdateEnabled.setSimpleItems(R.array.enabled)
binding.disableMemoryLimit.text = EnabledType.from(!Settings.disableMemoryLimit).name binding.disableMemoryLimit.text = EnabledType.from(!Settings.disableMemoryLimit).name
binding.disableMemoryLimit.setSimpleItems(R.array.enabled) binding.disableMemoryLimit.setSimpleItems(R.array.enabled)
binding.backgroundPermissionCard.isGone = removeBackgroudPermissionPage
} }
} }

View File

@@ -1,229 +1,294 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical">
android:padding="16dp">
<com.google.android.material.card.MaterialCardView <LinearLayout
android:id="@+id/appCenterCard"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<LinearLayout
<com.google.android.material.card.MaterialCardView
android:id="@+id/appCenterCard"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:orientation="vertical"
android:padding="16dp">
<TextView <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_app_center"
android:textAppearance="?attr/textAppearanceTitleLarge" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/appCenterEnabled"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:orientation="vertical"
android:hint="@string/enabled"> android:padding="16dp">
<AutoCompleteTextView <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_app_center"
android:textAppearance="?attr/textAppearanceTitleLarge" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/appCenterEnabled"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="none" android:layout_marginTop="16dp"
android:text="@string/disabled" android:hint="@string/enabled">
app:simpleItems="@array/enabled" />
</com.google.android.material.textfield.TextInputLayout> <AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="@string/disabled"
app:simpleItems="@array/enabled" />
<com.google.android.material.textfield.TextInputLayout </com.google.android.material.textfield.TextInputLayout>
android:id="@+id/checkUpdateEnabled"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/check_update">
<AutoCompleteTextView <com.google.android.material.textfield.TextInputLayout
android:id="@+id/checkUpdateEnabled"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="none" android:layout_marginTop="8dp"
android:text="@string/disabled" android:hint="@string/check_update">
app:simpleItems="@array/enabled" />
</com.google.android.material.textfield.TextInputLayout> <AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="@string/disabled"
app:simpleItems="@array/enabled" />
</LinearLayout> </com.google.android.material.textfield.TextInputLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView </LinearLayout>
android:id="@+id/statusCard" </com.google.android.material.card.MaterialCardView>
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout <com.google.android.material.card.MaterialCardView
android:id="@+id/statusCard"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginTop="16dp">
android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<TextView <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/core"
android:textAppearance="?attr/textAppearanceTitleLarge">
</TextView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/disableMemoryLimit"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:orientation="vertical"
android:hint="@string/memory_limit"> android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<AutoCompleteTextView <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/core"
android:textAppearance="?attr/textAppearanceTitleLarge">
</TextView>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/disableMemoryLimit"
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:inputType="none" android:layout_marginTop="8dp"
android:text="@string/enabled" android:hint="@string/memory_limit">
app:simpleItems="@array/enabled" />
</com.google.android.material.textfield.TextInputLayout> <AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none"
android:text="@string/enabled"
app:simpleItems="@array/enabled" />
<LinearLayout </com.google.android.material.textfield.TextInputLayout>
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<TextView <LinearLayout
style="?attr/textAppearanceTitleSmall" android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_marginTop="16dp">
android:text="@string/core_version" />
<TextView <TextView
android:id="@+id/versionText" style="?attr/textAppearanceTitleSmall"
style="?attr/textAppearanceBodyMedium" android:layout_width="0dp"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/core_version" />
<TextView
android:id="@+id/versionText"
style="?attr/textAppearanceBodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
tools:text="@string/loading" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
style="?attr/textAppearanceTitleSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/core_data_size" />
<TextView
android:id="@+id/dataSizeText"
style="?attr/textAppearanceBodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/loading" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="4dp" android:layout_marginTop="8dp"
tools:text="@string/loading" /> android:gravity="center_vertical|end"
android:orientation="horizontal">
<Button
android:id="@+id/clearButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_clear_working_directory"
android:textColor="#E91E63" />
</LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView </com.google.android.material.card.MaterialCardView>
style="?attr/textAppearanceTitleSmall"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/core_data_size" />
<TextView <com.google.android.material.card.MaterialCardView
android:id="@+id/dataSizeText" android:id="@+id/backgroundPermissionCard"
style="?attr/textAppearanceBodyMedium" style="?attr/materialCardViewElevatedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="@string/loading" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical|end"
android:orientation="horizontal">
<Button
android:id="@+id/clearButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings_clear_working_directory"
android:textColor="#E91E63" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/aboutCard"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginTop="16dp"
android:paddingStart="16dp" android:visibility="gone"
android:paddingTop="16dp" tools:visibility="visible">
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_title"
android:textAppearance="?attr/textAppearanceTitleLarge">
</TextView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/app_description" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical|end" android:orientation="vertical"
android:orientation="horizontal"> android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<Button <TextView
android:id="@+id/documentationButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/documentation_button" /> android:text="@string/background_permission"
android:textAppearance="?attr/textAppearanceTitleLarge">
<Button </TextView>
android:id="@+id/communityButton"
style="@style/Widget.Material3.Button.TextButton" <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/community_button" /> android:layout_marginTop="8dp"
android:text="@string/background_permission_description" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:orientation="horizontal">
<Button
android:id="@+id/dontKillMyAppButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/read_more" />
<Button
android:id="@+id/requestIgnoreBatteryOptimizationsButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/request_background_permission" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/aboutCard"
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_title"
android:textAppearance="?attr/textAppearanceTitleLarge">
</TextView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/app_description" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:orientation="horizontal">
<Button
android:id="@+id/documentationButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/documentation_button" />
<Button
android:id="@+id/communityButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/community_button" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </com.google.android.material.card.MaterialCardView>
</LinearLayout>
</com.google.android.material.card.MaterialCardView> </ScrollView>
</LinearLayout>

View File

@@ -80,5 +80,9 @@
<string name="documentation_button">Documentation</string> <string name="documentation_button">Documentation</string>
<string name="community_button">Community</string> <string name="community_button">Community</string>
<string name="memory_limit">Memory Limit</string> <string name="memory_limit">Memory Limit</string>
<string name="background_permission">Background permission</string>
<string name="background_permission_description">Apply for the necessary permissions in order for the VPN to function properly.\n\nIf you are using a device made by a Chinese company, the card may not disappear after the permission is granted.</string>
<string name="read_more">Read More</string>
<string name="request_background_permission">Ignore battery optimizations</string>
</resources> </resources>