biometrics support for Preferences
This commit is contained in:
parent
e440d89537
commit
2c956f43ba
|
@ -235,6 +235,7 @@ dependencies {
|
|||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.0.0'
|
||||
implementation 'androidx.biometric:biometric:1.0.0-rc02'
|
||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'androidx.percentlayout:percentlayout:1.0.0'
|
||||
|
|
|
@ -60,8 +60,8 @@ import info.nightscout.androidaps.utils.AndroidPermission;
|
|||
import info.nightscout.androidaps.utils.FabricPrivacy;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.PasswordProtection;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
|
||||
|
@ -333,11 +333,11 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
int id = item.getItemId();
|
||||
switch (id) {
|
||||
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);
|
||||
i.putExtra("id", -1);
|
||||
startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
return true;
|
||||
case R.id.nav_historybrowser:
|
||||
startActivity(new Intent(this, HistoryBrowseActivity.class));
|
||||
|
@ -375,11 +375,11 @@ public class MainActivity extends NoSplashAppCompatActivity {
|
|||
case R.id.nav_plugin_preferences:
|
||||
ViewPager viewPager = findViewById(R.id.pager);
|
||||
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);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return actionBarDrawerToggle.onOptionsItemSelected(item);
|
||||
|
|
|
@ -15,21 +15,25 @@ import android.text.TextUtils;
|
|||
import info.nightscout.androidaps.Config;
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.events.EventPreferenceChange;
|
||||
import info.nightscout.androidaps.events.EventRebuildTabs;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.interfaces.PluginType;
|
||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader;
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
|
||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.TidepoolPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.tidepool.comm.TidepoolUploader;
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
||||
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
|
||||
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
|
||||
|
@ -42,14 +46,10 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
|
|||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
|
||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
|
||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
|
||||
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.OKDialog;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin;
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck;
|
||||
|
||||
public class PreferencesActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
MyPreferenceFragment myPreferenceFragment;
|
||||
|
@ -87,6 +87,30 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
if (pref instanceof ListPreference) {
|
||||
ListPreference listPref = (ListPreference) pref;
|
||||
pref.setSummary(listPref.getEntry());
|
||||
// Preferences
|
||||
if (pref.getKey().equals(MainApp.gs(R.string.key_settings_protection))) {
|
||||
Preference pass = pref.getPreferenceManager().findPreference(MainApp.gs(R.string.key_settings_password));
|
||||
if (pass != null)
|
||||
if (((ListPreference) pref).getValue().equals(Integer.toString(ProtectionCheck.ProtectionType.PASSWORD.ordinal())))
|
||||
pass.setEnabled(true);
|
||||
else pass.setEnabled(false);
|
||||
}
|
||||
// Application
|
||||
if (pref.getKey().equals(MainApp.gs(R.string.key_application_protection))) {
|
||||
Preference pass = pref.getPreferenceManager().findPreference(MainApp.gs(R.string.key_application_password));
|
||||
if (pass != null)
|
||||
if (((ListPreference) pref).getValue().equals(Integer.toString(ProtectionCheck.ProtectionType.PASSWORD.ordinal())))
|
||||
pass.setEnabled(true);
|
||||
else pass.setEnabled(false);
|
||||
}
|
||||
// Bolus
|
||||
if (pref.getKey().equals(MainApp.gs(R.string.key_bolus_protection))) {
|
||||
Preference pass = pref.getPreferenceManager().findPreference(MainApp.gs(R.string.key_bolus_password));
|
||||
if (pass != null)
|
||||
if (((ListPreference) pref).getValue().equals(Integer.toString(ProtectionCheck.ProtectionType.PASSWORD.ordinal())))
|
||||
pass.setEnabled(true);
|
||||
else pass.setEnabled(false);
|
||||
}
|
||||
}
|
||||
if (pref instanceof EditTextPreference) {
|
||||
EditTextPreference editTextPref = (EditTextPreference) pref;
|
||||
|
@ -97,7 +121,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
|
|||
} else if (editTextPref.getText() != null) {
|
||||
((EditTextPreference) pref).setDialogMessage(editTextPref.getDialogMessage());
|
||||
pref.setSummary(editTextPref.getText());
|
||||
} else if (pref.getKey().contains("smscommunicator_allowednumbers") && (editTextPref.getText() == null || TextUtils.isEmpty(editTextPref.getText().trim()))) {
|
||||
} else if (pref.getKey().contains(SP.getString(R.string.key_smscommunicator_allowednumbers, "")) && (editTextPref.getText() == null || TextUtils.isEmpty(editTextPref.getText().trim()))) {
|
||||
pref.setSummary(MainApp.gs(R.string.smscommunicator_allowednumbers_summary));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import androidx.fragment.app.Fragment;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||
import info.nightscout.androidaps.utils.PasswordProtection;
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck;
|
||||
|
||||
public class SingleFragmentActivity extends AppCompatActivity {
|
||||
|
||||
|
@ -39,13 +39,12 @@ public class SingleFragmentActivity extends AppCompatActivity {
|
|||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
else if (item.getItemId() == R.id.nav_plugin_preferences) {
|
||||
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
|
||||
} else if (item.getItemId() == R.id.nav_plugin_preferences) {
|
||||
ProtectionCheck.INSTANCE.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||
Intent i = new Intent(this, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -14,7 +14,7 @@ import info.nightscout.androidaps.R
|
|||
import info.nightscout.androidaps.interfaces.*
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import info.nightscout.androidaps.utils.PasswordProtection
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.configbuilder_fragment.*
|
||||
|
@ -33,16 +33,20 @@ class ConfigBuilderFragment : Fragment() {
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
if (PasswordProtection.isLocked("settings_password"))
|
||||
if (ProtectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES))
|
||||
configbuilder_main_layout.visibility = View.GONE
|
||||
else
|
||||
unlock.visibility = View.GONE
|
||||
|
||||
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
|
||||
unlock.visibility = View.GONE
|
||||
}, null)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ 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.protection.ProtectionCheck
|
||||
|
||||
class PluginViewHolder internal constructor(private val fragment: ConfigBuilderFragment,
|
||||
private val pluginType: PluginType,
|
||||
|
@ -46,11 +46,13 @@ class PluginViewHolder internal constructor(private val fragment: ConfigBuilderF
|
|||
}
|
||||
|
||||
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)
|
||||
i.putExtra("id", plugin.preferencesId)
|
||||
fragment.startActivity(i)
|
||||
}, null)
|
||||
})
|
||||
}
|
||||
}
|
||||
update()
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@ import info.nightscout.androidaps.setupwizard.elements.SWRadioButton;
|
|||
import info.nightscout.androidaps.setupwizard.events.EventSWUpdate;
|
||||
import info.nightscout.androidaps.utils.AndroidPermission;
|
||||
import info.nightscout.androidaps.utils.LocaleHelper;
|
||||
import info.nightscout.androidaps.utils.PasswordProtection;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck;
|
||||
|
||||
public class SWDefinition {
|
||||
private AppCompatActivity activity;
|
||||
|
@ -216,11 +216,11 @@ public class SWDefinition {
|
|||
.action(() -> {
|
||||
final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin();
|
||||
if (plugin != null) {
|
||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
|
||||
ProtectionCheck.INSTANCE.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||
Intent i = new Intent(activity, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
activity.startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
})
|
||||
.visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveInsulin() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveInsulin()).getPreferencesId() > 0))
|
||||
|
@ -237,11 +237,11 @@ public class SWDefinition {
|
|||
.action(() -> {
|
||||
final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource();
|
||||
if (plugin != null) {
|
||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
|
||||
ProtectionCheck.INSTANCE.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||
Intent i = new Intent(activity, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
activity.startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
})
|
||||
.visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveBgSource() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveBgSource()).getPreferencesId() > 0))
|
||||
|
@ -307,11 +307,11 @@ public class SWDefinition {
|
|||
.action(() -> {
|
||||
final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActivePump();
|
||||
if (plugin != null) {
|
||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
|
||||
ProtectionCheck.INSTANCE.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||
Intent i = new Intent(activity, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
activity.startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
})
|
||||
.visibility(() -> (ConfigBuilderPlugin.getPlugin().getActivePump() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActivePump()).getPreferencesId() > 0)))
|
||||
|
@ -338,11 +338,11 @@ public class SWDefinition {
|
|||
.action(() -> {
|
||||
final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveAPS();
|
||||
if (plugin != null) {
|
||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
|
||||
ProtectionCheck.INSTANCE.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||
Intent i = new Intent(activity, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
activity.startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
})
|
||||
.visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveAPS() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveAPS()).getPreferencesId() > 0))
|
||||
|
@ -392,11 +392,11 @@ public class SWDefinition {
|
|||
.action(() -> {
|
||||
final PluginBase plugin = (PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity();
|
||||
if (plugin != null) {
|
||||
PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> {
|
||||
ProtectionCheck.INSTANCE.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, () -> {
|
||||
Intent i = new Intent(activity, PreferencesActivity.class);
|
||||
i.putExtra("id", plugin.getPreferencesId());
|
||||
activity.startActivity(i);
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
})
|
||||
.visibility(() -> ConfigBuilderPlugin.getPlugin().getActiveSensitivity() != null && ((PluginBase) ConfigBuilderPlugin.getPlugin().getActiveSensitivity()).getPreferencesId() > 0))
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
package info.nightscout.androidaps.utils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
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, "");
|
||||
if (password.equals("")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
LayoutInflater li = LayoutInflater.from(context);
|
||||
View promptsView = li.inflate(R.layout.passwordprompt, null);
|
||||
|
||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
|
||||
alertDialogBuilder.setView(promptsView);
|
||||
|
||||
final TextView label = (TextView) promptsView.findViewById(R.id.passwordprompt_text);
|
||||
label.setText(MainApp.gs(stringID));
|
||||
final EditText userInput = (EditText) promptsView.findViewById(R.id.passwordprompt_pass);
|
||||
|
||||
// set dialog message
|
||||
alertDialogBuilder
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("OK",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,int 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("Cancel",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,int id) {
|
||||
dialog.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
AlertDialog alertDialog = alertDialogBuilder.create();
|
||||
alertDialog.show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package info.nightscout.androidaps.utils.protection
|
||||
|
||||
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, 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)
|
||||
if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON) cancel?.run()
|
||||
else {
|
||||
// Called when an unrecoverable error has been encountered and the operation is complete.
|
||||
ToastUtils.showToastInUiThread(activity.baseContext, errString.toString())
|
||||
// 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(R.string.biometric_title))
|
||||
.setSubtitle("Set the subtitle to display.")
|
||||
.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, 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>
|
|
@ -515,8 +515,6 @@
|
|||
<string name="virtualpump_settings">Virtual pump settings</string>
|
||||
<string name="virtualpump_uploadstatus_title">Upload status to NS</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="nsclientinternal">NSClient</string>
|
||||
<string name="nsclientinternal_shortname">NSCI</string>
|
||||
|
|
|
@ -1,14 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<PreferenceCategory
|
||||
android:key="password"
|
||||
android:title="@string/settings_password">
|
||||
|
||||
<PreferenceCategory android:title="@string/protection">
|
||||
|
||||
<PreferenceScreen 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
|
||||
android:title="@string/settings_password"
|
||||
android:key="settings_password"
|
||||
android:inputType="textPassword">
|
||||
</EditTextPreference>
|
||||
android:inputType="textPassword"
|
||||
android:key="@string/key_settings_password"
|
||||
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" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
Loading…
Reference in a new issue