asking for permissions refactor

This commit is contained in:
Milos Kozak 2021-01-18 22:47:55 +01:00
parent 9e2fb90bb7
commit e26ae1af7d
28 changed files with 155 additions and 180 deletions

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps
import android.os.Build
import info.nightscout.androidaps.interfaces.ConfigInterface
import javax.inject.Inject
import javax.inject.Singleton
@ -14,4 +15,7 @@ class Config @Inject constructor() : ConfigInterface {
override val PUMPDRIVERS = BuildConfig.FLAVOR == "full" || BuildConfig.FLAVOR == "pumpcontrol"
override val FLAVOR = BuildConfig.FLAVOR
override val VERSION_NAME = BuildConfig.VERSION_NAME
override val currentDeviceModelString =
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
}

View file

@ -2,7 +2,6 @@ package info.nightscout.androidaps
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Rect
import android.os.Bundle
import android.os.PersistableBundle
@ -22,7 +21,6 @@ import android.widget.TextView
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.core.app.ActivityCompat
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayoutMediator
import com.google.firebase.crashlytics.FirebaseCrashlytics
@ -58,7 +56,6 @@ import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.IconsProvider
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
import info.nightscout.androidaps.utils.ui.UIRunnable
@ -77,7 +74,6 @@ class MainActivity : NoSplashAppCompatActivity() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var androidPermission: AndroidPermission
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var loopPlugin: LoopPlugin
@ -234,21 +230,6 @@ class MainActivity : NoSplashAppCompatActivity() {
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (permissions.isNotEmpty()) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
when (requestCode) {
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY, AndroidPermission.CASE_PHONE_STATE, AndroidPermission.CASE_SYSTEM_WINDOW -> {
}
}
}
}
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
val v = currentFocus

View file

@ -8,14 +8,10 @@ import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.activity_preferences.*
import javax.inject.Inject
class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
@Inject lateinit var resourceHelper: ResourceHelper
var preferenceId = 0
var myPreferenceFragment: MyPreferenceFragment? = null

View file

