Skip to content

Commit

Permalink
Merge pull request #39 from zVolt/feature/secure
Browse files Browse the repository at this point in the history
Feature/secure
  • Loading branch information
zkhan93 authored Nov 25, 2021
2 parents d794f0d + 43ff812 commit c988c22
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 241 deletions.
9 changes: 6 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ dependencies {
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'

implementation 'com.github.tgio:rncryptor-native:0.0.9'

implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
//guava-android
// implementation 'com.google.guava:guava:23.4-android'

//implementation 'com.github.PhilJay:MPAndroidChart:v3.0.2'
//guava-android
//implementation 'com.google.guava:guava:23.4-android'

//for registering watch on gmail
implementation 'pub.devrel:easypermissions:3.0.0'
Expand All @@ -117,6 +117,9 @@ dependencies {
exclude group: 'org.apache.httpcomponents'
}

// biometric
implementation "androidx.biometric:biometric:1.1.0"

//JUnit 4 framework
testImplementation 'junit:junit:4.13.1'
// Robolectric environment
Expand Down
9 changes: 0 additions & 9 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SettingsActivity"
android:label="@string/title_settings"
android:parentActivityName=".HomeActivity"
android:theme="@style/AppTheme.NoActionBar">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="io.github.zkhan93.familyfinance.HomeActivity" />
</activity>
<activity
android:name=".SelectFamilyActivity"
android:label="@string/title_activity_select_family"
Expand Down
82 changes: 81 additions & 1 deletion app/src/main/java/io/github/zkhan93/familyfinance/App.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
package io.github.zkhan93.familyfinance;

import static androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_STRONG;
import static androidx.biometric.BiometricManager.Authenticators.DEVICE_CREDENTIAL;

import android.app.Application;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;

import com.google.firebase.database.FirebaseDatabase;

import org.greenrobot.greendao.database.Database;

import java.util.concurrent.Executor;

import io.github.zkhan93.familyfinance.models.DaoMaster;
import io.github.zkhan93.familyfinance.models.DaoSession;

Expand All @@ -17,10 +32,16 @@ public class App extends Application {
public static final boolean ENCRYPTED = false;
private DaoSession daoSession;

private Executor executor;
private BiometricPrompt biometricPrompt;
private BiometricPrompt.PromptInfo promptInfo;
private SharedPreferences spf;
private static String TAG = App.class.getSimpleName();

@Override
public void onCreate() {
super.onCreate();

spf = PreferenceManager.getDefaultSharedPreferences(this);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);

DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,
Expand All @@ -34,4 +55,63 @@ public void onCreate() {
public DaoSession getDaoSession() {
return daoSession;
}

public void setBiometricAuthValidFromTimeToNow() {
spf.edit().putLong(getString(R.string.pref_success_biometric_auth_at),
System.currentTimeMillis()).apply();
}

public void requestBiometricAuth(FragmentActivity activity) {
long biometricAuthThreshold = 10 * 1000;
long lastAuthAt = spf.getLong(getString(R.string.pref_success_biometric_auth_at), 0);
if (lastAuthAt > System.currentTimeMillis() - biometricAuthThreshold) {
setBiometricAuthValidFromTimeToNow();
return;
}
//only if its not very recent
executor = ContextCompat.getMainExecutor(this);
biometricPrompt = new BiometricPrompt(activity,
executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode,
@NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Toast.makeText(getApplicationContext(),
"Authentication is required to use the app!", Toast.LENGTH_SHORT)
.show();
Log.d(TAG, errString.toString());
activity.finish();
}

@Override
public void onAuthenticationSucceeded(
@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
setBiometricAuthValidFromTimeToNow();

}

@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Toast.makeText(getApplicationContext(), "Authentication failed",
Toast.LENGTH_SHORT)
.show();
}
});

BiometricPrompt.PromptInfo.Builder builder = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric login for my app")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText(getString(R.string.cancel));
if (Build.VERSION.SDK_INT > 29) {
builder = builder.setAllowedAuthenticators(BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
}
promptInfo = builder.build();

// Prompt appears when user clicks "Log in".
// Consider integrating with the keystore to unlock cryptographic operations,
// if needed by your app.
biometricPrompt.authenticate(promptInfo);
}
}
112 changes: 2 additions & 110 deletions app/src/main/java/io/github/zkhan93/familyfinance/FragmentSetting.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,9 @@
* Created by zeeshan on 21/10/17.
*/

