Merge branch '176-setupactivity-warnings-api10' into 'master'

Fix SetupActivity warnings for API 10

Closes #176.

The manual setting of the error message color also (strangely) stops the message from disappearing every second character. I'm not complaining ^_^

I guessed that the text color problem probably stopped occurring from API 14 (at the big 4.0 overhaul), but it would be great if someone could confirm.

See merge request !40
This commit is contained in:
akwizgran
2015-12-31 12:03:44 +00:00
7 changed files with 175 additions and 126 deletions

View File

@@ -6,8 +6,9 @@ dependencies {
compile fileTree(dir: '../briar-core/libs', include: '*.jar') compile fileTree(dir: '../briar-core/libs', include: '*.jar')
compile project(':briar-core') compile project(':briar-core')
compile fileTree(dir: 'libs', include: '*.jar') compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.android.support:design:23.1.1' compile "com.android.support:support-v4:23.1.1"
compile 'com.android.support:recyclerview-v7:23.1.1' compile "com.android.support:appcompat-v7:23.1.1"
compile "com.android.support:design:23.1.1"
} }
android { android {

View File

@@ -27,7 +27,6 @@
android:hint="@string/password_hint" android:hint="@string/password_hint"
android:imeOptions="actionDone" android:imeOptions="actionDone"
android:inputType="textPassword" android:inputType="textPassword"
android:lines="1"
android:maxLines="1" /> android:maxLines="1" />
<Button <Button

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/margin_activity_vertical"
android:paddingEnd="@dimen/margin_activity_horizontal"
android:paddingLeft="@dimen/margin_activity_horizontal"
android:paddingRight="@dimen/margin_activity_horizontal"
android:paddingStart="@dimen/margin_activity_horizontal"
android:paddingTop="@dimen/margin_activity_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/choose_nickname"
android:textSize="@dimen/text_size_medium"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/nickname_entry_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<EditText
android:id="@+id/nickname_entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text|textCapWords"
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/choose_password"
android:textSize="@dimen/text_size_medium"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/password_entry_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<EditText
android:id="@+id/password_entry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/confirm_password"
android:textSize="@dimen/text_size_medium"/>
<android.support.design.widget.TextInputLayout
android:id="@+id/password_confirm_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<EditText
android:id="@+id/password_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:imeOptions="actionDone"
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
<org.briarproject.android.util.StrengthMeter
android:id="@+id/strength_meter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"/>
<Button
android:id="@+id/create_account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="false"
android:text="@string/create_account_button"/>
<ProgressBar
android:id="@+id/progress_wheel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="gone"/>
</LinearLayout>
</ScrollView>

View File

@@ -29,7 +29,6 @@ import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_HOME; import static android.content.Intent.CATEGORY_HOME;
import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
public class PasswordActivity extends BaseActivity { public class PasswordActivity extends BaseActivity {
@@ -63,11 +62,11 @@ public class PasswordActivity extends BaseActivity {
password = (EditText) findViewById(R.id.edit_password); password = (EditText) findViewById(R.id.edit_password);
password.setOnEditorActionListener(new OnEditorActionListener() { password.setOnEditorActionListener(new OnEditorActionListener() {
@Override @Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { public boolean onEditorAction(TextView v, int actionId,
if (actionId == IME_ACTION_DONE) { KeyEvent event) {
validatePassword(encrypted, password.getText()); hideSoftKeyboard();
} validatePassword(encrypted, password.getText());
return false; return true;
} }
}); });
} }

View File

@@ -4,20 +4,20 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener; import android.widget.TextView.OnEditorActionListener;
import org.briarproject.R; import org.briarproject.R;
import org.briarproject.android.util.LayoutUtils; import org.briarproject.android.util.AndroidUtils;
import org.briarproject.android.util.StrengthMeter; import org.briarproject.android.util.StrengthMeter;
import org.briarproject.api.android.ReferenceManager; import org.briarproject.api.android.ReferenceManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
@@ -35,38 +35,35 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import roboguice.inject.InjectView;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.text.InputType.TYPE_CLASS_TEXT;
import static android.text.InputType.TYPE_TEXT_FLAG_CAP_WORDS;
import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
import static android.view.Gravity.CENTER;
import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.INVISIBLE; import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
import static android.widget.LinearLayout.VERTICAL;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS; import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP;
import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK; import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
public class SetupActivity extends BaseActivity implements OnClickListener, public class SetupActivity extends BaseActivity implements OnClickListener,
OnEditorActionListener { OnEditorActionListener {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(SetupActivity.class.getName()); Logger.getLogger(SetupActivity.class.getName());
@Inject @CryptoExecutor private Executor cryptoExecutor; @Inject @CryptoExecutor private Executor cryptoExecutor;
@Inject private PasswordStrengthEstimator strengthEstimator; @Inject private PasswordStrengthEstimator strengthEstimator;
private EditText nicknameEntry = null; @InjectView(R.id.nickname_entry_wrapper) TextInputLayout nicknameEntryWrapper;
private EditText passwordEntry = null, passwordConfirmation = null; @InjectView(R.id.password_entry_wrapper) TextInputLayout passwordEntryWrapper;
private StrengthMeter strengthMeter = null; @InjectView(R.id.password_confirm_wrapper) TextInputLayout passwordConfirmationWrapper;
private Button createAccountButton = null; @InjectView(R.id.nickname_entry) EditText nicknameEntry;
private ProgressBar progress = null; @InjectView(R.id.password_entry) EditText passwordEntry;
@InjectView(R.id.password_confirm) EditText passwordConfirmation;
@InjectView(R.id.strength_meter) StrengthMeter strengthMeter;
@InjectView(R.id.create_account) Button createAccountButton;
@InjectView(R.id.progress_wheel) ProgressBar progress;
// Fields that are accessed from background threads must be volatile // Fields that are accessed from background threads must be volatile
@Inject private volatile CryptoComponent crypto; @Inject private volatile CryptoComponent crypto;
@@ -77,99 +74,32 @@ OnEditorActionListener {
@Override @Override
public void onCreate(Bundle state) { public void onCreate(Bundle state) {
super.onCreate(state); super.onCreate(state);
setContentView(R.layout.activity_setup);
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE); if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
LinearLayout layout = new LinearLayout(this); TextWatcher tw = new TextWatcher() {
layout.setLayoutParams(MATCH_MATCH);
layout.setOrientation(VERTICAL);
layout.setGravity(CENTER_HORIZONTAL);
int pad = LayoutUtils.getPadding(this);
layout.setPadding(pad, pad, pad, pad);
TextView chooseNickname = new TextView(this);
chooseNickname.setGravity(CENTER);
chooseNickname.setTextSize(18);
chooseNickname.setText(R.string.choose_nickname);
layout.addView(chooseNickname);
nicknameEntry = new EditText(this) {
@Override @Override
protected void onTextChanged(CharSequence text, int start, public void beforeTextChanged(CharSequence s, int start, int count,
int lengthBefore, int lengthAfter) { int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
enableOrDisableContinueButton(); enableOrDisableContinueButton();
} }
};
nicknameEntry.setId(1);
nicknameEntry.setMaxLines(1);
int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_WORDS;
nicknameEntry.setInputType(inputType);
layout.addView(nicknameEntry);
TextView choosePassword = new TextView(this);
choosePassword.setGravity(CENTER);
choosePassword.setTextSize(18);
choosePassword.setPadding(0, pad, 0, 0);
choosePassword.setText(R.string.choose_password);
layout.addView(choosePassword);
passwordEntry = new EditText(this) {
@Override @Override
protected void onTextChanged(CharSequence text, int start, public void afterTextChanged(Editable s) {
int lengthBefore, int lengthAfter) {
enableOrDisableContinueButton();
} }
}; };
passwordEntry.setId(2);
passwordEntry.setMaxLines(1);
inputType = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD;
passwordEntry.setInputType(inputType);
layout.addView(passwordEntry);
TextView confirmPassword = new TextView(this); nicknameEntry.addTextChangedListener(tw);
confirmPassword.setGravity(CENTER); passwordEntry.addTextChangedListener(tw);
confirmPassword.setTextSize(18); passwordConfirmation.addTextChangedListener(tw);
confirmPassword.setPadding(0, pad, 0, 0);
confirmPassword.setText(R.string.confirm_password);
layout.addView(confirmPassword);
passwordConfirmation = new EditText(this) {
@Override
protected void onTextChanged(CharSequence text, int start,
int lengthBefore, int lengthAfter) {
enableOrDisableContinueButton();
}
};
passwordConfirmation.setId(3);
passwordConfirmation.setMaxLines(1);
inputType = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD;
passwordConfirmation.setInputType(inputType);
passwordConfirmation.setOnEditorActionListener(this); passwordConfirmation.setOnEditorActionListener(this);
layout.addView(passwordConfirmation);
strengthMeter = new StrengthMeter(this);
strengthMeter.setPadding(pad, pad, pad, pad);
strengthMeter.setVisibility(INVISIBLE);
layout.addView(strengthMeter);
createAccountButton = new Button(this);
createAccountButton.setLayoutParams(WRAP_WRAP);
createAccountButton.setText(R.string.create_account_button);
createAccountButton.setEnabled(false);
createAccountButton.setOnClickListener(this); createAccountButton.setOnClickListener(this);
layout.addView(createAccountButton);
progress = new ProgressBar(this);
progress.setLayoutParams(WRAP_WRAP);
progress.setPadding(0, pad, 0, 0);
progress.setIndeterminate(true);
progress.setVisibility(GONE);
layout.addView(progress);
ScrollView scroll = new ScrollView(this);
scroll.addView(layout);
setContentView(scroll);
} }
private void enableOrDisableContinueButton() { private void enableOrDisableContinueButton() {
@@ -184,21 +114,22 @@ OnEditorActionListener {
boolean passwordsMatch = firstPassword.equals(secondPassword); boolean passwordsMatch = firstPassword.equals(secondPassword);
float strength = strengthEstimator.estimateStrength(firstPassword); float strength = strengthEstimator.estimateStrength(firstPassword);
strengthMeter.setStrength(strength); strengthMeter.setStrength(strength);
if (nicknameLength > MAX_AUTHOR_NAME_LENGTH) AndroidUtils.setError(nicknameEntryWrapper,
nicknameEntry.setError(getString(R.string.name_too_long)); getString(R.string.name_too_long),
if (firstPassword.length() > 0 && strength < WEAK) nicknameLength > MAX_AUTHOR_NAME_LENGTH);
passwordEntry.setError(getString(R.string.password_too_weak)); AndroidUtils.setError(passwordEntryWrapper,
if (secondPassword.length() > 0 && !passwordsMatch) getString(R.string.password_too_weak),
passwordConfirmation.setError(getString(R.string.passwords_do_not_match)); firstPassword.length() > 0 && strength < WEAK);
AndroidUtils.setError(passwordConfirmationWrapper,
getString(R.string.passwords_do_not_match),
secondPassword.length() > 0 && !passwordsMatch);
createAccountButton.setEnabled(nicknameLength > 0 createAccountButton.setEnabled(nicknameLength > 0
&& nicknameLength <= MAX_AUTHOR_NAME_LENGTH && nicknameLength <= MAX_AUTHOR_NAME_LENGTH
&& passwordsMatch && strength >= WEAK); && passwordsMatch && strength >= WEAK);
} }
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// Hide the soft keyboard hideSoftKeyboard();
Object o = getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
return true; return true;
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject.android.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Build; import android.os.Build;
import android.support.design.widget.TextInputLayout;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -23,4 +24,12 @@ public class AndroidUtils {
} }
return Collections.unmodifiableList(abis); return Collections.unmodifiableList(abis);
} }
public static void setError(TextInputLayout til, String error, boolean condition) {
if (condition) {
if (til.getError() == null)
til.setError(error);
} else
til.setError(null);
}
} }

View File

@@ -1,5 +1,15 @@
package org.briarproject.android.util; package org.briarproject.android.util;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.util.AttributeSet;
import android.widget.ProgressBar;
import static android.graphics.Color.BLACK; import static android.graphics.Color.BLACK;
import static android.graphics.Paint.Style.FILL; import static android.graphics.Paint.Style.FILL;
import static android.graphics.Paint.Style.STROKE; import static android.graphics.Paint.Style.STROKE;
@@ -9,14 +19,6 @@ import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_STRONG
import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_WEAK; import static org.briarproject.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
import static org.briarproject.api.crypto.PasswordStrengthEstimator.STRONG; import static org.briarproject.api.crypto.PasswordStrengthEstimator.STRONG;
import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK; import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.widget.ProgressBar;
public class StrengthMeter extends ProgressBar { public class StrengthMeter extends ProgressBar {
@@ -30,7 +32,11 @@ public class StrengthMeter extends ProgressBar {
private final ShapeDrawable bar; private final ShapeDrawable bar;
public StrengthMeter(Context context) { public StrengthMeter(Context context) {
super(context, null, android.R.attr.progressBarStyleHorizontal); this(context, null);
}
public StrengthMeter(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.progressBarStyleHorizontal);
bar = new ShapeDrawable(); bar = new ShapeDrawable();
bar.getPaint().setColor(RED); bar.getPaint().setColor(RED);
ClipDrawable clip = new ClipDrawable(bar, LEFT, HORIZONTAL); ClipDrawable clip = new ClipDrawable(bar, LEFT, HORIZONTAL);