@ -24,15 +24,14 @@ import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import kotlinx.android.synthetic.main.activity_profilehelper.*
import java.text.DecimalFormat
import javax.inject.Inject
class ProfileHelperActivity : NoSplashAppCompatActivity() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var tddCalculator: TddCalculator
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var defaultProfile: DefaultProfile
@ -229,7 +228,9 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
ProfileType.AVAILABLE_PROFILE -> activePlugin.activeProfileInterface.profile?.getSpecificProfile(profileList[profileUsed[tab]].toString())
ProfileType.PROFILE_SWITCH -> profileSwitch[profileSwitchUsed[tab]].profileObject?.convertToNonCustomizedProfile()
}
} catch (e: Exception) { null }
} catch (e: Exception) {
null
}
private fun getProfileName(age: Double, tdd: Double, weight: Double, basalSumPct: Double, tab: Int): String =
when (typeSelected[tab]) {

View file

@ -15,6 +15,7 @@ class RequestDexcomPermissionActivity : DialogAppCompatActivity() {
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
finish()
}

View file

@ -3,18 +3,16 @@ package info.nightscout.androidaps.activities
import android.os.Bundle
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.ActivityMonitor
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.androidaps.utils.stats.TirCalculator
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.activity_stats.*
import javax.inject.Inject
class StatsActivity : NoSplashAppCompatActivity() {
@Inject lateinit var tddCalculator: TddCalculator
@Inject lateinit var tirCalculator: TirCalculator
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activityMonitor: ActivityMonitor
override fun onCreate(savedInstanceState: Bundle?) {

View file

@ -16,7 +16,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.InstanceId
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.stats.TddCalculator
import info.nightscout.androidaps.utils.stats.TirCalculator
import kotlinx.android.synthetic.main.activity_survey.*
@ -24,7 +23,6 @@ import javax.inject.Inject
class SurveyActivity : NoSplashAppCompatActivity() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var activePlugin: ActivePluginProvider
@Inject lateinit var tddCalculator: TddCalculator
@Inject lateinit var tirCalculator: TirCalculator

View file

@ -31,7 +31,6 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.T
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@ -49,7 +48,6 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var sp: SP
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var defaultValueHelper: DefaultValueHelper
@Inject lateinit var iobCobCalculatorPluginHistory: IobCobCalculatorPluginHistory

View file

@ -16,6 +16,7 @@ import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.events.EventAppExit
import info.nightscout.androidaps.interfaces.ConfigInterface
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag
@ -53,6 +54,7 @@ class ImportExportPrefs @Inject constructor(
private val buildHelper: BuildHelper,
private val rxBus: RxBusWrapper,
private val passwordCheck: PasswordCheck,
private val config: ConfigInterface,
private val androidPermission: AndroidPermission,
private val classicPrefsFormat: ClassicPrefsFormat,
private val encryptedPrefsFormat: EncryptedPrefsFormat,
@ -74,8 +76,8 @@ class ImportExportPrefs @Inject constructor(
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
fragment.activity?.let {
androidPermission.askForPermission(it, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE), AndroidPermission.CASE_STORAGE)
androidPermission.askForPermission(it,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE))
}
} else {
onGranted.run()
@ -91,7 +93,7 @@ class ImportExportPrefs @Inject constructor(
metadata[PrefsMetadataKey.CREATED_AT] = PrefMetadata(DateUtil.toISOString(Date()), PrefsStatus.OK)
metadata[PrefsMetadataKey.AAPS_VERSION] = PrefMetadata(BuildConfig.VERSION_NAME, PrefsStatus.OK)
metadata[PrefsMetadataKey.AAPS_FLAVOUR] = PrefMetadata(BuildConfig.FLAVOR, PrefsStatus.OK)
metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(getCurrentDeviceModelString(), PrefsStatus.OK)
metadata[PrefsMetadataKey.DEVICE_MODEL] = PrefMetadata(config.currentDeviceModelString, PrefsStatus.OK)
if (prefsEncryptionIsDisabled()) {
metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata("Disabled", PrefsStatus.DISABLED)

View file

@ -17,7 +17,6 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWiza
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.wizard.QuickWizard
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@ -26,7 +25,6 @@ import javax.inject.Inject
class QuickWizardListActivity : NoSplashAppCompatActivity() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var quickWizard: QuickWizard
@Inject lateinit var dateUtil: DateUtil

View file

@ -21,17 +21,16 @@ import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePas
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.activity_smscommunicator_otp.*
import net.glxn.qrgen.android.QRCode
import javax.inject.Inject
class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() {
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
@Inject lateinit var otp: OneTimePassword
@Inject lateinit var resourceHelper: ResourceHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View file

@ -118,7 +118,7 @@ class SWDefinition @Inject constructor(
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility { androidPermission.permissionNotGranted(context, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) }
.action { androidPermission.askForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY) })
.action { androidPermission.askForPermission(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) })
.visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) }
.validator { !androidPermission.permissionNotGranted(activity, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) }
private val screenPermissionBt = SWScreen(injector, R.string.permission)
@ -129,7 +129,7 @@ class SWDefinition @Inject constructor(
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) }
.action { androidPermission.askForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION, AndroidPermission.CASE_LOCATION) })
.action { androidPermission.askForPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) })
.visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) }
.validator { !androidPermission.permissionNotGranted(activity, Manifest.permission.ACCESS_FINE_LOCATION) }
private val screenPermissionStore = SWScreen(injector, R.string.permission)
@ -140,7 +140,7 @@ class SWDefinition @Inject constructor(
.add(SWButton(injector)
.text(R.string.askforpermission)
.visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) }
.action { androidPermission.askForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE) })
.action { androidPermission.askForPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) })
.visibility { androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) }
.validator { !androidPermission.permissionNotGranted(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) }
private val screenImport = SWScreen(injector, R.string.nav_import)

View file

