AndroidAPS/app/src/main/java/info/nightscout/androidaps/utils/AndroidPermission.kt

157 lines
9 KiB
Kotlin
Raw Normal View History

2020-03-30 13:14:24 +02:00
package info.nightscout.androidaps.utils
import android.Manifest
import android.annotation.SuppressLint
2021-12-12 10:15:47 +01:00
import android.annotation.TargetApi
2021-12-14 16:45:41 +01:00
import android.bluetooth.BluetoothAdapter
2020-03-30 13:14:24 +02:00
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import androidx.core.content.ContextCompat
2020-10-19 18:40:17 +02:00
import androidx.fragment.app.FragmentActivity
2020-03-30 13:14:24 +02:00
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
2021-01-18 22:47:55 +01:00
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
2021-10-15 14:56:22 +02:00
import info.nightscout.androidaps.plugins.bus.RxBus
2020-03-30 13:14:24 +02:00
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
2021-02-09 17:57:28 +01:00
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
2020-03-30 13:14:24 +02:00
import info.nightscout.androidaps.utils.resources.ResourceHelper
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class AndroidPermission @Inject constructor(
2021-11-04 10:56:12 +01:00
val rh: ResourceHelper,
2021-10-15 14:56:22 +02:00
val rxBus: RxBus,
2020-03-30 13:14:24 +02:00
val injector: HasAndroidInjector
) {
2021-01-18 22:47:55 +01:00
private var permissionBatteryOptimizationFailed = false
2020-03-30 13:14:24 +02:00
@SuppressLint("BatteryLife")
2021-01-18 22:47:55 +01:00
fun askForPermission(activity: FragmentActivity, permissions: Array<String>) {
2020-03-30 13:14:24 +02:00
var test = false
var testBattery = false
2021-01-18 22:47:55 +01:00
for (s in permissions) {
2020-03-30 13:14:24 +02:00
test = test || ContextCompat.checkSelfPermission(activity, s) != PackageManager.PERMISSION_GRANTED
if (s == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
val powerManager = activity.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = activity.packageName
testBattery = testBattery || !powerManager.isIgnoringBatteryOptimizations(packageName)
}
}
if (test) {
2021-01-18 22:47:55 +01:00
if (activity is DaggerAppCompatActivityWithResult)
activity.requestMultiplePermissions.launch(permissions)
2020-03-30 13:14:24 +02:00
}
if (testBattery) {
try {
2021-01-18 22:47:55 +01:00
if (activity is DaggerAppCompatActivityWithResult)
activity.callForBatteryOptimization.launch(null)
2020-03-30 13:14:24 +02:00
} catch (e: ActivityNotFoundException) {
2021-01-18 22:47:55 +01:00
permissionBatteryOptimizationFailed = true
2021-11-04 10:56:12 +01:00
OKDialog.show(activity, rh.gs(R.string.permission), rh.gs(R.string.alert_dialog_permission_battery_optimization_failed)) { activity.recreate() }
2020-03-30 13:14:24 +02:00
}
}
}
2021-01-18 22:47:55 +01:00
fun askForPermission(activity: FragmentActivity, permission: String) = askForPermission(activity, arrayOf(permission))
2020-03-30 13:14:24 +02:00
fun permissionNotGranted(context: Context, permission: String): Boolean {
var selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
if (permission == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
2021-01-18 22:47:55 +01:00
if (!permissionBatteryOptimizationFailed) {
2020-03-30 13:14:24 +02:00
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = context.packageName
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName)
}
}
return !selfCheck
}
@Synchronized
2020-10-19 18:40:17 +02:00
fun notifyForSMSPermissions(activity: FragmentActivity, smsCommunicatorPlugin: SmsCommunicatorPlugin) {
2021-11-09 17:57:51 +01:00
if (smsCommunicatorPlugin.isEnabled()) {
2020-03-30 13:14:24 +02:00
if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS)) {
2021-11-04 10:56:12 +01:00
val notification = NotificationWithAction(injector, Notification.PERMISSION_SMS, rh.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT)
2021-12-14 16:45:41 +01:00
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_MMS)) }
2020-03-30 13:14:24 +02:00
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SMS))
// Following is a bug in Android 8
2021-12-12 10:15:47 +01:00
// if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) {
// val notification = NotificationWithAction(injector, Notification.PERMISSION_PHONE_STATE, rh.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT)
// notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE)) }
// rxBus.send(EventNewNotification(notification))
// } else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONE_STATE))
2020-03-30 13:14:24 +02:00
}
}
2021-12-14 16:45:41 +01:00
@Synchronized
fun notifyForBtConnectPermission(activity: FragmentActivity) {
if (Build.VERSION.SDK_INT >= /*Build.VERSION_CODES.S*/31) {
// Manifest.permission.BLUETOOTH_CONNECT
if (permissionNotGranted(activity, "android.permission.BLUETOOTH_CONNECT") || permissionNotGranted(activity, "android.permission.BLUETOOTH_SCAN")) {
val notification = NotificationWithAction(injector, Notification.PERMISSION_BT, rh.gs(R.string.needconnectpermission), Notification.URGENT)
notification.action(R.string.request) { askForPermission(activity, arrayOf("android.permission.BLUETOOTH_SCAN", "android.permission.BLUETOOTH_CONNECT")) }
rxBus.send(EventNewNotification(notification))
2021-12-15 18:14:13 +01:00
} else {
activity.startActivity(Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE))
rxBus.send(EventDismissNotification(Notification.PERMISSION_BT))
}
2021-12-14 16:45:41 +01:00
}
}
2020-03-30 13:14:24 +02:00
@Synchronized
2020-10-19 18:40:17 +02:00
fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) {
2020-03-30 13:14:24 +02:00
if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
2021-11-04 10:56:12 +01:00
val notification = NotificationWithAction(injector, Notification.PERMISSION_BATTERY, String.format(rh.gs(R.string.needwhitelisting), rh.gs(R.string.app_name)), Notification.URGENT)
2021-01-18 22:47:55 +01:00
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) }
2020-03-30 13:14:24 +02:00
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY))
}
2020-10-19 18:40:17 +02:00
@Synchronized fun notifyForStoragePermission(activity: FragmentActivity) {
2020-03-30 13:14:24 +02:00
if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
2021-11-04 10:56:12 +01:00
val notification = NotificationWithAction(injector, Notification.PERMISSION_STORAGE, rh.gs(R.string.needstoragepermission), Notification.URGENT)
2021-12-14 16:45:41 +01:00
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) }
2020-03-30 13:14:24 +02:00
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_STORAGE))
}
2020-10-19 18:40:17 +02:00
@Synchronized fun notifyForLocationPermissions(activity: FragmentActivity) {
2020-03-30 13:14:24 +02:00
if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) {
2021-11-04 10:56:12 +01:00
val notification = NotificationWithAction(injector, Notification.PERMISSION_LOCATION, rh.gs(R.string.needlocationpermission), Notification.URGENT)
2021-01-18 22:47:55 +01:00
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)) }
2020-03-30 13:14:24 +02:00
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_LOCATION))
}
2020-10-19 18:40:17 +02:00
@Synchronized fun notifyForSystemWindowPermissions(activity: FragmentActivity) {
2020-03-30 13:14:24 +02:00
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
if (!Settings.canDrawOverlays(activity)) {
2021-11-04 10:56:12 +01:00
val notification = NotificationWithAction(injector, Notification.PERMISSION_SYSTEM_WINDOW, rh.gs(R.string.needsystemwindowpermission), Notification.URGENT)
2021-01-18 22:47:55 +01:00
notification.action(R.string.request) {
2020-03-30 13:14:24 +02:00
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.packageName))
activity.startActivity(intent)
}
2021-01-18 22:47:55 +01:00
}
2020-03-30 13:14:24 +02:00
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SYSTEM_WINDOW))
}
}
}