Merge branch 'biometric' into dagger3
This commit is contained in:
commit
0e9f643241
16 changed files with 338 additions and 141 deletions
|
@ -241,6 +241,7 @@ dependencies {
|
||||||
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
|
implementation 'androidx.biometric:biometric:1.0.1'
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation 'androidx.percentlayout:percentlayout:1.0.0'
|
implementation 'androidx.percentlayout:percentlayout:1.0.0'
|
||||||
|
|
|
@ -61,10 +61,10 @@ import info.nightscout.androidaps.utils.AndroidPermission;
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||||
import info.nightscout.androidaps.utils.OKDialog;
|
import info.nightscout.androidaps.utils.OKDialog;
|
||||||
import info.nightscout.androidaps.utils.PasswordProtection;
|
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper;
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper;
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
|
||||||
|
@ -189,6 +189,12 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
||||||
disposable.clear();
|
disposable.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
ProtectionCheck.INSTANCE.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null, this::finish, this::finish);
|
||||||
|
}
|
||||||
|
|
||||||
private void setWakeLock() {
|
private void setWakeLock() {
|
||||||
boolean keepScreenOn = sp.getBoolean(R.string.key_keep_screen_on, false);
|
boolean keepScreenOn = sp.getBoolean(R.string.key_keep_screen_on, false);
|
||||||
if (keepScreenOn)
|
if (keepScreenOn)
|
||||||
|
@ -302,11 +308,11 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case R.id.nav_preferences:
|
case R.id.nav_preferences:
|
||||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
|
ProtectionCheck.INSTANCE.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||||
Intent i = new Intent(this, PreferencesActivity.class);
|
Intent i = new Intent(this, PreferencesActivity.class);
|
||||||
i.putExtra("id", -1);
|
i.putExtra("id", -1);
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
}, null);
|
});
|
||||||
return true;
|
return true;
|
||||||
case R.id.nav_historybrowser:
|
case R.id.nav_historybrowser:
|
||||||
startActivity(new Intent(this, HistoryBrowseActivity.class));
|
startActivity(new Intent(this, HistoryBrowseActivity.class));
|
||||||
|
@ -342,11 +348,11 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
||||||
case R.id.nav_plugin_preferences:
|
case R.id.nav_plugin_preferences:
|
||||||
ViewPager viewPager = findViewById(R.id.pager);
|
ViewPager viewPager = findViewById(R.id.pager);
|
||||||
final PluginBase plugin = ((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem());
|
final PluginBase plugin = ((TabPageAdapter) viewPager.getAdapter()).getPluginAt(viewPager.getCurrentItem());
|
||||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
|
ProtectionCheck.INSTANCE.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||||
Intent i = new Intent(this, PreferencesActivity.class);
|
Intent i = new Intent(this, PreferencesActivity.class);
|
||||||
i.putExtra("id", plugin.getPreferencesId());
|
i.putExtra("id", plugin.getPreferencesId());
|
||||||
startActivity(i);
|
startActivity(i);
|
||||||
}, null);
|
});
|
||||||
return true;
|
return true;
|
||||||
/*
|
/*
|
||||||
case R.id.nav_survey:
|
case R.id.nav_survey:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.activities
|
package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||||
|
@ -51,6 +52,7 @@ import info.nightscout.androidaps.plugins.source.PoctechPlugin
|
||||||
import info.nightscout.androidaps.plugins.source.TomatoPlugin
|
import info.nightscout.androidaps.plugins.source.TomatoPlugin
|
||||||
import info.nightscout.androidaps.utils.OKDialog.show
|
import info.nightscout.androidaps.utils.OKDialog.show
|
||||||
import info.nightscout.androidaps.utils.SafeParse
|
import info.nightscout.androidaps.utils.SafeParse
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -211,6 +213,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
updatePrefSummary(findPreference(key))
|
updatePrefSummary(findPreference(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
private fun addPreferencesFromResource(@XmlRes preferencesResId: Int, key: String?) {
|
private fun addPreferencesFromResource(@XmlRes preferencesResId: Int, key: String?) {
|
||||||
val xmlRoot = preferenceManager.inflateFromResource(context,
|
val xmlRoot = preferenceManager.inflateFromResource(context,
|
||||||
preferencesResId, null)
|
preferencesResId, null)
|
||||||
|
@ -247,6 +250,24 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
private fun updatePrefSummary(pref: Preference?) {
|
private fun updatePrefSummary(pref: Preference?) {
|
||||||
if (pref is ListPreference) {
|
if (pref is ListPreference) {
|
||||||
pref.setSummary(pref.entry)
|
pref.setSummary(pref.entry)
|
||||||
|
// Preferences
|
||||||
|
// Preferences
|
||||||
|
if (pref.getKey() == resourceHelper.gs(R.string.key_settings_protection)) {
|
||||||
|
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_settings_password))
|
||||||
|
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.PASSWORD.ordinal.toString()
|
||||||
|
}
|
||||||
|
// Application
|
||||||
|
// Application
|
||||||
|
if (pref.getKey() == resourceHelper.gs(R.string.key_application_protection)) {
|
||||||
|
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_application_password))
|
||||||
|
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.PASSWORD.ordinal.toString()
|
||||||
|
}
|
||||||
|
// Bolus
|
||||||
|
// Bolus
|
||||||
|
if (pref.getKey() == resourceHelper.gs(R.string.key_bolus_protection)) {
|
||||||
|
val pass: Preference? = findPreference(resourceHelper.gs(R.string.key_bolus_password))
|
||||||
|
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.PASSWORD.ordinal.toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pref is EditTextPreference) {
|
if (pref is EditTextPreference) {
|
||||||
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
|
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||||
import info.nightscout.androidaps.utils.LocaleHelper
|
import info.nightscout.androidaps.utils.LocaleHelper
|
||||||
import info.nightscout.androidaps.utils.PasswordProtection
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class SingleFragmentActivity : DaggerAppCompatActivity() {
|
class SingleFragmentActivity : DaggerAppCompatActivity() {
|
||||||
|
@ -36,7 +36,7 @@ class SingleFragmentActivity : DaggerAppCompatActivity() {
|
||||||
finish()
|
finish()
|
||||||
return true
|
return true
|
||||||
} else if (item.itemId == R.id.nav_plugin_preferences) {
|
} else if (item.itemId == R.id.nav_plugin_preferences) {
|
||||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", Runnable {
|
ProtectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||||
val i = Intent(this, PreferencesActivity::class.java)
|
val i = Intent(this, PreferencesActivity::class.java)
|
||||||
i.putExtra("id", plugin?.preferencesId)
|
i.putExtra("id", plugin?.preferencesId)
|
||||||
startActivity(i)
|
startActivity(i)
|
||||||
|
|
|
@ -12,15 +12,14 @@ import android.widget.RadioButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
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.events.EventRebuildTabs
|
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
import info.nightscout.androidaps.plugins.bus.RxBusWrapper
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.PasswordProtection
|
|
||||||
import info.nightscout.androidaps.utils.extensions.plusAssign
|
import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.toVisibility
|
import info.nightscout.androidaps.utils.toVisibility
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
@ -47,16 +46,20 @@ class ConfigBuilderFragment : DaggerFragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
if (PasswordProtection.isLocked("settings_password"))
|
if (ProtectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES))
|
||||||
configbuilder_main_layout.visibility = View.GONE
|
configbuilder_main_layout.visibility = View.GONE
|
||||||
else
|
else
|
||||||
unlock.visibility = View.GONE
|
unlock.visibility = View.GONE
|
||||||
|
|
||||||
unlock.setOnClickListener {
|
unlock.setOnClickListener {
|
||||||
PasswordProtection.QueryPassword(context, R.string.settings_password, "settings_password", {
|
activity?.let { activity ->
|
||||||
|
ProtectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||||
|
activity.runOnUiThread {
|
||||||
configbuilder_main_layout.visibility = View.VISIBLE
|
configbuilder_main_layout.visibility = View.VISIBLE
|
||||||
unlock.visibility = View.GONE
|
unlock.visibility = View.GONE
|
||||||
}, null)
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,12 +147,14 @@ class ConfigBuilderFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginPreferences.setOnClickListener {
|
pluginPreferences.setOnClickListener {
|
||||||
PasswordProtection.QueryPassword(fragment.context, R.string.settings_password, "settings_password", {
|
fragment.activity?.let { activity ->
|
||||||
|
ProtectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, Runnable {
|
||||||
val i = Intent(fragment.context, PreferencesActivity::class.java)
|
val i = Intent(fragment.context, PreferencesActivity::class.java)
|
||||||
i.putExtra("id", plugin.preferencesId)
|
i.putExtra("id", plugin.preferencesId)
|
||||||
fragment.startActivity(i)
|
fragment.startActivity(i)
|
||||||
}, null)
|
}, null)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.configBuilder
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.CheckBox
|
|
||||||
import android.widget.ImageButton
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.RadioButton
|
|
||||||
import android.widget.TextView
|
|
||||||
import info.nightscout.androidaps.R
|
|
||||||
import info.nightscout.androidaps.activities.PreferencesActivity
|
|
||||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
|
||||||
import info.nightscout.androidaps.interfaces.PluginType
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
|
||||||
import info.nightscout.androidaps.utils.PasswordProtection
|
|
||||||
import info.nightscout.androidaps.utils.toVisibility
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import info.nightscout.androidaps.utils.extensions.plusAssign
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import info.nightscout.androidaps.utils.toVisibility
|
import info.nightscout.androidaps.utils.toVisibility
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import kotlinx.android.synthetic.main.actions_fragment.*
|
import kotlinx.android.synthetic.main.actions_fragment.*
|
||||||
|
@ -72,11 +73,13 @@ class ActionsFragment : DaggerFragment() {
|
||||||
fragmentManager?.let { TempTargetDialog().show(it, "Actions") }
|
fragmentManager?.let { TempTargetDialog().show(it, "Actions") }
|
||||||
}
|
}
|
||||||
actions_extendedbolus.setOnClickListener {
|
actions_extendedbolus.setOnClickListener {
|
||||||
context?.let { context ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(context, resourceHelper.gs(R.string.extended_bolus), resourceHelper.gs(R.string.ebstopsloop),
|
ProtectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable {
|
||||||
|
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), resourceHelper.gs(R.string.ebstopsloop),
|
||||||
Runnable {
|
Runnable {
|
||||||
fragmentManager?.let { ExtendedBolusDialog().show(it, "Actions") }
|
fragmentManager?.let { ExtendedBolusDialog().show(it, "Actions") }
|
||||||
}, null)
|
}, null)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions_extendedbolus_cancel.setOnClickListener {
|
actions_extendedbolus_cancel.setOnClickListener {
|
||||||
|
@ -116,7 +119,11 @@ class ActionsFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actions_fill.setOnClickListener { fragmentManager?.let { FillDialog().show(it, "FillDialog") } }
|
actions_fill.setOnClickListener {
|
||||||
|
activity?.let { activity ->
|
||||||
|
ProtectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { fragmentManager?.let { FillDialog().show(it, "FillDialog") } })
|
||||||
|
}
|
||||||
|
}
|
||||||
actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
|
actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
|
||||||
actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
|
actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
|
||||||
actions_bgcheck.setOnClickListener {
|
actions_bgcheck.setOnClickListener {
|
||||||
|
|
|
@ -122,6 +122,7 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP;
|
||||||
import info.nightscout.androidaps.utils.wizard.BolusWizard;
|
import info.nightscout.androidaps.utils.wizard.BolusWizard;
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard;
|
import info.nightscout.androidaps.utils.wizard.QuickWizard;
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -856,11 +857,10 @@ public class OverviewFragment extends DaggerFragment implements View.OnClickList
|
||||||
onClickAcceptTemp();
|
onClickAcceptTemp();
|
||||||
break;
|
break;
|
||||||
case R.id.overview_quickwizardbutton:
|
case R.id.overview_quickwizardbutton:
|
||||||
onClickQuickwizard();
|
ProtectionCheck.INSTANCE.queryProtection(getActivity(), ProtectionCheck.Protection.BOLUS, this::onClickQuickwizard);
|
||||||
break;
|
break;
|
||||||
case R.id.overview_wizardbutton:
|
case R.id.overview_wizardbutton:
|
||||||
WizardDialog wizardDialog = new WizardDialog();
|
ProtectionCheck.INSTANCE.queryProtection(getActivity(), ProtectionCheck.Protection.BOLUS, () -> new WizardDialog().show(manager, "WizardDialog"));
|
||||||
wizardDialog.show(manager, "WizardDialog");
|
|
||||||
break;
|
break;
|
||||||
case R.id.overview_calibrationbutton:
|
case R.id.overview_calibrationbutton:
|
||||||
if (xdrip) {
|
if (xdrip) {
|
||||||
|
@ -894,13 +894,13 @@ public class OverviewFragment extends DaggerFragment implements View.OnClickList
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case R.id.overview_treatmentbutton:
|
case R.id.overview_treatmentbutton:
|
||||||
new TreatmentDialog().show(manager, "Overview");
|
ProtectionCheck.INSTANCE.queryProtection(getActivity(), ProtectionCheck.Protection.BOLUS, () -> new TreatmentDialog().show(manager, "Overview"));
|
||||||
break;
|
break;
|
||||||
case R.id.overview_insulinbutton:
|
case R.id.overview_insulinbutton:
|
||||||
new InsulinDialog().show(manager, "Overview");
|
ProtectionCheck.INSTANCE.queryProtection(getActivity(), ProtectionCheck.Protection.BOLUS, () -> new InsulinDialog().show(manager, "Overview"));
|
||||||
break;
|
break;
|
||||||
case R.id.overview_carbsbutton:
|
case R.id.overview_carbsbutton:
|
||||||
new CarbsDialog().show(manager, "Overview");
|
ProtectionCheck.INSTANCE.queryProtection(getActivity(), ProtectionCheck.Protection.BOLUS, () -> new CarbsDialog().show(manager, "Overview"));
|
||||||
break;
|
break;
|
||||||
case R.id.overview_pumpstatus:
|
case R.id.overview_pumpstatus:
|
||||||
if (activePlugin.getActivePump().isSuspended() || !activePlugin.getActivePump().isInitialized())
|
if (activePlugin.getActivePump().isSuspended() || !activePlugin.getActivePump().isInitialized())
|
||||||
|
|
|
@ -34,8 +34,8 @@ import info.nightscout.androidaps.setupwizard.elements.*
|
||||||
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
|
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate
|
||||||
import info.nightscout.androidaps.utils.AndroidPermission
|
import info.nightscout.androidaps.utils.AndroidPermission
|
||||||
import info.nightscout.androidaps.utils.LocaleHelper.update
|
import info.nightscout.androidaps.utils.LocaleHelper.update
|
||||||
import info.nightscout.androidaps.utils.PasswordProtection
|
|
||||||
import info.nightscout.androidaps.utils.extensions.isRunningTest
|
import info.nightscout.androidaps.utils.extensions.isRunningTest
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
import info.nightscout.androidaps.utils.sharedPreferences.SP
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -217,12 +217,12 @@ class SWDefinition @Inject constructor(
|
||||||
.add(SWButton(injector)
|
.add(SWButton(injector)
|
||||||
.text(R.string.insulinsourcesetup)
|
.text(R.string.insulinsourcesetup)
|
||||||
.action(Runnable {
|
.action(Runnable {
|
||||||
val plugin = activePlugin.activeInsulin as PluginBase?
|
val plugin = activePlugin.activeInsulin as PluginBase
|
||||||
if (plugin != null) {
|
activity?.let { activity ->
|
||||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -236,12 +236,12 @@ class SWDefinition @Inject constructor(
|
||||||
.add(SWButton(injector)
|
.add(SWButton(injector)
|
||||||
.text(R.string.bgsourcesetup)
|
.text(R.string.bgsourcesetup)
|
||||||
.action(Runnable {
|
.action(Runnable {
|
||||||
val plugin = activePlugin.activeBgSource as PluginBase?
|
val plugin = activePlugin.activeBgSource as PluginBase
|
||||||
if (plugin != null) {
|
activity?.let { activity ->
|
||||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -287,11 +287,13 @@ 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
|
||||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", Runnable {
|
activity?.let { activity ->
|
||||||
|
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)
|
||||||
|
@ -313,12 +315,12 @@ class SWDefinition @Inject constructor(
|
||||||
.add(SWButton(injector)
|
.add(SWButton(injector)
|
||||||
.text(R.string.apssetup)
|
.text(R.string.apssetup)
|
||||||
.action(Runnable {
|
.action(Runnable {
|
||||||
val plugin = activePlugin.activeAPS as PluginBase?
|
val plugin = activePlugin.activeAPS as PluginBase
|
||||||
if (plugin != null) {
|
activity?.let { activity ->
|
||||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -363,12 +365,12 @@ class SWDefinition @Inject constructor(
|
||||||
.add(SWButton(injector)
|
.add(SWButton(injector)
|
||||||
.text(R.string.sensitivitysetup)
|
.text(R.string.sensitivitysetup)
|
||||||
.action(Runnable {
|
.action(Runnable {
|
||||||
val plugin = activePlugin.activeSensitivity as PluginBase?
|
val plugin = activePlugin.activeSensitivity as PluginBase
|
||||||
if (plugin != null) {
|
activity?.let { activity ->
|
||||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
package info.nightscout.androidaps.utils;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.MainApp;
|
|
||||||
import info.nightscout.androidaps.R;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by mike on 14.02.2017.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class PasswordProtection {
|
|
||||||
static public boolean isLocked(String preference) {
|
|
||||||
final String password = SP.getString(preference, "");
|
|
||||||
return !password.equals("");
|
|
||||||
}
|
|
||||||
|
|
||||||
static public void QueryPassword(final Context context, int stringID, String preference, final Runnable ok, final Runnable fail) {
|
|
||||||
final String password = SP.getString(preference, "");
|
|
||||||
if (password.equals("")) {
|
|
||||||
if (ok != null) ok.run();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
View promptsView = LayoutInflater.from(context).inflate(R.layout.passwordprompt, null);
|
|
||||||
|
|
||||||
View titleLayout = LayoutInflater.from(context).inflate(R.layout.dialog_alert_custom, null);
|
|
||||||
((TextView) titleLayout.findViewById(R.id.alertdialog_title)).setText(R.string.confirmation);
|
|
||||||
((ImageView) titleLayout.findViewById(R.id.alertdialog_icon)).setImageResource(R.drawable.ic_check_while_48dp);
|
|
||||||
|
|
||||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
|
|
||||||
alertDialogBuilder.setView(promptsView);
|
|
||||||
alertDialogBuilder.setCustomTitle(titleLayout);
|
|
||||||
|
|
||||||
final TextView label = promptsView.findViewById(R.id.passwordprompt_text);
|
|
||||||
label.setText(MainApp.gs(stringID));
|
|
||||||
final EditText userInput = promptsView.findViewById(R.id.passwordprompt_pass);
|
|
||||||
|
|
||||||
// set dialog message
|
|
||||||
alertDialogBuilder
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton(android.R.string.ok,
|
|
||||||
(dialog, id) -> {
|
|
||||||
String enteredPassword = userInput.getText().toString();
|
|
||||||
if (password.equals(enteredPassword)) {
|
|
||||||
if (ok != null) ok.run();
|
|
||||||
} else {
|
|
||||||
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.wrongpassword));
|
|
||||||
if (fail != null) fail.run();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton(android.R.string.cancel,
|
|
||||||
(dialog, id) -> dialog.cancel());
|
|
||||||
|
|
||||||
AlertDialog alertDialog = alertDialogBuilder.create();
|
|
||||||
alertDialog.show();
|
|
||||||
alertDialog.setCanceledOnTouchOutside(false);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
package info.nightscout.androidaps.utils.protection
|
||||||
|
|
||||||
|
import androidx.biometric.BiometricConstants
|
||||||
|
import androidx.biometric.BiometricPrompt
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
object BiometricCheck {
|
||||||
|
fun biometricPrompt(activity: FragmentActivity, title: Int, ok: Runnable?, cancel: Runnable? = null, fail: Runnable? = null) {
|
||||||
|
val executor = Executors.newSingleThreadExecutor()
|
||||||
|
|
||||||
|
val biometricPrompt = BiometricPrompt(activity, executor, object : BiometricPrompt.AuthenticationCallback() {
|
||||||
|
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||||
|
super.onAuthenticationError(errorCode, errString)
|
||||||
|
when (errorCode) {
|
||||||
|
BiometricConstants.ERROR_UNABLE_TO_PROCESS,
|
||||||
|
BiometricConstants.ERROR_TIMEOUT,
|
||||||
|
BiometricConstants.ERROR_CANCELED,
|
||||||
|
BiometricConstants.ERROR_LOCKOUT,
|
||||||
|
BiometricConstants.ERROR_VENDOR,
|
||||||
|
BiometricConstants.ERROR_LOCKOUT_PERMANENT,
|
||||||
|
BiometricConstants.ERROR_USER_CANCELED -> {
|
||||||
|
ToastUtils.showToastInUiThread(activity.baseContext, errString.toString())
|
||||||
|
fail?.run()
|
||||||
|
}
|
||||||
|
BiometricConstants.ERROR_NEGATIVE_BUTTON ->
|
||||||
|
cancel?.run()
|
||||||
|
BiometricConstants.ERROR_NO_SPACE,
|
||||||
|
BiometricConstants.ERROR_HW_UNAVAILABLE,
|
||||||
|
BiometricConstants.ERROR_HW_NOT_PRESENT,
|
||||||
|
BiometricConstants.ERROR_NO_DEVICE_CREDENTIAL,
|
||||||
|
BiometricConstants.ERROR_NO_BIOMETRICS ->
|
||||||
|
// call ok, because it's not possible to bypass it when biometrics fail
|
||||||
|
ok?.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||||
|
super.onAuthenticationSucceeded(result)
|
||||||
|
// Called when a biometric is recognized.
|
||||||
|
ok?.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAuthenticationFailed() {
|
||||||
|
super.onAuthenticationFailed()
|
||||||
|
// Called when a biometric is valid but not recognized.
|
||||||
|
fail?.run()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||||
|
.setTitle(MainApp.gs(title))
|
||||||
|
.setDescription(MainApp.gs(R.string.biometric_title))
|
||||||
|
.setNegativeButtonText(MainApp.gs(R.string.cancel))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
biometricPrompt.authenticate(promptInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package info.nightscout.androidaps.utils.protection
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import info.nightscout.androidaps.MainApp
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.SP
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
|
||||||
|
object PasswordCheck {
|
||||||
|
fun queryPassword(activity: FragmentActivity, @StringRes labelId: Int, @StringRes preference: Int, ok: Runnable?, cancel: Runnable? = null, fail: Runnable? = null) {
|
||||||
|
val password = SP.getString(preference, "")
|
||||||
|
if (password == "") {
|
||||||
|
ok?.run()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val promptsView = LayoutInflater.from(activity).inflate(R.layout.passwordprompt, null)
|
||||||
|
|
||||||
|
val alertDialogBuilder = AlertDialog.Builder(activity)
|
||||||
|
alertDialogBuilder.setView(promptsView)
|
||||||
|
|
||||||
|
val label = promptsView.findViewById<View>(R.id.passwordprompt_text) as TextView
|
||||||
|
label.text = MainApp.gs(labelId)
|
||||||
|
val userInput = promptsView.findViewById<View>(R.id.passwordprompt_pass) as EditText
|
||||||
|
|
||||||
|
alertDialogBuilder
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(MainApp.gs(R.string.ok)) { _, _ ->
|
||||||
|
val enteredPassword = userInput.text.toString()
|
||||||
|
if (password == enteredPassword) ok?.run()
|
||||||
|
else {
|
||||||
|
ToastUtils.showToastInUiThread(activity, MainApp.gs(R.string.wrongpassword))
|
||||||
|
fail?.run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setNegativeButton(MainApp.gs(R.string.cancel)
|
||||||
|
) { dialog, _ ->
|
||||||
|
cancel?.run()
|
||||||
|
dialog.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
alertDialogBuilder.create().show()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package info.nightscout.androidaps.utils.protection
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.utils.SP
|
||||||
|
|
||||||
|
object ProtectionCheck {
|
||||||
|
enum class Protection {
|
||||||
|
PREFERENCES,
|
||||||
|
APPLICATION,
|
||||||
|
BOLUS
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ProtectionType {
|
||||||
|
NONE,
|
||||||
|
BIOMETRIC,
|
||||||
|
PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
private val passwordsResourceIDs = listOf(
|
||||||
|
R.string.key_settings_password,
|
||||||
|
R.string.key_application_password,
|
||||||
|
R.string.key_bolus_password)
|
||||||
|
|
||||||
|
private val protectionTypeResourceIDs = listOf(
|
||||||
|
R.string.key_settings_protection,
|
||||||
|
R.string.key_application_protection,
|
||||||
|
R.string.key_bolus_protection)
|
||||||
|
|
||||||
|
private val titleResourceIDs = listOf(
|
||||||
|
R.string.settings_password,
|
||||||
|
R.string.application_password,
|
||||||
|
R.string.bolus_password)
|
||||||
|
|
||||||
|
fun isLocked(protection: Protection): Boolean {
|
||||||
|
when (ProtectionType.values()[SP.getInt(protectionTypeResourceIDs[protection.ordinal], ProtectionType.NONE.ordinal)]) {
|
||||||
|
ProtectionType.NONE -> return false
|
||||||
|
ProtectionType.BIOMETRIC -> return true
|
||||||
|
ProtectionType.PASSWORD -> return SP.getString(passwordsResourceIDs[protection.ordinal], "") != ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun queryProtection(activity: FragmentActivity, protection: Protection,
|
||||||
|
ok: Runnable?, cancel: Runnable? = null, fail: Runnable? = null) {
|
||||||
|
when (ProtectionType.values()[SP.getInt(protectionTypeResourceIDs[protection.ordinal], ProtectionType.NONE.ordinal)]) {
|
||||||
|
ProtectionType.NONE ->
|
||||||
|
ok?.run()
|
||||||
|
ProtectionType.BIOMETRIC ->
|
||||||
|
BiometricCheck.biometricPrompt(activity, titleResourceIDs[protection.ordinal], ok, cancel, fail)
|
||||||
|
ProtectionType.PASSWORD ->
|
||||||
|
PasswordCheck.queryPassword(activity, titleResourceIDs[protection.ordinal], passwordsResourceIDs[protection.ordinal], ok, cancel, fail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
app/src/main/res/values/protection.xml
Normal file
36
app/src/main/res/values/protection.xml
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="biometric_title">Authentication required</string>
|
||||||
|
<string name="biometric_description">Place your finger on the fingerprint reader to verify your identity</string>
|
||||||
|
<string name="settings_protection">Settings protection</string>
|
||||||
|
<string name="application_protection">Application protection</string>
|
||||||
|
<string name="bolus_protection">Bolus protection</string>
|
||||||
|
<string name="settings_password">Settings password</string>
|
||||||
|
<string name="application_password">Application password</string>
|
||||||
|
<string name="bolus_password">Bolus password</string>
|
||||||
|
<string name="unlock_settings">Unlock settings</string>
|
||||||
|
<string name="biometric">Biometric</string>
|
||||||
|
<string name="password">Password</string>
|
||||||
|
<string name="noprotection">No protection</string>
|
||||||
|
<string name="protection">Protection</string>
|
||||||
|
|
||||||
|
<string name="key_settings_password" translatable="false">settings_password</string>
|
||||||
|
<string name="key_application_password" translatable="false">application_password</string>
|
||||||
|
<string name="key_bolus_password">translatable="false"bolus_password</string>
|
||||||
|
<string name="key_settings_protection" translatable="false">settings_protection</string>
|
||||||
|
<string name="key_application_protection" translatable="false">application_protection</string>
|
||||||
|
<string name="key_bolus_protection" translatable="false">bolus_protection</string>
|
||||||
|
|
||||||
|
<string-array name="protectiontype">
|
||||||
|
<item>@string/noprotection</item>
|
||||||
|
<item>@string/biometric</item>
|
||||||
|
<item>@string/password</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="protectiontypeValues">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -520,8 +520,6 @@
|
||||||
<string name="virtualpump_settings">Virtual pump settings</string>
|
<string name="virtualpump_settings">Virtual pump settings</string>
|
||||||
<string name="virtualpump_uploadstatus_title">Upload status to NS</string>
|
<string name="virtualpump_uploadstatus_title">Upload status to NS</string>
|
||||||
<string name="wrongpassword">Wrong password</string>
|
<string name="wrongpassword">Wrong password</string>
|
||||||
<string name="settings_password">Password for settings</string>
|
|
||||||
<string name="unlock_settings">Unlock settings</string>
|
|
||||||
<string name="approachingdailylimit">Approaching insulin daily limit</string>
|
<string name="approachingdailylimit">Approaching insulin daily limit</string>
|
||||||
<string name="nsclientinternal">NSClient</string>
|
<string name="nsclientinternal">NSClient</string>
|
||||||
<string name="nsclientinternal_shortname">NSCI</string>
|
<string name="nsclientinternal_shortname">NSCI</string>
|
||||||
|
|
|
@ -20,10 +20,45 @@
|
||||||
android:key="@string/key_language"
|
android:key="@string/key_language"
|
||||||
android:title="@string/language" />
|
android:title="@string/language" />
|
||||||
|
|
||||||
|
<PreferenceCategory android:title="@string/protection">
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="1"
|
||||||
|
android:entries="@array/protectiontype"
|
||||||
|
android:entryValues="@array/protectiontypeValues"
|
||||||
|
android:key="@string/key_settings_protection"
|
||||||
|
android:title="@string/settings_protection" />
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:title="@string/settings_password"
|
android:inputType="textPassword"
|
||||||
android:key="settings_password"
|
android:key="@string/key_settings_password"
|
||||||
android:inputType="textPassword"/>
|
android:title="@string/settings_password" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="1"
|
||||||
|
android:entries="@array/protectiontype"
|
||||||
|
android:entryValues="@array/protectiontypeValues"
|
||||||
|
android:key="@string/key_application_protection"
|
||||||
|
android:title="@string/application_protection" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:key="@string/key_application_password"
|
||||||
|
android:title="@string/application_password" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:defaultValue="1"
|
||||||
|
android:entries="@array/protectiontype"
|
||||||
|
android:entryValues="@array/protectiontypeValues"
|
||||||
|
android:key="@string/key_bolus_protection"
|
||||||
|
android:title="@string/bolus_protection" />
|
||||||
|
|
||||||
|
<EditTextPreference
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:key="@string/key_bolus_password"
|
||||||
|
android:title="@string/bolus_password" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue