163 lines
8.8 KiB
Kotlin
163 lines
8.8 KiB
Kotlin
|
package info.nightscout.androidaps.utils
|
||
|
|
||
|
import android.Manifest
|
||
|
import android.annotation.SuppressLint
|
||
|
import android.app.Activity
|
||
|
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.app.ActivityCompat
|
||
|
import androidx.core.content.ContextCompat
|
||
|
import dagger.android.HasAndroidInjector
|
||
|
import info.nightscout.androidaps.R
|
||
|
import info.nightscout.androidaps.interfaces.PluginType
|
||
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||
|
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
|
||
|
import info.nightscout.androidaps.utils.OKDialog.show
|
||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||
|
import javax.inject.Inject
|
||
|
import javax.inject.Singleton
|
||
|
|
||
|
@Singleton
|
||
|
class AndroidPermission @Inject constructor(
|
||
|
val resourceHelper: ResourceHelper,
|
||
|
val rxBus: RxBusWrapper,
|
||
|
val injector: HasAndroidInjector
|
||
|
) {
|
||
|
|
||
|
companion object {
|
||
|
const val CASE_STORAGE = 0x1
|
||
|
const val CASE_SMS = 0x2
|
||
|
const val CASE_LOCATION = 0x3
|
||
|
const val CASE_BATTERY = 0x4
|
||
|
const val CASE_PHONE_STATE = 0x5
|
||
|
const val CASE_SYSTEM_WINDOW = 0x6
|
||
|
}
|
||
|
|
||
|
private var permission_battery_optimization_failed = false
|
||
|
|
||
|
@SuppressLint("BatteryLife")
|
||
|
private fun askForPermission(activity: Activity, permission: Array<String>, requestCode: Int) {
|
||
|
var test = false
|
||
|
var testBattery = false
|
||
|
for (s in permission) {
|
||
|
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) {
|
||
|
ActivityCompat.requestPermissions(activity, permission, requestCode)
|
||
|
}
|
||
|
if (testBattery) {
|
||
|
try {
|
||
|
val i = Intent()
|
||
|
i.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||
|
i.data = Uri.parse("package:" + activity.packageName)
|
||
|
activity.startActivityForResult(i, CASE_BATTERY)
|
||
|
} catch (e: ActivityNotFoundException) {
|
||
|
permission_battery_optimization_failed = true
|
||
|
show(activity, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_permission_battery_optimization_failed), Runnable { activity.recreate() })
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fun askForPermission(activity: Activity, permission: String, requestCode: Int) {
|
||
|
val permissions = arrayOf(permission)
|
||
|
askForPermission(activity, permissions, requestCode)
|
||
|
}
|
||
|
|
||
|
fun permissionNotGranted(context: Context, permission: String): Boolean {
|
||
|
var selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
|
||
|
if (permission == Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) {
|
||
|
if (!permission_battery_optimization_failed) {
|
||
|
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
|
||
|
val packageName = context.packageName
|
||
|
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName)
|
||
|
}
|
||
|
}
|
||
|
return !selfCheck
|
||
|
}
|
||
|
|
||
|
@Synchronized
|
||
|
fun notifyForSMSPermissions(activity: Activity, smsCommunicatorPlugin: SmsCommunicatorPlugin) {
|
||
|
if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) {
|
||
|
if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS)) {
|
||
|
val notification = NotificationWithAction(injector, Notification.PERMISSION_SMS, resourceHelper.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT)
|
||
|
notification.action(R.string.request, Runnable {
|
||
|
askForPermission(activity, arrayOf(Manifest.permission.RECEIVE_SMS,
|
||
|
Manifest.permission.SEND_SMS,
|
||
|
Manifest.permission.RECEIVE_MMS), CASE_SMS)
|
||
|
})
|
||
|
rxBus.send(EventNewNotification(notification))
|
||
|
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SMS))
|
||
|
// Following is a bug in Android 8
|
||
|
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) {
|
||
|
if (permissionNotGranted(activity, Manifest.permission.READ_PHONE_STATE)) {
|
||
|
val notification = NotificationWithAction(injector, Notification.PERMISSION_PHONESTATE, resourceHelper.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT)
|
||
|
notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE), CASE_PHONE_STATE) })
|
||
|
rxBus.send(EventNewNotification(notification))
|
||
|
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONESTATE))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Synchronized
|
||
|
fun notifyForBatteryOptimizationPermission(activity: Activity) {
|
||
|
if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
|
||
|
val notification = NotificationWithAction(injector, Notification.PERMISSION_BATTERY, String.format(resourceHelper.gs(R.string.needwhitelisting), resourceHelper.gs(R.string.app_name)), Notification.URGENT)
|
||
|
notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS), CASE_BATTERY) })
|
||
|
rxBus.send(EventNewNotification(notification))
|
||
|
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY))
|
||
|
}
|
||
|
|
||
|
@Synchronized fun notifyForStoragePermission(activity: Activity) {
|
||
|
if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
|
||
|
val notification = NotificationWithAction(injector, Notification.PERMISSION_STORAGE, resourceHelper.gs(R.string.needstoragepermission), Notification.URGENT)
|
||
|
notification.action(R.string.request, Runnable {
|
||
|
askForPermission(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
|
||
|
Manifest.permission.WRITE_EXTERNAL_STORAGE), CASE_STORAGE)
|
||
|
})
|
||
|
rxBus.send(EventNewNotification(notification))
|
||
|
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_STORAGE))
|
||
|
}
|
||
|
|
||
|
@Synchronized fun notifyForLocationPermissions(activity: Activity) {
|
||
|
if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||
|
val notification = NotificationWithAction(injector, Notification.PERMISSION_LOCATION, resourceHelper.gs(R.string.needlocationpermission), Notification.URGENT)
|
||
|
notification.action(R.string.request, Runnable { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), CASE_LOCATION) })
|
||
|
rxBus.send(EventNewNotification(notification))
|
||
|
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_LOCATION))
|
||
|
}
|
||
|
|
||
|
@Synchronized fun notifyForSystemWindowPermissions(activity: Activity) {
|
||
|
// Check if Android Q or higher
|
||
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
|
||
|
if (!Settings.canDrawOverlays(activity)) {
|
||
|
val notification = NotificationWithAction(injector, Notification.PERMISSION_SYSTEM_WINDOW, resourceHelper.gs(R.string.needsystemwindowpermission), Notification.URGENT)
|
||
|
notification.action(R.string.request, Runnable {
|
||
|
// 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)
|
||
|
}
|
||
|
})
|
||
|
rxBus.send(EventNewNotification(notification))
|
||
|
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SYSTEM_WINDOW))
|
||
|
}
|
||
|
}
|
||
|
}
|