@ -1,11 +1,9 @@
package info.nightscout.androidaps.setupwizard
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.core.app.ActivityCompat
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.MainActivity
import info.nightscout.androidaps.R
@ -19,12 +17,9 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange
import info.nightscout.androidaps.setupwizard.elements.SWItem
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.showConfirmation
import info.nightscout.androidaps.utils.locale.LocaleHelper.update
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@ -39,7 +34,6 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
@Inject lateinit var swDefinition: SWDefinition
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var sp: SP
@Inject lateinit var fabricPrivacy: FabricPrivacy
@ -123,7 +117,7 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
sw_scrollview?.smoothScrollTo(0, 0)
}
private fun updateButtons() {
override fun updateButtons() {
runOnUiThread {
val currentScreen = screens[currentWizardPage]
if (currentScreen.validator == null || currentScreen.validator!!.isValid || currentScreen.skippable) {
@ -198,25 +192,4 @@ class SetupWizardActivity : NoSplashAppCompatActivity() {
}
return max(currentWizardPage, 0)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (permissions.isNotEmpty()) {
if (ActivityCompat.checkSelfPermission(this, permissions[0]) == PackageManager.PERMISSION_GRANTED) {
when (requestCode) {
AndroidPermission.CASE_STORAGE -> //show dialog after permission is granted
show(this, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
AndroidPermission.CASE_LOCATION, AndroidPermission.CASE_SMS, AndroidPermission.CASE_BATTERY -> {
}
}
}
}
updateButtons()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == AndroidPermission.CASE_BATTERY) updateButtons()
}
}

View file

@ -10,11 +10,11 @@ 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 androidx.fragment.app.FragmentActivity
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
@ -34,23 +34,13 @@ class AndroidPermission @Inject constructor(
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
private var permissionBatteryOptimizationFailed = false
@SuppressLint("BatteryLife")
fun askForPermission(activity: FragmentActivity, permission: Array<String>, requestCode: Int) {
fun askForPermission(activity: FragmentActivity, permissions: Array<String>) {
var test = false
var testBattery = false
for (s in permission) {
for (s in permissions) {
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
@ -59,30 +49,26 @@ class AndroidPermission @Inject constructor(
}
}
if (test) {
ActivityCompat.requestPermissions(activity, permission, requestCode)
if (activity is DaggerAppCompatActivityWithResult)
activity.requestMultiplePermissions.launch(permissions)
}
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)
if (activity is DaggerAppCompatActivityWithResult)
activity.callForBatteryOptimization.launch(null)
} catch (e: ActivityNotFoundException) {
permission_battery_optimization_failed = true
permissionBatteryOptimizationFailed = true
show(activity, resourceHelper.gs(R.string.permission), resourceHelper.gs(R.string.alert_dialog_permission_battery_optimization_failed), Runnable { activity.recreate() })
}
}
}
fun askForPermission(activity: FragmentActivity, permission: String, requestCode: Int) {
val permissions = arrayOf(permission)
askForPermission(activity, permissions, requestCode)
}
fun askForPermission(activity: FragmentActivity, permission: String) = askForPermission(activity, arrayOf(permission))
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) {
if (!permissionBatteryOptimizationFailed) {
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
val packageName = context.packageName
selfCheck = selfCheck && powerManager.isIgnoringBatteryOptimizations(packageName)
@ -96,17 +82,17 @@ class AndroidPermission @Inject constructor(
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 {
notification.action(R.string.request) {
askForPermission(activity, arrayOf(Manifest.permission.RECEIVE_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_MMS), CASE_SMS)
})
Manifest.permission.RECEIVE_MMS))
}
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SMS))
// Following is a bug in Android 8
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) })
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.READ_PHONE_STATE)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_PHONESTATE))
}
@ -116,7 +102,7 @@ class AndroidPermission @Inject constructor(
fun notifyForBatteryOptimizationPermission(activity: FragmentActivity) {
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) })
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_BATTERY))
}
@ -124,10 +110,10 @@ class AndroidPermission @Inject constructor(
@Synchronized fun notifyForStoragePermission(activity: FragmentActivity) {
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 {
notification.action(R.string.request) {
askForPermission(activity, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE), CASE_STORAGE)
})
Manifest.permission.WRITE_EXTERNAL_STORAGE))
}
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_STORAGE))
}
@ -135,7 +121,7 @@ class AndroidPermission @Inject constructor(
@Synchronized fun notifyForLocationPermissions(activity: FragmentActivity) {
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) })
notification.action(R.string.request) { askForPermission(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)) }
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_LOCATION))
}
@ -145,7 +131,7 @@ class AndroidPermission @Inject constructor(
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 {
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
@ -154,7 +140,7 @@ class AndroidPermission @Inject constructor(
Uri.parse("package:" + activity.packageName))
activity.startActivity(intent)
}
})
}
rxBus.send(EventNewNotification(notification))
} else rxBus.send(EventDismissNotification(Notification.PERMISSION_SYSTEM_WINDOW))
}

