Skip to content

Commit

Permalink
#814 feat: show system dialog to remove Key Mapper from background op…
Browse files Browse the repository at this point in the history
…timisation
  • Loading branch information
sds100 committed Nov 4, 2021
1 parent 48c5174 commit e0415d6
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 128 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import io.github.sds100.keymapper.Constants
import io.github.sds100.keymapper.R
import io.github.sds100.keymapper.ServiceLocator
import io.github.sds100.keymapper.UseCases
import io.github.sds100.keymapper.system.DeviceAdmin
import io.github.sds100.keymapper.system.Shell
import io.github.sds100.keymapper.system.url.UrlUtils
Expand Down Expand Up @@ -51,165 +51,167 @@ class RequestPermissionDelegate(

fun requestPermission(permission: Permission, navController: NavController?) {
when (permission) {
Permission.WRITE_SETTINGS ->
Permission.WRITE_SETTINGS -> requestWriteSettings()
Permission.CAMERA -> requestPermissionLauncher.launch(Manifest.permission.CAMERA)
Permission.DEVICE_ADMIN -> requestDeviceAdmin()
Permission.READ_PHONE_STATE -> requestPermissionLauncher.launch(Manifest.permission.READ_PHONE_STATE)
Permission.ACCESS_NOTIFICATION_POLICY -> requestAccessNotificationPolicy()
Permission.WRITE_SECURE_SETTINGS -> requestWriteSecureSettings()
Permission.CALL_PHONE -> requestPermissionLauncher.launch(Manifest.permission.CALL_PHONE)
Permission.ROOT -> {
require(navController != null) { "nav controller can't be null!" }
requestRootPermission(navController)
}

Permission.IGNORE_BATTERY_OPTIMISATION ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS).apply {
data = Uri.parse("package:${Constants.PACKAGE_NAME}")
flags = Intent.FLAG_ACTIVITY_NO_HISTORY

try {
activity.startActivity(this)
} catch (e: Exception) {
toast(R.string.error_cant_find_write_settings_page)
}
}
requestIgnoreBatteryOptimisations()
}
}
}

Permission.CAMERA -> requestPermissionLauncher.launch(Manifest.permission.CAMERA)

Permission.DEVICE_ADMIN -> {
activity.materialAlertDialog {
private fun requestAccessNotificationPolicy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)

messageResource = R.string.enable_device_admin_message
try {
startActivityForResultLauncher.launch(intent)
} catch (e: Exception) {
toast(R.string.error_cant_find_dnd_access_settings)
}
}
}

okButton {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
private fun requestWriteSettings() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS).apply {
data = Uri.parse("package:${Constants.PACKAGE_NAME}")
flags = Intent.FLAG_ACTIVITY_NO_HISTORY

intent.putExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN,
ComponentName(activity, DeviceAdmin::class.java)
)
try {
activity.startActivity(this)
} catch (e: Exception) {
toast(R.string.error_cant_find_write_settings_page)
}
}
}
}

intent.putExtra(
DevicePolicyManager.EXTRA_ADD_EXPLANATION,
activity.str(R.string.error_need_to_enable_device_admin)
)
private fun requestWriteSecureSettings() {
activity.materialAlertDialog {
titleResource = R.string.dialog_title_write_secure_settings
messageResource = R.string.dialog_message_write_secure_settings

startActivityForResultLauncher.launch(intent)
}
positiveButton(R.string.pos_grant_write_secure_settings_guide) {
UrlUtils.openUrl(
activity,
activity.str(R.string.url_grant_write_secure_settings_guide)
)
}

negativeButton(R.string.neg_cancel) { it.cancel() }
negativeButton(R.string.pos_enable_root_features) {
val successful = ServiceLocator.suAdapter(context).requestPermission()

show()
if (successful) {
context.toast(R.string.toast_root_features_turned_on)
}
}

Permission.READ_PHONE_STATE ->
requestPermissionLauncher.launch(Manifest.permission.READ_PHONE_STATE)
show()
}
}

