AndroidPermission refactor

This commit is contained in:
Milos Kozak 2020-03-30 13:14:24 +02:00
parent caae6ab078
commit 969f713914
5 changed files with 216 additions and 216 deletions

View file

@ -78,6 +78,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
@Inject AAPSLogger aapsLogger;
@Inject RxBusWrapper rxBus;
@Inject AndroidPermission androidPermission;
@Inject SP sp;
@Inject ResourceHelper resourceHelper;
@Inject VersionCheckerUtils versionCheckerUtils;
@ -161,12 +162,12 @@ public class MainActivity extends NoSplashAppCompatActivity {
startActivity(intent);
}
AndroidPermission.notifyForStoragePermission(this);
AndroidPermission.notifyForBatteryOptimizationPermission(this);
androidPermission.notifyForStoragePermission(this);
androidPermission.notifyForBatteryOptimizationPermission(this);
if (Config.PUMPDRIVERS) {
AndroidPermission.notifyForLocationPermissions(this);
AndroidPermission.notifyForSMSPermissions(this, smsCommunicatorPlugin);
AndroidPermission.notifyForSystemWindowPermissions(this);
androidPermission.notifyForLocationPermissions(this);
androidPermission.notifyForSMSPermissions(this, smsCommunicatorPlugin);
androidPermission.notifyForSystemWindowPermissions(this);
}
}

View file