View file

@ -38,7 +38,6 @@
<string name="reset_db_confirm">Do you really want to reset the databases?</string>
<string name="nav_exit">Exit</string>
<string name="ns_sync_use_absolute_title">Always use basal absolute values</string>
<string name="alert_dialog_storage_permission_text">Please reboot your phone or restart AndroidAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)!</string>
<string name="alert_dialog_permission_battery_optimization_failed">This device does not appear to support battery optimization whitelisting - you may experience performance issues.</string>
<string name="description_actions">Some buttons to quickly access common features</string>

View file

@ -17,6 +17,7 @@ dependencies {
api 'androidx.recyclerview:recyclerview:1.1.0'
api 'androidx.gridlayout:gridlayout:1.0.0'
api 'androidx.percentlayout:percentlayout:1.0.0'
api 'androidx.activity:activity-ktx:1.2.0-rc01'
api "com.google.android.material:material:$material_version"
api "com.google.dagger:dagger-android:$dagger_version"

View file

@ -1,12 +1,21 @@
package info.nightscout.androidaps.activities
import android.Manifest
import android.content.pm.PackageManager
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import dagger.android.support.DaggerAppCompatActivity
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.interfaces.ImportExportPrefsInterface
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.permissions.OptimizationPermissionContract
import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation
import javax.inject.Inject
open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() {
@Inject lateinit var resourceHelper: ResourceHelperImplementation
@Inject lateinit var importExportPrefs: ImportExportPrefsInterface
val callForPrefFile = registerForActivityResult(PrefsFileContract()) {
@ -14,4 +23,26 @@ open class DaggerAppCompatActivityWithResult : DaggerAppCompatActivity() {
importExportPrefs.importSharedPreferences(this, it)
}
}
val callForBatteryOptimization = registerForActivityResult(OptimizationPermissionContract()) {
updateButtons()
}
val requestMultiplePermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
if (it.value)
if (ActivityCompat.checkSelfPermission(this, it.key) == PackageManager.PERMISSION_GRANTED) {
when (it.key) {
Manifest.permission.WRITE_EXTERNAL_STORAGE ->
//show dialog after permission is granted
OKDialog.show(this, "", resourceHelper.gs(R.string.alert_dialog_storage_permission_text))
// ignore the rest
}
}
}
updateButtons()
}
// Used for SetupWizardActivity
open fun updateButtons() {}
}

View file