Permission.ACCESS_NOTIFICATION_POLICY ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
private fun requestRootPermission(navController: NavController) {

try {
startActivityForResultLauncher.launch(intent)
} catch (e: Exception) {
toast(R.string.error_cant_find_dnd_access_settings)
}
if (showDialogs) {
activity.materialAlertDialog {
titleResource = R.string.dialog_title_root_prompt
messageResource = R.string.dialog_message_root_prompt
setIcon(R.drawable.ic_baseline_warning_24)

okButton {
navController.navigate(R.id.action_global_settingsFragment)
Shell.run("su")
}

Permission.WRITE_SECURE_SETTINGS -> {
require(navController != null) { "nav controller can't be null!" }
activity.materialAlertDialog {
messageResource = R.string.dialog_message_write_secure_settings
negativeButton(R.string.neg_cancel) { it.cancel() }

positiveButton(R.string.pos_grant_write_secure_settings_guide) {
UrlUtils.openUrl(
activity,
activity.str(R.string.url_grant_write_secure_settings_guide)
)
}
show()
}
} else {
navController.navigate(R.id.action_global_settingsFragment)
Shell.run("su")
}
}

negativeButton(R.string.pos_enable_root_features) {
val successful = ServiceLocator.suAdapter(context).requestPermission()
private fun requestDeviceAdmin() {
activity.materialAlertDialog {

if (successful){
context.toast(R.string.toast_root_features_turned_on)
}
}
messageResource = R.string.enable_device_admin_message

show()
}
}
okButton {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)

Permission.NOTIFICATION_LISTENER ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS).apply {
try {
startActivityForResultLauncher.launch(this)
} catch (e: Exception) {
toast(R.string.error_cant_find_notification_listener_settings)
}
}
}
intent.putExtra(
DevicePolicyManager.EXTRA_DEVICE_ADMIN,
ComponentName(activity, DeviceAdmin::class.java)
)

Permission.CALL_PHONE ->
requestPermissionLauncher.launch(Manifest.permission.CALL_PHONE)
intent.putExtra(
DevicePolicyManager.EXTRA_ADD_EXPLANATION,
activity.str(R.string.error_need_to_enable_device_admin)
)

Permission.ROOT -> {
require(navController != null) { "nav controller can't be null!" }
startActivityForResultLauncher.launch(intent)
}

negativeButton(R.string.neg_cancel) { it.cancel() }

if (showDialogs) {
activity.materialAlertDialog {
titleResource = R.string.dialog_title_root_prompt
messageResource = R.string.dialog_message_root_prompt
setIcon(R.drawable.ic_baseline_warning_24)
show()
}
}

okButton {
navController.navigate(R.id.action_global_settingsFragment)
Shell.run("su")
}
@RequiresApi(Build.VERSION_CODES.M)
private fun requestIgnoreBatteryOptimisations() {
if (showDialogs) {
activity.materialAlertDialog {
titleResource = R.string.dialog_title_disable_battery_optimisation
messageResource = R.string.dialog_message_disable_battery_optimisation

negativeButton(R.string.neg_cancel) { it.cancel() }
positiveButton(R.string.pos_turn_off_stock_battery_optimisation) {

try {
val intent = Intent(
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
Uri.parse("package:${Constants.PACKAGE_NAME}")
)

show()
activity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
activity.longToast(R.string.error_battery_optimisation_activity_not_found)
}
} else {
navController.navigate(R.id.action_global_settingsFragment)
Shell.run("su")
}
}

Permission.IGNORE_BATTERY_OPTIMISATION ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (showDialogs) {
activity.materialAlertDialog {
titleResource = R.string.dialog_title_disable_battery_optimisation
messageResource = R.string.dialog_message_disable_battery_optimisation

positiveButton(R.string.pos_turn_off_stock_battery_optimisation) {
try {
val intent =
Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)

activity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
longToast(R.string.error_battery_optimisation_activity_not_found)
}
}

negativeButton(R.string.neg_cancel) { it.cancel() }

neutralButton(R.string.neutral_go_to_dont_kill_my_app) {
UrlUtils.openUrl(
activity,
activity.str(R.string.url_dont_kill_my_app)
)
}

show()
}
} else {
try {
val intent =
Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)

activity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
longToast(R.string.error_battery_optimisation_activity_not_found)
}
}
negativeButton(R.string.neg_cancel) { it.cancel() }

neutralButton(R.string.neutral_go_to_dont_kill_my_app) {
UrlUtils.openUrl(
activity,
activity.str(R.string.url_dont_kill_my_app)
)
}

show()
}
} else {
try {
val intent =
Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)

activity.startActivity(intent)
} catch (e: ActivityNotFoundException) {
longToast(R.string.error_battery_optimisation_activity_not_found)
}
}
}
}

0 comments on commit e0415d6

Please sign in to comment.