First part of the authentication slide (WIP)
This commit is contained in:
parent
324f84b36c
commit
14a7e2c174
3 changed files with 181 additions and 32 deletions
|
@ -2,13 +2,12 @@ package org.shadowice.flocke.andotp.Activities;
|
|||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
@ -25,6 +24,7 @@ public class MainIntroActivity extends IntroActivity {
|
|||
private Settings settings;
|
||||
|
||||
private EncryptionFragment encryptionFragment;
|
||||
private AuthenticationFragment authenticationFragment;
|
||||
|
||||
@Override protected void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -32,6 +32,15 @@ public class MainIntroActivity extends IntroActivity {
|
|||
settings = new Settings(this);
|
||||
|
||||
encryptionFragment = new EncryptionFragment();
|
||||
authenticationFragment = new AuthenticationFragment();
|
||||
|
||||
encryptionFragment.setEncryptionChangedCallback(new EncryptionFragment.EncryptionChangedCallback() {
|
||||
@Override
|
||||
public void onEncryptionChanged(Constants.EncryptionType newEncryptionType) {
|
||||
authenticationFragment.updateEncryptionType(newEncryptionType);
|
||||
settings.setEncryption(newEncryptionType);
|
||||
}
|
||||
});
|
||||
|
||||
setButtonBackFunction(BUTTON_BACK_FUNCTION_BACK);
|
||||
|
||||
|
@ -53,36 +62,12 @@ public class MainIntroActivity extends IntroActivity {
|
|||
.build()
|
||||
);
|
||||
|
||||
// TODO: Set authentication
|
||||
addSlide(new SimpleSlide.Builder()
|
||||
.title(R.string.intro_slide1_title)
|
||||
.description(R.string.intro_slide1_desc)
|
||||
.image(R.mipmap.ic_launcher)
|
||||
addSlide(new FragmentSlide.Builder()
|
||||
.background(R.color.colorPrimary)
|
||||
.backgroundDark(R.color.colorPrimaryDark)
|
||||
.scrollable(false)
|
||||
.fragment(authenticationFragment)
|
||||
.build()
|
||||
);
|
||||
|
||||
addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (position == 2) {
|
||||
// TODO: Inter-page communication
|
||||
settings.setEncryption(encryptionFragment.getSelectedEncryption());
|
||||
Log.d("INTRO", "Encryption saved");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,6 +77,8 @@ public class MainIntroActivity extends IntroActivity {
|
|||
}
|
||||
|
||||
public static class EncryptionFragment extends SlideFragment {
|
||||
private EncryptionChangedCallback encryptionChangedCallback = null;
|
||||
|
||||
private Spinner selection;
|
||||
private TextView desc;
|
||||
|
||||
|
@ -100,6 +87,10 @@ public class MainIntroActivity extends IntroActivity {
|
|||
public EncryptionFragment() {
|
||||
}
|
||||
|
||||
public void setEncryptionChangedCallback(EncryptionChangedCallback cb) {
|
||||
encryptionChangedCallback = cb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
@ -108,7 +99,7 @@ public class MainIntroActivity extends IntroActivity {
|
|||
selection = root.findViewById(R.id.introEncryptionSelection);
|
||||
desc = root.findViewById(R.id.introEncryptionDesc);
|
||||
|
||||
final String[] encValues = getResources().getStringArray(R.array.settings_values_encryption);
|
||||
String[] encValues = getResources().getStringArray(R.array.settings_values_encryption);
|
||||
|
||||
selectionMapping = new SparseArray<>();
|
||||
for (int i = 0; i < encValues.length; i++)
|
||||
|
@ -123,6 +114,9 @@ public class MainIntroActivity extends IntroActivity {
|
|||
desc.setText(R.string.intro_slide2_desc_password);
|
||||
else if (encryptionType == Constants.EncryptionType.KEYSTORE)
|
||||
desc.setText(R.string.intro_slide2_desc_keystore);
|
||||
|
||||
if (encryptionChangedCallback != null)
|
||||
encryptionChangedCallback.onEncryptionChanged(encryptionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -133,8 +127,78 @@ public class MainIntroActivity extends IntroActivity {
|
|||
return root;
|
||||
}
|
||||
|
||||
private Constants.EncryptionType getSelectedEncryption() {
|
||||
return selectionMapping.get(selection.getSelectedItemPosition());
|
||||
public interface EncryptionChangedCallback {
|
||||
void onEncryptionChanged(Constants.EncryptionType newEncryptionType);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AuthenticationFragment extends SlideFragment {
|
||||
private Constants.EncryptionType encryptionType = Constants.EncryptionType.KEYSTORE;
|
||||
|
||||
private TextView desc = null;
|
||||
private Spinner selection = null;
|
||||
|
||||
private SparseArray<Constants.AuthMethod> selectionMapping;
|
||||
|
||||
public AuthenticationFragment() {
|
||||
}
|
||||
|
||||
public void updateEncryptionType(Constants.EncryptionType encryptionType) {
|
||||
this.encryptionType = encryptionType;
|
||||
|
||||
if (desc != null) {
|
||||
if (encryptionType == Constants.EncryptionType.KEYSTORE) {
|
||||
desc.setText(R.string.intro_slide3_desc_keystore);
|
||||
} else if (encryptionType == Constants.EncryptionType.PASSWORD) {
|
||||
desc.setText(R.string.intro_slide3_desc_password);
|
||||
|
||||
Constants.AuthMethod selectedMethod = selectionMapping.get(selection.getSelectedItemPosition());
|
||||
if (selectedMethod != Constants.AuthMethod.PASSWORD && selectedMethod != Constants.AuthMethod.PIN )
|
||||
selection.setSelection(selectionMapping.indexOfValue(Constants.AuthMethod.PASSWORD));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.component_intro_authentication, container, false);
|
||||
|
||||
desc = root.findViewById(R.id.introAuthDesc);
|
||||
selection = root.findViewById(R.id.introAuthSelection);
|
||||
|
||||
Constants.AuthMethod[] authValues = Constants.AuthMethod.values();
|
||||
String[] authEntries = getResources().getStringArray(R.array.settings_entries_auth);
|
||||
|
||||
selectionMapping = new SparseArray<>();
|
||||
for (int i = 0; i < authValues.length; i++)
|
||||
selectionMapping.put(i, authValues[i]);
|
||||
|
||||
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(getIntroActivity(), android.R.layout.simple_spinner_item, authEntries) {
|
||||
@Override
|
||||
public boolean isEnabled(int position){
|
||||
return encryptionType != Constants.EncryptionType.PASSWORD ||
|
||||
position == selectionMapping.indexOfValue(Constants.AuthMethod.PASSWORD) ||
|
||||
position == selectionMapping.indexOfValue(Constants.AuthMethod.PIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View view = super.getDropDownView(position, convertView, parent);
|
||||
TextView tv = (TextView) view;
|
||||
|
||||
tv.setEnabled(encryptionType != Constants.EncryptionType.PASSWORD ||
|
||||
position == selectionMapping.indexOfValue(Constants.AuthMethod.PASSWORD) ||
|
||||
position == selectionMapping.indexOfValue(Constants.AuthMethod.PIN));
|
||||
|
||||
return view;
|
||||
}
|
||||
};
|
||||
|
||||
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
selection.setAdapter(spinnerArrayAdapter);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
79
app/src/main/res/layout/component_intro_authentication.xml
Normal file
79
app/src/main/res/layout/component_intro_authentication.xml
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/activity_margin_large">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/settings_title_auth" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/introAuthDesc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:text="@string/intro_slide3_desc_keystore"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/introAuthSelection"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/activity_margin_large"
|
||||
android:layout_marginStart="@dimen/activity_margin"
|
||||
android:layout_marginEnd="@dimen/activity_margin"
|
||||
android:entries="@array/settings_entries_auth" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/introCredentialsLayout"
|
||||
android:visibility="invisible"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/activity_margin_large"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/introPasswordLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/settings_hint_password"
|
||||
app:passwordToggleEnabled="true" >
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/introPasswordEdit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/introPasswordConfirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/settings_hint_password_confirm"
|
||||
android:inputType="textPassword" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/introPasswordToShortWarning"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:visibility="gone"
|
||||
android:textAlignment="center"
|
||||
android:text="@string/settings_label_short_password" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -4,7 +4,7 @@
|
|||
<string name="intro_slide1_desc">This wizard will guide you through the initial setup.</string>
|
||||
|
||||
<string name="intro_slide2_desc">To ensure the security of your accounts andOTP only stores them
|
||||
in encrypted data files. Here you can choose which method of encryption will be used:</string>
|
||||
in encrypted data files. Here you can choose which method of encryption will be used.</string>
|
||||
<string name="intro_slide2_desc_keystore">The KeyStore is a system component of Android for
|
||||
securely storing cryptographic keys. The advantage of this method is that the keys are
|
||||
stored separated from the data files and can be backed by hardware cryptography (if your
|
||||
|
@ -18,4 +18,10 @@
|
|||
generated from a password or PIN. The main advantage here is that this will work with
|
||||
external backup solutions (like Titanium). However, you will have to enter your credentials
|
||||
every time you start andOTP.</string>
|
||||
|
||||
<string name="intro_slide3_desc_keystore">Here you can setup an authentication to lock andOTP.
|
||||
Since you have chosen <b>Android KeyStore</b> as encryption method this is optional.</string>
|
||||
<string name="intro_slide3_desc_password">Here you can setup an authentication to lock andOTP.
|
||||
Since you have chosen <b>Password / PIN</b> as encryption method you need to set either a
|
||||
password or a PIN to proceed.</string>
|
||||
</resources>
|
Loading…
Reference in a new issue