@ -8,4 +8,5 @@ interface ConfigInterface {
val PUMPDRIVERS: Boolean
val FLAVOR: String
val VERSION_NAME: String
val currentDeviceModelString : String
}

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.general.maintenance
import android.os.Build
import android.os.Environment
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.interfaces.ConfigInterface
@ -18,9 +17,6 @@ import javax.inject.Inject
import javax.inject.Singleton
import kotlin.math.abs
fun getCurrentDeviceModelString() =
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
@Singleton
class PrefFileListProvider @Inject constructor(
private val resourceHelper: ResourceHelper,
@ -117,7 +113,7 @@ class PrefFileListProvider @Inject constructor(
}
meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model ->
if (model.value != getCurrentDeviceModelString()) {
if (model.value != config.currentDeviceModelString) {
model.status = PrefsStatus.WARN
model.info = resourceHelper.gs(R.string.metadata_warning_different_device)
}

View file

@ -5,23 +5,23 @@ import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerAppCompatActivity
import info.nightscout.androidaps.core.R
import info.nightscout.androidaps.core.databinding.MaintenanceImportListActivityBinding
import info.nightscout.androidaps.core.databinding.MaintenanceImportListItemBinding
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFormatsHandler
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.locale.LocaleHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.maintenance_importlist_activity.*
import javax.inject.Inject
class PrefImportListActivity : DaggerAppCompatActivity() {
@ -29,38 +29,33 @@ class PrefImportListActivity : DaggerAppCompatActivity() {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var prefFileListProvider: PrefFileListProvider
private lateinit var binding: MaintenanceImportListActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.AppTheme)
setContentView(R.layout.maintenance_importlist_activity)
binding = MaintenanceImportListActivityBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
title = resourceHelper.gs(R.string.preferences_import_list_title)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(true)
importlist_recyclerview.layoutManager = LinearLayoutManager(this)
importlist_recyclerview.adapter = RecyclerViewAdapter(prefFileListProvider.listPreferenceFiles(loadMetadata = true))
binding.recyclerview.layoutManager = LinearLayoutManager(this)
binding.recyclerview.adapter = RecyclerViewAdapter(prefFileListProvider.listPreferenceFiles(loadMetadata = true))
}
inner class RecyclerViewAdapter internal constructor(private var prefFileList: List<PrefsFile>) : RecyclerView.Adapter<RecyclerViewAdapter.PrefFileViewHolder>() {
inner class PrefFileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var fileName: TextView = itemView.findViewById(R.id.filelist_name)
var fileDir: TextView = itemView.findViewById(R.id.filelist_dir)
var metaDateTime: TextView = itemView.findViewById(R.id.meta_date_time)
var metaDeviceName: TextView = itemView.findViewById(R.id.meta_device_name)
var metaAppVersion: TextView = itemView.findViewById(R.id.meta_app_version)
var metaVariantFormat: TextView = itemView.findViewById(R.id.meta_variant_format)
var metalineName: View = itemView.findViewById(R.id.metaline_name)
var metaDateTimeIcon: View = itemView.findViewById(R.id.meta_date_time_icon)
inner class PrefFileViewHolder(val maintenanceImportListItemBinding: MaintenanceImportListItemBinding) : RecyclerView.ViewHolder(maintenanceImportListItemBinding.root) {
init {
itemView.isClickable = true
itemView.setOnClickListener {
val prefFile = fileName.tag as PrefsFile
with(maintenanceImportListItemBinding) {
root.isClickable = true
maintenanceImportListItemBinding.root.setOnClickListener {
val prefFile = filelistName.tag as PrefsFile
val i = Intent()
i.putExtra(PrefsFileContract.OUTPUT_PARAM, prefFile)
@ -69,10 +64,11 @@ class PrefImportListActivity : DaggerAppCompatActivity() {
}
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PrefFileViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.maintenance_importlist_item, parent, false)
return PrefFileViewHolder(v)
val binding = MaintenanceImportListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return PrefFileViewHolder(binding)
}
override fun getItemCount(): Int {
@ -81,44 +77,45 @@ class PrefImportListActivity : DaggerAppCompatActivity() {
override fun onBindViewHolder(holder: PrefFileViewHolder, position: Int) {
val prefFile = prefFileList[position]
holder.fileName.text = prefFile.file.name
holder.fileName.tag = prefFile
with(holder.maintenanceImportListItemBinding) {
filelistName.text = prefFile.file.name
filelistName.tag = prefFile
holder.fileDir.text = resourceHelper.gs(R.string.in_directory, prefFile.file.parentFile.absolutePath)
filelistDir.text = resourceHelper.gs(R.string.in_directory, prefFile.file.parentFile.absolutePath)
val visible = if (prefFile.handler == PrefsFormatsHandler.CLASSIC) View.GONE else View.VISIBLE
holder.metalineName.visibility = visible
holder.metaDateTimeIcon.visibility = visible
holder.metaAppVersion.visibility = visible
val visible = (prefFile.handler != PrefsFormatsHandler.CLASSIC).toVisibility()
metalineName.visibility = visible
metaDateTimeIcon.visibility = visible
metaAppVersion.visibility = visible
if (prefFile.handler == PrefsFormatsHandler.CLASSIC) {
holder.metaVariantFormat.text = resourceHelper.gs(R.string.metadata_format_old)
holder.metaVariantFormat.setTextColor(resourceHelper.gc(R.color.metadataTextWarning))
holder.metaDateTime.text = " "
metaVariantFormat.text = resourceHelper.gs(R.string.metadata_format_old)
metaVariantFormat.setTextColor(resourceHelper.gc(R.color.metadataTextWarning))
metaDateTime.text = " "
} else {
prefFile.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.let {
holder.metaVariantFormat.text = it.value
metaVariantFormat.text = it.value
val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning
holder.metaVariantFormat.setTextColor(resourceHelper.gc(color))
metaVariantFormat.setTextColor(resourceHelper.gc(color))
}
prefFile.metadata[PrefsMetadataKey.CREATED_AT]?.let {
holder.metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value)
metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value)
}
prefFile.metadata[PrefsMetadataKey.AAPS_VERSION]?.let {
holder.metaAppVersion.text = it.value
metaAppVersion.text = it.value
val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning
holder.metaAppVersion.setTextColor(resourceHelper.gc(color))
metaAppVersion.setTextColor(resourceHelper.gc(color))
}
prefFile.metadata[PrefsMetadataKey.DEVICE_NAME]?.let {
holder.metaDeviceName.text = it.value
metaDeviceName.text = it.value
}
}
}
}
}

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.utils.permissions
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.activity.result.contract.ActivityResultContract
class OptimizationPermissionContract : ActivityResultContract<Void, Unit>() {
override fun parseResult(resultCode: Int, intent: Intent?): Unit? = null
override fun createIntent(context: Context, input: Void?): Intent {
return Intent().also {
it.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
it.data = Uri.parse("package:" + context.packageName)
}
}
}

View file

@ -11,7 +11,7 @@
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/importlist_recyclerview"
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="true"

View file

@ -311,6 +311,9 @@
<string name="running_invalid_version">We have detected that you are running an invalid version. Loop disabled!</string>
<string name="versionavailable">Version %1$s available</string>
<!-- Permissions -->
<string name="alert_dialog_storage_permission_text">Please reboot your phone or restart AndroidAPS from the System Settings \notherwise Android APS will not have logging (important to track and verify that the algorithms are working correctly)!</string>
<plurals name="days">
<item quantity="one">%1$d day</item>
<item quantity="other">%1$d days</item>

View file

@ -31,7 +31,6 @@ import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import java.util.*
@ -41,7 +40,6 @@ class DanaHistoryActivity : NoSplashAppCompatActivity() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var profileFunction: ProfileFunction
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var activePlugin: ActivePluginProvider

View file

@ -19,7 +19,6 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import java.text.DecimalFormat
@ -32,7 +31,6 @@ class DanaUserOptionsActivity : NoSplashAppCompatActivity() {
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var context: Context
@Inject lateinit var danaPump: DanaPump
@Inject lateinit var activePlugin: ActivePluginProvider

View file

@ -12,7 +12,6 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.hexStringToByteArray
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.textValidator.DefaultEditTextValidator
import info.nightscout.androidaps.utils.textValidator.EditTextValidator
@ -25,7 +24,6 @@ class EnterPinActivity : NoSplashAppCompatActivity() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var danaRSPlugin: DanaRSPlugin
@Inject lateinit var sp: SP
@Inject lateinit var bleComm: BLEComm

View file

@ -30,7 +30,6 @@ import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
@ -43,7 +42,6 @@ import javax.inject.Inject
class PodManagementActivity : NoSplashAppCompatActivity() {
@Inject lateinit var rxBus: RxBusWrapper
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var commandQueue: CommandQueueProvider
@Inject lateinit var podStateManager: PodStateManager