@ -1,12 +1,12 @@
package info.nightscout.androidaps.setupwizard
import android.Manifest
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
@ -46,7 +46,7 @@ import javax.inject.Singleton
class SWDefinition @Inject constructor(
injector: HasAndroidInjector,
private val rxBus: RxBusWrapper,
private val mainApp: MainApp,
private val context: Context,
resourceHelper: ResourceHelper,
private val sp: SP,
private val profileFunction: ProfileFunction,
@ -58,10 +58,11 @@ class SWDefinition @Inject constructor(
private val loopPlugin: LoopPlugin,
private val nsClientPlugin: NSClientPlugin,
private val nsProfilePlugin: NSProfilePlugin,
private val protectionCheck: ProtectionCheck
private val protectionCheck: ProtectionCheck,
private val androidPermission: AndroidPermission
) {
var activity: AppCompatActivity? = null
lateinit var activity: AppCompatActivity
private val screens: MutableList<SWScreen> = ArrayList()
fun getScreens(): List<SWScreen> {
@ -83,7 +84,7 @@ class SWDefinition @Inject constructor(
.preferenceId(R.string.key_language).label(R.string.language)
.comment(R.string.setupwizard_language_prompt))
.validator(SWValidator {
update(mainApp)
update(context)
sp.contains(R.string.key_language)
})
private val screenEula = SWScreen(injector, R.string.end_user_license_agreement)
@ -127,10 +128,10 @@ class SWDefinition @Inject constructor(
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility(SWValidator { AndroidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
.action(Runnable { AndroidPermission.askForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY) }))
.visibility(SWValidator { AndroidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
.validator(SWValidator { !AndroidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
.visibility(SWValidator { androidPermission.permissionNotGranted(context, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
.action(Runnable { androidPermission.askForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY) }))
.visibility(SWValidator { androidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
.validator(SWValidator { !androidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
private val screenPermissionBt = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfotext(injector)
@ -138,10 +139,10 @@ class SWDefinition @Inject constructor(
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility(SWValidator { AndroidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
.action(Runnable { AndroidPermission.askForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION) }))
.visibility(SWValidator { AndroidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
.validator(SWValidator { !AndroidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
.visibility(SWValidator { androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
.action(Runnable { androidPermission.askForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION) }))
.visibility(SWValidator { androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
.validator(SWValidator { !androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
private val screenPermissionStore = SWScreen(injector, R.string.permission)
.skippable(false)
.add(SWInfotext(injector)
@ -149,10 +150,10 @@ class SWDefinition @Inject constructor(
.add(SWBreak(injector))
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility(SWValidator { AndroidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.action(Runnable { AndroidPermission.askForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE) }))
.visibility(SWValidator { AndroidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.validator(SWValidator { !AndroidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.visibility(SWValidator { androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.action(Runnable { androidPermission.askForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE) }))
.visibility(SWValidator { androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.validator(SWValidator { !androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
private val screenImport = SWScreen(injector, R.string.nav_import)
.add(SWInfotext(injector)
.label(R.string.storedsettingsfound))
@ -160,7 +161,7 @@ class SWDefinition @Inject constructor(
.add(SWButton(injector)
.text(R.string.nav_import)
.action(Runnable { ImportExportPrefs.importSharedPreferences(activity) }))
.visibility(SWValidator { ImportExportPrefs.file.exists() && !AndroidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.visibility(SWValidator { ImportExportPrefs.file.exists() && !androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
private val screenNsClient = SWScreen(injector, R.string.nsclientinternal_title)
.skippable(true)
.add(SWInfotext(injector)
@ -219,13 +220,11 @@ class SWDefinition @Inject constructor(
.text(R.string.insulinsourcesetup)
.action(Runnable {
val plugin = activePlugin.activeInsulin as PluginBase
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
}
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
})
.visibility(SWValidator { (activePlugin.activeInsulin as PluginBase).preferencesId > 0 }))
private val screenBgSource = SWScreen(injector, R.string.configbuilder_bgsource)
@ -238,13 +237,11 @@ class SWDefinition @Inject constructor(
.text(R.string.bgsourcesetup)
.action(Runnable {
val plugin = activePlugin.activeBgSource as PluginBase
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
}
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
})
.visibility(SWValidator { (activePlugin.activeBgSource as PluginBase).preferencesId > 0 }))
private val screenProfile = SWScreen(injector, R.string.configbuilder_profile)
@ -275,7 +272,7 @@ class SWDefinition @Inject constructor(
.label(R.string.profileswitch_ismissing))
.add(SWButton(injector)
.text(R.string.doprofileswitch)
.action(Runnable { ProfileSwitchDialog().show(activity!!.supportFragmentManager, "SetupWizard") }))
.action(Runnable { ProfileSwitchDialog().show(activity.supportFragmentManager, "SetupWizard") }))
.validator(SWValidator { profileFunction.getProfile() != null })
.visibility(SWValidator { profileFunction.getProfile() == null })
private val screenPump = SWScreen(injector, R.string.configbuilder_pump)
@ -288,13 +285,11 @@ class SWDefinition @Inject constructor(
.text(R.string.pumpsetup)
.action(Runnable {
val plugin = activePlugin.activePump as PluginBase
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
}
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
})
.visibility(SWValidator { (activePlugin.activePump as PluginBase).preferencesId > 0 }))
.add(SWButton(injector)
@ -317,13 +312,11 @@ class SWDefinition @Inject constructor(
.text(R.string.apssetup)
.action(Runnable {
val plugin = activePlugin.activeAPS as PluginBase
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
}
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
})
.visibility(SWValidator { (activePlugin.activeAPS as PluginBase).preferencesId > 0 }))
.visibility(SWValidator { Config.APS })
@ -367,13 +360,11 @@ class SWDefinition @Inject constructor(
.text(R.string.sensitivitysetup)
.action(Runnable {
val plugin = activePlugin.activeSensitivity as PluginBase
activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
}
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
val i = Intent(activity, PreferencesActivity::class.java)
i.putExtra("id", plugin.preferencesId)
activity.startActivity(i)
}, null)
})
.visibility(SWValidator { (activePlugin.activeSensitivity as PluginBase).preferencesId > 0 }))
private val getScreenObjectives = SWScreen(injector, R.string.objectives)

View file

@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.setupwizard.SWDefinition
class SWFragment(injecto:HasAndroidInjector, private var definition: SWDefinition) : SWItem(injecto, Type.FRAGMENT) {
class SWFragment(injector:HasAndroidInjector, private var definition: SWDefinition) : SWItem(injector, Type.FRAGMENT) {
lateinit var fragment: Fragment
fun add(fragment: Fragment): SWFragment {
@ -14,6 +14,6 @@ class SWFragment(injecto:HasAndroidInjector, private var definition: SWDefinitio
}
override fun generateDialog(layout: LinearLayout) {
definition.activity?.supportFragmentManager?.beginTransaction()?.add(layout.id, fragment, fragment.tag)?.commit()
definition.activity.supportFragmentManager.beginTransaction().add(layout.id, fragment, fragment.tag).commit()
}
}

View file

@ -1,155 +0,0 @@
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 info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.plugins.bus.RxBus;
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;
public class AndroidPermission {
public static final int CASE_STORAGE = 0x1;
public static final int CASE_SMS = 0x2;
public static final int CASE_LOCATION = 0x3;
public static final int CASE_BATTERY = 0x4;
public static final int CASE_PHONE_STATE = 0x5;
public static final int CASE_SYSTEM_WINDOW = 0x6;
private static boolean permission_battery_optimization_failed = false;
@SuppressLint("BatteryLife")
private static void askForPermission(Activity activity, String[] permission, Integer requestCode) {
boolean test = false;
boolean testBattery = false;
for (String s : permission) {
test = test || (ContextCompat.checkSelfPermission(activity, s) != PackageManager.PERMISSION_GRANTED);
if (s.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
PowerManager powerManager = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
String packageName = activity.getPackageName();
testBattery = testBattery || !powerManager.isIgnoringBatteryOptimizations(packageName);
}
}
if (test) {
ActivityCompat.requestPermissions(activity, permission, requestCode);
}
if (testBattery) {
try {
Intent i = new Intent();
i.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
i.setData(Uri.parse("package:" + activity.getPackageName()));
activity.startActivityForResult(i, CASE_BATTERY);
} catch (ActivityNotFoundException e) {
permission_battery_optimization_failed = true;
OKDialog.show(activity, MainApp.gs(R.string.permission), MainApp.gs(R.string.alert_dialog_permission_battery_optimization_failed), activity::recreate);
}
}
}
public static void askForPermission(Activity activity, String permission, Integer requestCode) {
String[] permissions = {permission};
askForPermission(activity, permissions, requestCode);
}
public static boolean permissionNotGranted(Context context, String permission) {
boolean selfCheck = ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
if (permission.equals(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
if (!permission_battery_optimization_failed) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
String packageName = context.getPackageName();
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName);
}
}
return !selfCheck;
}
public static synchronized void notifyForSMSPermissions(Activity activity, SmsCommunicatorPlugin smsCommunicatorPlugin) {
if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) {
if (permissionNotGranted(activity, Manifest.permission.RECEIVE_SMS)) {
NotificationWithAction notification = new NotificationWithAction(MainApp.instance(), Notification.PERMISSION_SMS, MainApp.gs(R.string.smscommunicator_missingsmspermission), Notification.URGENT);
notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.RECEIVE_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_MMS}, AndroidPermission.CASE_SMS));
RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
} else
RxBus.Companion.getINSTANCE().send(new 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)) {
NotificationWithAction notification = new NotificationWithAction(MainApp.instance(), Notification.PERMISSION_PHONESTATE, MainApp.gs(R.string.smscommunicator_missingphonestatepermission), Notification.URGENT);
notification.action(R.string.request, () ->
AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_PHONE_STATE}, AndroidPermission.CASE_PHONE_STATE));
RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
} else
RxBus.Companion.getINSTANCE().send(new EventDismissNotification(Notification.PERMISSION_PHONESTATE));
}
}
}
public static synchronized void notifyForBatteryOptimizationPermission(Activity activity) {
if (permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) {
NotificationWithAction notification = new NotificationWithAction(MainApp.instance(), Notification.PERMISSION_BATTERY, String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)), Notification.URGENT);
notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}, AndroidPermission.CASE_BATTERY));
RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
} else
RxBus.Companion.getINSTANCE().send(new EventDismissNotification(Notification.PERMISSION_BATTERY));
}
public static synchronized void notifyForStoragePermission(Activity activity) {
if (permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
NotificationWithAction notification = new NotificationWithAction(MainApp.instance(), Notification.PERMISSION_STORAGE, MainApp.gs(R.string.needstoragepermission), Notification.URGENT);
notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, AndroidPermission.CASE_STORAGE));
RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
} else
RxBus.Companion.getINSTANCE().send(new EventDismissNotification(Notification.PERMISSION_STORAGE));
}
public static synchronized void notifyForLocationPermissions(Activity activity) {
if (permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION)) {
NotificationWithAction notification = new NotificationWithAction(MainApp.instance(), Notification.PERMISSION_LOCATION, MainApp.gs(R.string.needlocationpermission), Notification.URGENT);
notification.action(R.string.request, () -> AndroidPermission.askForPermission(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, AndroidPermission.CASE_LOCATION));
RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
} else
RxBus.Companion.getINSTANCE().send(new EventDismissNotification(Notification.PERMISSION_LOCATION));
}
public static synchronized void notifyForSystemWindowPermissions(Activity activity) {
// Check if Android Q or higher
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
if (!Settings.canDrawOverlays(activity)) {
NotificationWithAction notification = new NotificationWithAction(MainApp.instance(), Notification.PERMISSION_SYSTEM_WINDOW, MainApp.gs(R.string.needsystemwindowpermission), Notification.URGENT);
notification.action(R.string.request, () -> {
// 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
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + activity.getPackageName()));
activity.startActivity(intent);
}
});
RxBus.Companion.getINSTANCE().send(new EventNewNotification(notification));
} else
RxBus.Companion.getINSTANCE().send(new EventDismissNotification(Notification.PERMISSION_SYSTEM_WINDOW));
}
}
}

View file

@ -0,0 +1,163 @@
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))
}
}
}