Android improvements.
[UPDATED] Opal API [ADDED] Scrypt native binaries for more archs. [IMPROVED] Android activity secure. [FIXED] White background on buttons for some devices. [IMPROVED] Android layout. [WIP] Remember password on Android.
This commit is contained in:
parent
ca5d83d40c
commit
a6e7a749bf
@ -24,12 +24,12 @@
|
||||
<dependency>
|
||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||
<artifactId>opal-system</artifactId>
|
||||
<version>1.6-p6</version>
|
||||
<version>1.6-p7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lyndir.lhunath.opal</groupId>
|
||||
<artifactId>opal-crypto</artifactId>
|
||||
<version>1.6-p6</version>
|
||||
<version>1.6-p7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- EXTERNAL DEPENDENCIES -->
|
||||
|
@ -77,15 +77,6 @@ public class MasterKey {
|
||||
return idForBytes( masterKey );
|
||||
}
|
||||
|
||||
private byte[] getSubKey(final int subkeyLength) {
|
||||
|
||||
Preconditions.checkState( valid );
|
||||
byte[] subkey = new byte[Math.min( subkeyLength, masterKey.length )];
|
||||
System.arraycopy( masterKey, 0, subkey, 0, subkey.length );
|
||||
|
||||
return subkey;
|
||||
}
|
||||
|
||||
public String encode(final String siteName, final MPSiteType siteType, int siteCounter, final MPSiteVariant siteVariant,
|
||||
@Nullable final String siteContext) {
|
||||
Preconditions.checkState( valid );
|
||||
|
@ -114,11 +114,10 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>com.lambdaworks</groupId>
|
||||
<artifactId>libscrypt</artifactId>
|
||||
<version>1.4.0</version>
|
||||
<type>so</type>
|
||||
<classifier>android</classifier>
|
||||
<scope>runtime</scope>
|
||||
<artifactId>scrypt</artifactId>
|
||||
<version>1.4.0-android</version>
|
||||
<type>jar</type>
|
||||
<classifier>native</classifier>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
@ -12,64 +12,61 @@
|
||||
android:gravity="center">
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="20dp"
|
||||
android:indeterminate="true" />
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/userNameField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text|textCapWords|textPersonName"
|
||||
android:hint="@string/userName.hint"
|
||||
android:hint="@string/userName_hint"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="26sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/masterPasswordField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text|textPassword"
|
||||
android:hint="@string/masterPassword.hint"
|
||||
android:password="true"
|
||||
android:hint="@string/masterPassword_hint"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/double_"
|
||||
android:contentDescription="@string/empty" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/siteNameField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text|textNoSuggestions|textUri"
|
||||
android:hint="@string/siteName.hint"
|
||||
android:hint="@string/siteName_hint"
|
||||
android:gravity="center"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="26sp" />
|
||||
|
||||
<Button
|
||||
<ImageView
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:src="@drawable/double_"
|
||||
android:contentDescription="@string/empty" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sitePasswordField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:background="@null"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="32sp"
|
||||
android:text="LuxdZozvDuma4["
|
||||
@ -77,13 +74,30 @@
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/typeField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center" />
|
||||
|
||||
<NumberPicker
|
||||
<EditText
|
||||
android:id="@+id/counterField"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:inputType="text|textNoSuggestions"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="26sp"
|
||||
android:text="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/rememberPasswordField"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/remember" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
<resources>
|
||||
<string name="app_name">Master Password</string>
|
||||
<string name="avatar">User Avatar</string>
|
||||
<string name="siteName.hint">Site Name</string>
|
||||
<string name="userName.hint">Your Name</string>
|
||||
<string name="masterPassword.hint">Your Master Password</string>
|
||||
<string name="remember">Remember Password</string>
|
||||
<string name="siteName_hint">Site Name</string>
|
||||
<string name="userName_hint">Your Name</string>
|
||||
<string name="masterPassword_hint">Your Master Password</string>
|
||||
<string name="empty" />
|
||||
</resources>
|
||||
|
@ -9,12 +9,14 @@ import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.*;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.InjectView;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.util.concurrent.*;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.lhunath.opal.system.util.ConversionUtils;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
|
||||
@ -55,11 +57,14 @@ public class EmergencyActivity extends Activity {
|
||||
Spinner typeField;
|
||||
|
||||
@InjectView(R.id.counterField)
|
||||
NumberPicker counterField;
|
||||
EditText counterField;
|
||||
|
||||
@InjectView(R.id.sitePasswordField)
|
||||
TextView sitePasswordField;
|
||||
|
||||
@InjectView(R.id.rememberPasswordField)
|
||||
CheckBox rememberPasswordField;
|
||||
|
||||
private int hc_userName;
|
||||
private int hc_masterPassword;
|
||||
|
||||
@ -68,6 +73,7 @@ public class EmergencyActivity extends Activity {
|
||||
super.onCreate( savedInstanceState );
|
||||
Res.init( getResources() );
|
||||
|
||||
getWindow().setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE );
|
||||
setContentView( R.layout.activity_emergency );
|
||||
ButterKnife.inject( this );
|
||||
|
||||
@ -75,23 +81,26 @@ public class EmergencyActivity extends Activity {
|
||||
masterPasswordField.setOnFocusChangeListener( updateMasterKey );
|
||||
siteNameField.addTextChangedListener( updateSitePassword );
|
||||
typeField.setOnItemSelectedListener( updateSitePassword );
|
||||
counterField.setOnValueChangedListener( updateSitePassword );
|
||||
counterField.addTextChangedListener( updateSitePassword );
|
||||
|
||||
userNameField.setTypeface( Res.exo_Thin );
|
||||
userNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
masterPasswordField.setTypeface( Res.sourceCodePro_ExtraLight );
|
||||
masterPasswordField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
masterPasswordField.setPaintFlags( masterPasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
siteNameField.setTypeface( Res.exo_Regular );
|
||||
siteNameField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
siteNameField.setPaintFlags( siteNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
sitePasswordField.setTypeface( Res.sourceCodePro_Black );
|
||||
sitePasswordField.setPaintFlags( userNameField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
sitePasswordField.setPaintFlags( sitePasswordField.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG );
|
||||
|
||||
typeField.setAdapter( new ArrayAdapter<>( this, R.layout.type_item, MPSiteType.forClass( MPSiteTypeClass.Generated ) ) );
|
||||
typeField.setSelection( MPSiteType.GeneratedLong.ordinal() );
|
||||
|
||||
counterField.setMinValue( 1 );
|
||||
counterField.setMaxValue( Integer.MAX_VALUE );
|
||||
counterField.setWrapSelectorWheel( false );
|
||||
rememberPasswordField.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(final CompoundButton buttonView, final boolean isChecked) {
|
||||
getPreferences( MODE_PRIVATE ).edit().putBoolean( "rememberPassword", isChecked ).apply();
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -99,25 +108,32 @@ public class EmergencyActivity extends Activity {
|
||||
super.onResume();
|
||||
|
||||
userNameField.setText( getPreferences( MODE_PRIVATE ).getString( "userName", "" ) );
|
||||
rememberPasswordField.setSelected( isRememberPasswordEnabled() );
|
||||
masterPasswordField.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
synchronized (this) {
|
||||
hc_userName = hc_masterPassword = 0;
|
||||
if (masterKeyFuture != null) {
|
||||
masterKeyFuture.cancel( true );
|
||||
masterKeyFuture = null;
|
||||
if (!isRememberPasswordEnabled()) {
|
||||
synchronized (this) {
|
||||
hc_userName = hc_masterPassword = 0;
|
||||
if (masterKeyFuture != null) {
|
||||
masterKeyFuture.cancel( true );
|
||||
masterKeyFuture = null;
|
||||
}
|
||||
|
||||
sitePasswordField.setText( "" );
|
||||
progressView.setVisibility( View.INVISIBLE );
|
||||
}
|
||||
}
|
||||
|
||||
sitePasswordField.setText( "" );
|
||||
progressView.setVisibility( View.INVISIBLE );
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private boolean isRememberPasswordEnabled() {
|
||||
return getPreferences( MODE_PRIVATE ).getBoolean( "rememberPassword", false );
|
||||
}
|
||||
|
||||
private synchronized void updateMasterKey() {
|
||||
final String userName = userNameField.getText().toString();
|
||||
final String masterPassword = masterPasswordField.getText().toString();
|
||||
@ -126,9 +142,7 @@ public class EmergencyActivity extends Activity {
|
||||
hc_userName = userName.hashCode();
|
||||
hc_masterPassword = masterPassword.hashCode();
|
||||
|
||||
SharedPreferences.Editor pref = getPreferences( MODE_PRIVATE ).edit();
|
||||
pref.putString( "userName", userName );
|
||||
pref.apply();
|
||||
getPreferences( MODE_PRIVATE ).edit().putString( "userName", userName ).apply();
|
||||
|
||||
if (masterKeyFuture != null)
|
||||
masterKeyFuture.cancel( true );
|
||||
@ -170,7 +184,7 @@ public class EmergencyActivity extends Activity {
|
||||
private void updateSitePassword() {
|
||||
final String siteName = siteNameField.getText().toString();
|
||||
final MPSiteType type = (MPSiteType) typeField.getSelectedItem();
|
||||
final int counter = counterField.getValue();
|
||||
final int counter = ConversionUtils.toIntegerNN( counterField.getText() );
|
||||
|
||||
if (masterKeyFuture == null || siteName.isEmpty() || type == null) {
|
||||
sitePasswordField.setText( "" );
|
||||
@ -220,13 +234,13 @@ public class EmergencyActivity extends Activity {
|
||||
|
||||
ClipDescription description = new ClipDescription( strf( "Password for %s", siteNameField.getText() ),
|
||||
new String[]{ ClipDescription.MIMETYPE_TEXT_PLAIN } );
|
||||
((ClipboardManager) getSystemService( CLIPBOARD_SERVICE )).setPrimaryClip(
|
||||
new ClipData( description, new ClipData.Item( sitePassword ) ) );
|
||||
ClipData clipData = new ClipData( description, new ClipData.Item( sitePassword ) );
|
||||
((ClipboardManager) getSystemService( CLIPBOARD_SERVICE )).setPrimaryClip( clipData );
|
||||
|
||||
Intent startMain = new Intent(Intent.ACTION_MAIN);
|
||||
startMain.addCategory(Intent.CATEGORY_HOME);
|
||||
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(startMain);
|
||||
Intent startMain = new Intent( Intent.ACTION_MAIN );
|
||||
startMain.addCategory( Intent.CATEGORY_HOME );
|
||||
startMain.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
|
||||
startActivity( startMain );
|
||||
}
|
||||
|
||||
private abstract class ValueChangedListener
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>com.lyndir.lhunath</groupId>
|
||||
<artifactId>lyndir</artifactId>
|
||||
<version>1.18</version>
|
||||
<version>1.20</version>
|
||||
</parent>
|
||||
|
||||
<name>Master Password</name>
|
||||
|
Loading…
Reference in New Issue
Block a user