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

View file

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

View file

@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
import dagger.android.HasAndroidInjector import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.setupwizard.SWDefinition 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 lateinit var fragment: Fragment
fun add(fragment: Fragment): SWFragment { fun add(fragment: Fragment): SWFragment {
@ -14,6 +14,6 @@ class SWFragment(injecto:HasAndroidInjector, private var definition: SWDefinitio
} }
override fun generateDialog(layout: LinearLayout) { 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))
}
}
}