public class FragmentSetting extends PreferenceFragmentCompat implements Preference
.OnPreferenceChangeListener, SharedPreferences.OnSharedPreferenceChangeListener {
public class FragmentSetting extends PreferenceFragmentCompat {

public static final String TAG = FragmentSetting.class.getSimpleName();
private SharedPreferences sharedPreferences;
private static int REQUEST_CODE_SET_PIN = 102;
private static int REQUEST_CODE_CHECK_PIN = 103;
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
Expand Down Expand Up @@ -71,16 +67,6 @@ public class FragmentSetting extends PreferenceFragmentCompat implements Prefere
preference.setSummary((boolean) value ? R.string.pref_copy_enable : R
.string.pref_copy_disable);
return true;
case "pref_key_pin":
preference.setSummary((boolean) value ? R.string.pref_pin_enable : R
.string.pref_pin_disable);
return true;
case "pref_key_autolock":
int index = ((ListPreference) preference).findIndexOfValue(stringValue);
preference.setSummary(preference.getContext().getString(R.string
.pref_autolock, ((ListPreference) preference).getEntries()
[index]));
return true;
case "pref_key_allsms":
preference.setSummary((boolean) value ? R.string.pref_allsms_enable : R
.string.pref_allsms_disable);
Expand Down Expand Up @@ -126,7 +112,7 @@ else if (preference instanceof ListPreference)

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
setPreferencesFromResource(R.xml.pref_general, rootKey);
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
// to their values. When their values change, their summaries are
Expand All @@ -137,102 +123,8 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
bindPreferenceSummaryToValue(findPreference(getString(R.string
.pref_key_notification_only_otp)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key_vibrate)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key_autolock)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key_allsms)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_key_pin)));
Preference pinPreference = findPreference(getString(R.string.pref_key_pin));
pinPreference.setOnPreferenceChangeListener(this);
((SwitchPreference) pinPreference).setChecked(sharedPreferences.getBoolean(getString
(R.string.pref_key_pin),
false));
Log.d(TAG, "setting all set");
}

@Override
public void onStart() {
super.onStart();
PreferenceManager.getDefaultSharedPreferences(getActivity())
.registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause() {
super.onPause();
PreferenceManager.getDefaultSharedPreferences(getActivity())
.unregisterOnSharedPreferenceChangeListener(this);
findPreference(getString(R.string.pref_key_pin)).setOnPreferenceClickListener(null);
Log.d(TAG, "listener removed");
}

@Override
public boolean onPreferenceChange(Preference preference, Object o) {
Log.d(TAG, "preferenceClick " + preference.getKey());
if (preference.getKey().equals(getString(R.string.pref_key_pin))) {
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
PreferenceManager
.getDefaultSharedPreferences(preference.getContext())
.getBoolean(preference.getKey(), false));
if (!((SwitchPreference) preference).isChecked()) {
Log.d(TAG, "set new PIN");
startActivityForResult(new Intent(PinActivity.ACTIONS.SET_PIN, null,
getActivity(), PinActivity.class), REQUEST_CODE_SET_PIN);
} else {
Log.d(TAG, "check PIN then disable");
startActivityForResult(new Intent(PinActivity.ACTIONS.CHECK_PIN, null,
getActivity(), PinActivity.class), REQUEST_CODE_CHECK_PIN);
}
return true;
}
return false;
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (isAdded() && key.equals(getString(R.string.pref_key_pin)))
((SwitchPreference) findPreference(getString(R.string.pref_key_pin))).setChecked
(sharedPreferences
.getBoolean(key, false));
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult req:" + requestCode + " res:" + resultCode);
//response for pin set
if (requestCode == REQUEST_CODE_SET_PIN) {
if (resultCode == RESULT_OK) {
Log.d(TAG, "set pin success");
sharedPreferences.edit().putBoolean
(getString(R.string.pref_key_pin), true).apply();
} else {
//cancelled
Log.d(TAG, "set pin failed");
sharedPreferences.edit().putBoolean
(getString(R.string.pref_key_pin), false).remove(getString(R.string
.pref_key_pin_value)).apply();
((SwitchPreference) findPreference(getString(R.string.pref_key_pin)))
.setChecked(false);
}
}
//response for PIN check
if (requestCode == REQUEST_CODE_CHECK_PIN) {

if (resultCode == RESULT_OK) {
//pin checked now disable the pin
Log.d(TAG, "check pin success");
sharedPreferences.edit().putBoolean
(getString(R.string.pref_key_pin), false).putString(getString(R.string
.pref_key_pin_value), null)
.remove(getString(R.string.pref_key_pin_value)).apply();
} else {
//pin verification failed keep the pin on
Log.d(TAG, "check pin failed");
sharedPreferences.edit().putBoolean
(getString(R.string.pref_key_pin), true).apply();
((SwitchPreference) findPreference(getString(R.string.pref_key_pin)))
.setChecked(true);
}
}
super.onActivityResult(requestCode, resultCode, data);
}

}
Loading

0 comments on commit c988c22

Please sign in to comment.