Migrate from password manager (#39)

* Update gradle
Change .gitignore & clean project

* Change password manager

* Change password manager

* Change password manager

* Cleaned up imports.
Fixed the backup screen.

* Update security
pull/2/head
Maksim 7 years ago committed by Marat Subkhankulov
parent 07264d542b
commit 44850ed5ce
  1. 33
      app/src/main/java/com/wallet/crypto/trustapp/controller/Controller.java
  2. 1
      app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStore.java
  3. 23
      app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStoreUtils.java
  4. 2
      app/src/main/java/com/wallet/crypto/trustapp/controller/EthplorerService.java
  5. 1
      app/src/main/java/com/wallet/crypto/trustapp/controller/ServiceErrorException.java
  6. 4
      app/src/main/java/com/wallet/crypto/trustapp/util/KS.java
  7. 4
      app/src/main/java/com/wallet/crypto/trustapp/views/AccountListActivity.java
  8. 5
      app/src/main/java/com/wallet/crypto/trustapp/views/CreateAccountActivity.java
  9. 189
      app/src/main/java/com/wallet/crypto/trustapp/views/ExportAccountActivity.java
  10. 9
      app/src/main/java/com/wallet/crypto/trustapp/views/ImportAccountActivity.java
  11. 4
      app/src/main/java/com/wallet/crypto/trustapp/views/IntroActivity.java
  12. 13
      app/src/main/java/com/wallet/crypto/trustapp/views/RequestActivity.java
  13. 2
      app/src/main/java/com/wallet/crypto/trustapp/views/SettingsActivity.java
  14. 5
      app/src/main/java/com/wallet/crypto/trustapp/views/SettingsFragment.java
  15. 2
      app/src/main/java/com/wallet/crypto/trustapp/views/SplashActivity.java
  16. 2
      app/src/main/java/com/wallet/crypto/trustapp/views/TokenListActivity.java
  17. 4
      app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailActivity.java
  18. 3
      app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailFragment.java
  19. 12
      app/src/main/java/com/wallet/crypto/trustapp/views/TransactionListActivity.java
  20. 6
      app/src/main/java/com/wallet/crypto/trustapp/views/WarningBackupActivity.java
  21. 6
      app/src/main/java/com/wallet/crypto/trustapp/views/barcode/BarcodeCaptureActivity.java
  22. 151
      app/src/main/java/com/wallet/crypto/trustapp/widget/HelperTextInputLayout.java
  23. 2
      app/src/main/res/drawable/splash_background.xml
  24. 81
      app/src/main/res/layout/activity_export_account.xml
  25. 63
      app/src/main/res/layout/content_export_account.xml
  26. 24
      app/src/main/res/values/colors.xml
  27. 12
      app/src/main/res/values/helper_input_layout_res.xml
  28. 24
      app/src/main/res/values/strings.xml

@ -32,10 +32,10 @@ import com.wallet.crypto.trustapp.views.CreateAccountActivity;
import com.wallet.crypto.trustapp.views.ExportAccountActivity;
import com.wallet.crypto.trustapp.views.ImportAccountActivity;
import com.wallet.crypto.trustapp.views.RequestActivity;
import com.wallet.crypto.trustapp.views.SendActivity;
import com.wallet.crypto.trustapp.views.SettingsActivity;
import com.wallet.crypto.trustapp.views.TokenListActivity;
import com.wallet.crypto.trustapp.views.TransactionListActivity;
import com.wallet.crypto.trustapp.views.SendActivity;
import com.wallet.crypto.trustapp.views.WarningBackupActivity;
import org.ethereum.geth.Account;
@ -88,7 +88,7 @@ public class Controller {
public static final int IMPORT_ACCOUNT_REQUEST = 1;
public static final int UNLOCK_SCREEN_REQUEST = 1001;
public static final int SHARE_RESULT = 2;
// public static final int SHARE_RESULT = 2;
private static String TAG = "CONTROLLER";
@ -486,24 +486,22 @@ public class Controller {
}
}
public void navigateToExportAccount(Activity parent, String address) {
Intent intent = new Intent(parent, ExportAccountActivity.class);
intent.putExtra(getString(R.string.address_keyword), address);
parent.startActivityForResult(intent, SHARE_RESULT);
}
// public void navigateToExportAccount(Activity parent, String address) {
// Intent intent = new Intent(parent, ExportAccountActivity.class);
// intent.putExtra(getString(R.string.address_keyword), address);
// parent.startActivityForResult(intent, SHARE_RESULT);
// }
public String clickExportAccount(Context context, String address, String new_password) throws ServiceErrorException {
public String exportAccount(String address, String newPassword) throws ServiceErrorException {
try {
Account account = mEtherStore.getAccount(address);
// String account_password = PasswordManager.getPassword(address, mAppContext);
String account_password = new String(KS.get(mAppContext, address.toLowerCase()));
return mEtherStore.exportAccount(account, account_password, new_password);
String accountPassword = new String(KS.get(mAppContext, address.toLowerCase()));
return mEtherStore.exportAccount(account, accountPassword, newPassword);
} catch (ServiceErrorException ex) {
throw ex;
} catch (Exception e) {
Toast.makeText(context, "Failed to export account " + e.getMessage(), Toast.LENGTH_SHORT);
throw new ServiceErrorException(ServiceErrorException.UNKNOWN_ERROR, e.getMessage());
}
return "";
}
public ESTransaction findTransaction(String address, String txn_hash) {
@ -534,15 +532,6 @@ public class Controller {
return mNetworks;
}
public void shareKeystore(Activity parent, String keystoreJson) {
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Keystore");
sharingIntent.putExtra(Intent.EXTRA_TEXT, keystoreJson);
parent.startActivityForResult(Intent.createChooser(sharingIntent, "Share via"), SHARE_RESULT);
}
public static String generatePassphrase() {
return UUID.randomUUID().toString();
}

@ -10,7 +10,6 @@ import org.ethereum.geth.BigInt;
import org.ethereum.geth.Geth;
import org.ethereum.geth.KeyStore;
import org.ethereum.geth.Transaction;
import org.web3j.protocol.core.methods.request.RawTransaction;
import java.nio.charset.Charset;
import java.util.ArrayList;

@ -1,36 +1,15 @@
package com.wallet.crypto.trustapp.controller;
import android.util.Log;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.spongycastle.crypto.generators.SCrypt;
import org.web3j.crypto.CipherException;
import org.web3j.crypto.ECKeyPair;
import org.web3j.crypto.Hash;
import org.web3j.crypto.Keys;
import org.web3j.crypto.Wallet;
import org.web3j.crypto.WalletFile;
import org.web3j.utils.Numeric;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.UUID;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import static cz.msebera.android.httpclient.protocol.HTTP.UTF_8;
import static org.web3j.crypto.Wallet.create;
/**

@ -4,8 +4,8 @@ import com.wallet.crypto.trustapp.model.EPAddressInfo;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
import retrofit2.http.Path;
import retrofit2.http.Query;
/**
* Created by marat on 11/16/17.

@ -4,6 +4,7 @@ import android.support.annotation.Nullable;
public class ServiceErrorException extends Exception {
public static final int UNKNOWN_ERROR = -1;
public static final int INVALID_DATA = 1;
public static final int KEY_STORE_ERROR = 1001;
public static final int FAIL_TO_SAVE_IV_FILE = 1002;

@ -46,7 +46,6 @@ public class KS {
private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
private static final int AUTH_DURATION_SEC = 600;
private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
@ -77,8 +76,7 @@ public class KS {
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(BLOCK_MODE)
.setKeySize(256)
.setUserAuthenticationRequired(true)
.setUserAuthenticationValidityDurationSeconds(AUTH_DURATION_SEC)
.setUserAuthenticationRequired(false)
.setRandomizedEncryptionRequired(true)
.setEncryptionPaddings(PADDING)
.build());

@ -1,15 +1,14 @@
package com.wallet.crypto.trustapp.views;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.support.design.widget.FloatingActionButton;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
@ -21,7 +20,6 @@ import android.widget.TextView;
import android.widget.Toast;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.controller.Controller;
import com.wallet.crypto.trustapp.model.VMAccount;

@ -4,6 +4,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
@ -67,7 +68,9 @@ public class CreateAccountActivity extends AppCompatActivity {
try {
mController.clickCreateAccount(CreateAccountActivity.this, "account name", generatedPassphrase);
} catch (Exception e) {
if (e instanceof ServiceErrorException) {
Log.d("CREATE_ACC", "Error", e);
if (e instanceof ServiceErrorException
&& ((ServiceErrorException) e).code == ServiceErrorException.USER_NOT_AUTHENTICATED) {
KS.showAuthenticationScreen(CreateAccountActivity.this, Controller.UNLOCK_SCREEN_REQUEST);
} else {
Toast.makeText(getApplicationContext(), "Create account: " + e.toString(), Toast.LENGTH_LONG).show();

@ -1,7 +1,5 @@
package com.wallet.crypto.trustapp.views;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -10,10 +8,12 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.wallet.crypto.trustapp.R;
@ -21,86 +21,49 @@ import com.wallet.crypto.trustapp.controller.Controller;
import com.wallet.crypto.trustapp.controller.ServiceErrorException;
import com.wallet.crypto.trustapp.util.KS;
public class ExportAccountActivity extends AppCompatActivity {
public class ExportAccountActivity extends AppCompatActivity implements View.OnClickListener {
private static final int MIN_PASSWORD_LENGTH = 1;
private Controller mController;
public static final String ADDRESS_KEY = "account_address";
public static final int SHARE_REQUEST_CODE = 1;
private String mAddress;
private EditText mPasswordText;
private EditText mConfirmPasswordText;
private Button mExportButton;
private static final int MIN_PASSWORD_LENGTH = 1;
@Override
public static void open(Context context, String accountAddress) {
Intent intent = new Intent(context, ExportAccountActivity.class);
intent.putExtra(ADDRESS_KEY, accountAddress);
context.startActivity(intent);
}
private String accountAddress;
private EditText passwordTxt;
private EditText confirmPasswordTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_export_account);
accountAddress = getIntent().getStringExtra(ADDRESS_KEY);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(getString(R.string.activity_title_backup, accountAddress.substring(0, 5)));
}
mAddress = getIntent().getStringExtra(getString(R.string.address_keyword));
getSupportActionBar().setTitle(getString(R.string.title_backup) + ": " + mAddress.substring(0, 5) + "...");
mController = Controller.with(this);
mPasswordText = findViewById(R.id.export_password);
mConfirmPasswordText = findViewById(R.id.confirm_password);
mExportButton = findViewById(R.id.export_account_button);
mExportButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final String pwd = mPasswordText.getText().toString();
if (!isPasswordLongEnough(pwd)) {
mPasswordText.setError(String.format(getString(R.string.min_pwd_length), MIN_PASSWORD_LENGTH));
}
final String pwdConfirm = mConfirmPasswordText.getText().toString();
if (!isPasswordLongEnough(pwdConfirm)) {
mConfirmPasswordText.setError(String.format(getString(R.string.min_pwd_length), MIN_PASSWORD_LENGTH));
} else if (!pwd.equals(pwdConfirm)) {
mConfirmPasswordText.setError(getString(R.string.error_passwords_must_match));
}
if (!isPasswordLongEnough(pwd) || !isPasswordLongEnough(pwdConfirm) || !pwd.equals(pwdConfirm)) {
return;
}
String keystoreJson = null;
try {
keystoreJson = mController.clickExportAccount(ExportAccountActivity.this, mAddress, mPasswordText.getText().toString());
if (keystoreJson.isEmpty()) {
Toast.makeText(ExportAccountActivity.this, "Unable to export", Toast.LENGTH_SHORT).show();
} else {
mController.shareKeystore(ExportAccountActivity.this, keystoreJson);
}
} catch (ServiceErrorException e) {
if (e.code == ServiceErrorException.USER_NOT_AUTHENTICATED) {
KS.showAuthenticationScreen(ExportAccountActivity.this, Controller.UNLOCK_SCREEN_REQUEST);
}
}
}
passwordTxt = findViewById(R.id.password);
confirmPasswordTxt = findViewById(R.id.confirm_password);
confirmPasswordTxt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});
}
boolean isPasswordLongEnough(String password) {
return password.length() >= MIN_PASSWORD_LENGTH;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Controller.SHARE_RESULT) {
if (resultCode == RESULT_OK) {
setResult(RESULT_OK);
finish();
}
}
findViewById(R.id.export_account_button).setOnClickListener(this);
}
@Override
@ -112,4 +75,92 @@ public class ExportAccountActivity extends AppCompatActivity {
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SHARE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
setResult(RESULT_OK);
finish();
} else {
new AlertDialog.Builder(this)
.setMessage(R.string.do_manage_make_backup)
.setPositiveButton(R.string.yes_continue, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setResult(RESULT_OK);
finish();
}
})
.setNegativeButton(R.string.no_repeat, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onExport();
}
})
.show();
}
} else if (requestCode == Controller.UNLOCK_SCREEN_REQUEST) {
if (resultCode == RESULT_OK) {
onExport();
} else {
showError(getString(R.string.unable_unblock_device));
}
}
}
@Override
public void onClick(View v) {
onExport();
}
public void onExport() {
final String password = passwordTxt.getText().toString();
final String passwordConfirm = confirmPasswordTxt.getText().toString();
if (isPasswordValid(password, passwordConfirm)) {
try {
String jsonData = Controller.with(this).exportAccount(accountAddress, password);
if (!TextUtils.isEmpty(jsonData)) {
openShareDialog(jsonData);
} else {
showError("Unable to export");
}
} catch (ServiceErrorException e) {
if (e.code == ServiceErrorException.USER_NOT_AUTHENTICATED) {
KS.showAuthenticationScreen(ExportAccountActivity.this, Controller.UNLOCK_SCREEN_REQUEST);
} else {
showError("Failed to export account " + e.getMessage());
}
}
}
}
private void openShareDialog(String jsonData) {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "Keystore");
sharingIntent.putExtra(Intent.EXTRA_TEXT, jsonData);
startActivityForResult(
Intent.createChooser(sharingIntent, "Share via"),
SHARE_REQUEST_CODE);
}
private void showError(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
private boolean isPasswordValid(String password, String passwordConfirm) {
boolean isValid = true;
if (password.length() < MIN_PASSWORD_LENGTH) {
passwordTxt.setError(String.format(getString(R.string.min_pwd_length), MIN_PASSWORD_LENGTH));
isValid = false;
}
if (!password.equals(passwordConfirm)) {
confirmPasswordTxt.setError(getString(R.string.error_passwords_must_match));
isValid = false;
}
return isValid;
}
}

@ -10,17 +10,8 @@ import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.controller.Controller;
import com.wallet.crypto.trustapp.controller.OnTaskCompleted;
import com.wallet.crypto.trustapp.controller.TaskResult;
import com.wallet.crypto.trustapp.controller.TaskStatus;
public class ImportAccountActivity extends AppCompatActivity {

@ -1,14 +1,14 @@
package com.wallet.crypto.trustapp.views;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import com.wallet.crypto.trustapp.R;
import com.github.paolorotolo.appintro.AppIntro;
import com.github.paolorotolo.appintro.AppIntroFragment;
import com.wallet.crypto.trustapp.R;
public class IntroActivity extends AppIntro {
@Override

@ -3,11 +3,11 @@ package com.wallet.crypto.trustapp.views;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@ -16,15 +16,14 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.journeyapps.barcodescanner.BarcodeEncoder;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.controller.Controller;
import com.wallet.crypto.trustapp.model.VMAccount;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.journeyapps.barcodescanner.BarcodeEncoder;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.controller.Controller;
import com.wallet.crypto.trustapp.model.VMAccount;
public class RequestActivity extends AppCompatActivity {

@ -1,7 +1,7 @@
package com.wallet.crypto.trustapp.views;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.wallet.crypto.trustapp.R;

@ -1,8 +1,6 @@
package com.wallet.crypto.trustapp.views;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
@ -45,8 +43,7 @@ public class SettingsFragment extends PreferenceFragment
export.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
mController.navigateToExportAccount(getActivity(), mController.getCurrentAccount().getAddress());
ExportAccountActivity.open(getContext(), mController.getCurrentAccount().getAddress());
return false;
}
});

@ -1,8 +1,8 @@
package com.wallet.crypto.trustapp.views;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class SplashActivity extends AppCompatActivity {

@ -4,8 +4,6 @@ import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;

@ -1,9 +1,9 @@
package com.wallet.crypto.trustapp.views;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import com.wallet.crypto.trustapp.R;

@ -4,14 +4,13 @@ import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.support.design.widget.CollapsingToolbarLayout;
import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.wallet.crypto.trustapp.R;

@ -6,7 +6,9 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.widget.SwipeRefreshLayout;
@ -22,7 +24,6 @@ import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.controller.Controller;
import com.wallet.crypto.trustapp.controller.OnTaskCompleted;
@ -178,7 +179,11 @@ public class TransactionListActivity extends AppCompatActivity {
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (keyguardManager != null && !keyguardManager.isDeviceSecure()) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
if (keyguardManager != null
&& !keyguardManager.isDeviceSecure()
&& pref.getBoolean("should_show_security_alert", true)) {
pref.edit().putBoolean("should_show_security_alert", false).apply();
new AlertDialog.Builder(this)
.setTitle(R.string.lock_title)
.setMessage(R.string.lock_body)
@ -189,10 +194,9 @@ public class TransactionListActivity extends AppCompatActivity {
startActivity(intent);
}
})
.setNegativeButton(R.string.lock_exit, new DialogInterface.OnClickListener() {
.setNegativeButton(R.string.skip, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
})
.show();

@ -34,7 +34,7 @@ public class WarningBackupActivity extends AppCompatActivity {
mBackupButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
controller.navigateToExportAccount(WarningBackupActivity.this, mAddress);
ExportAccountActivity.open(getApplicationContext(), mAddress);
}
});
@ -64,15 +64,13 @@ public class WarningBackupActivity extends AppCompatActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == Controller.SHARE_RESULT) {
if (requestCode == ExportAccountActivity.SHARE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
if (Controller.with(this).getAccounts().size() == 1) {
Intent intent = new Intent(getApplicationContext(), TransactionListActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
}
finish();
}
}

@ -37,15 +37,15 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.Toast;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.views.camera.CameraSource;
import com.wallet.crypto.trustapp.views.camera.CameraSourcePreview;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.vision.MultiProcessor;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import com.wallet.crypto.trustapp.R;
import com.wallet.crypto.trustapp.views.camera.CameraSource;
import com.wallet.crypto.trustapp.views.camera.CameraSourcePreview;
import java.io.IOException;

@ -0,0 +1,151 @@
package com.wallet.crypto.trustapp.widget;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.support.design.widget.TextInputLayout;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.EditText;
import android.widget.TextView;
import com.wallet.crypto.trustapp.R;
/**
* TextInputLayout temporary workaround for helper text showing
* https://gist.github.com/drstranges/1a86965f582f610244d6
*/
public class HelperTextInputLayout extends TextInputLayout {
static final Interpolator FAST_OUT_SLOW_IN_INTERPOLATOR = new FastOutSlowInInterpolator();
private CharSequence mHelperText;
private ColorStateList mHelperTextColor;
private boolean mHelperTextEnabled = false;
private boolean mErrorEnabled = false;
private TextView mHelperView;
private int mHelperTextAppearance = R.style.HelperTextAppearance;
public HelperTextInputLayout(Context _context) {
super(_context);
}
public HelperTextInputLayout(Context _context, AttributeSet _attrs) {
super(_context, _attrs);
final TypedArray a = getContext().obtainStyledAttributes(
_attrs,
R.styleable.HelperTextInputLayout,0,0);
try {
mHelperTextColor = a.getColorStateList(R.styleable.HelperTextInputLayout_helperTextColor);
mHelperText = a.getText(R.styleable.HelperTextInputLayout_helperText);
} finally {
a.recycle();
}
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
super.addView(child, index, params);
if (child instanceof EditText) {
if (!TextUtils.isEmpty(mHelperText)) {
setHelperText(mHelperText);
}
}
}
public int getHelperTextAppearance() {
return mHelperTextAppearance;
}
public void setHelperTextAppearance(int _helperTextAppearanceResId) {
mHelperTextAppearance = _helperTextAppearanceResId;
}
public void setHelperTextColor(ColorStateList _helperTextColor) {
mHelperTextColor = _helperTextColor;
}
public void setHelperTextEnabled(boolean _enabled) {
if (mHelperTextEnabled == _enabled) return;
if (_enabled && mErrorEnabled) {
setErrorEnabled(false);
}
if (this.mHelperTextEnabled != _enabled) {
if (_enabled) {
this.mHelperView = new TextView(this.getContext());
this.mHelperView.setTextAppearance(this.getContext(), this.mHelperTextAppearance);
if (mHelperTextColor != null){
this.mHelperView.setTextColor(mHelperTextColor);
}
this.mHelperView.setVisibility(INVISIBLE);
this.addView(this.mHelperView);
if (this.mHelperView != null) {
ViewCompat.setPaddingRelative(
this.mHelperView,
ViewCompat.getPaddingStart(getEditText()),
0, ViewCompat.getPaddingEnd(getEditText()),
getEditText().getPaddingBottom());
}
} else {
this.removeView(this.mHelperView);
this.mHelperView = null;
}
this.mHelperTextEnabled = _enabled;
}
}
public void setHelperText(CharSequence _helperText) {
mHelperText = _helperText;
if (!this.mHelperTextEnabled) {
if (TextUtils.isEmpty(mHelperText)) {
return;
}
this.setHelperTextEnabled(true);
}
if (!TextUtils.isEmpty(mHelperText)) {
this.mHelperView.setText(mHelperText);
this.mHelperView.setVisibility(VISIBLE);
ViewCompat.setAlpha(this.mHelperView, 0.0F);
ViewCompat.animate(this.mHelperView)
.alpha(1.0F).setDuration(200L)
.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR)
.setListener(null).start();
} else if (this.mHelperView.getVisibility() == VISIBLE) {
ViewCompat.animate(this.mHelperView)
.alpha(0.0F).setDuration(200L)
.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR)
.setListener(new ViewPropertyAnimatorListenerAdapter() {
public void onAnimationEnd(View view) {
mHelperView.setText(null);
mHelperView.setVisibility(INVISIBLE);
}
}).start();
}
this.sendAccessibilityEvent(2048);
}
@Override
public void setErrorEnabled(boolean _enabled) {
if (mErrorEnabled == _enabled) return;
mErrorEnabled = _enabled;
if (_enabled && mHelperTextEnabled) {
setHelperTextEnabled(false);
}
super.setErrorEnabled(_enabled);
if (!(_enabled || TextUtils.isEmpty(mHelperText))) {
setHelperText(mHelperText);
}
}
}

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@color/colorWhite" />
<item android:drawable="@color/white" />
<item>
<bitmap
android:gravity="center"

@ -1,26 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.wallet.crypto.trustapp.views.ExportAccountActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:title="@string/action_export"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_export_account" />
</android.support.design.widget.CoordinatorLayout>
>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:title="@string/action_export"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
/>
<LinearLayout
android:orientation="vertical"
android:padding="16dp"
android:layout_marginTop="?actionBarSize"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.wallet.crypto.trustapp.widget.HelperTextInputLayout
app:helperText="@string/backup_new_password_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/password"
android:hint="@string/label_new_password"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:maxLines="1"
android:singleLine="true"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</com.wallet.crypto.trustapp.widget.HelperTextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/confirm_password"
android:hint="@string/label_confirm_new_password"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/export_account_button"
android:text="@string/action_backup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
/>
</LinearLayout>
</FrameLayout>

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.wallet.crypto.trustapp.views.ExportAccountActivity"
tools:showIn="@layout/activity_export_account">
<LinearLayout
android:id="@+id/import_form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/export_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/label_new_password"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/confirm_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/label_confirm_new_password"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/export_account_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/action_backup"
android:textStyle="bold" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#2e91db</color>
<color name="colorPrimaryDark">#1E76CE</color>
<color name="colorAccent">#2e91db</color>
<color name="green">#2fbb4f</color>
<color name="red">#f7506c</color>
<color name="colorWhite">#FFFFFFFF</color>
<color name="semitransparentWhite">#AAFFFFFF</color>
<color name="QRCodeBlackColor">#FF000000</color>
<color name="QRCodeWhiteColor">#FFFFFFFF</color>
<color name="black">#313849</color>
<color name="green">#2fbb4f</color>
<color name="red">#f7506c</color>
<color name="white">#FFFFFFFF</color>
<color name="black">#313849</color>
<color name="colorPrimary">#2e91db</color>
<color name="colorPrimaryDark">#1E76CE</color>
<color name="colorAccent">#2e91db</color>
<color name="secondary_text">#40000000</color>
<color name="semitransparentWhite">#AAFFFFFF</color>
<color name="QRCodeBlackColor">#FF000000</color>
<color name="QRCodeWhiteColor">#FFFFFFFF</color>
</resources>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HelperTextInputLayout">
<attr name="helperText" format="string"/>
<attr name="helperTextColor" format="color|reference"/>
</declare-styleable>
<style name="HelperTextAppearance" parent="TextAppearance.Design.Error">
<item name="android:textColor">@color/secondary_text</item>
</style>
</resources>

@ -41,7 +41,6 @@
<string name="action_import">Import</string>
<string name="title_activity_export_account">ExportAccountActivity</string>
<string name="action_export">Backup private key</string>
<string name="address_keyword">ADDRESS</string>
<string name="message_save_this">Keep this someplace safe</string>
<string name="copy">Copy to clipboard</string>
<string name="close">Close</string>
@ -95,7 +94,7 @@
<string name="error_passwords_must_match">Passwords must match.</string>
<string name="label_confirm_new_password">Confirm new password</string>
<string name="label_new_password">New password</string>
<string name="title_backup">Backup</string>
<string name="activity_title_backup">Backup: %s…</string>
<string name="action_backup">Backup</string>
<string name="title_privacy_policy">Privacy Policy</string>
<string name="title_terms">Terms and Conditions</string>
@ -108,14 +107,21 @@
<string name="tab_keystore">Keystore</string>
<string name="tab_private_key">Private key</string>
<string name="action_transaction_detail">More details</string>
<string name="lock_title">Lock screen</string>
<string name="lock_body">Secure lock screen hasn\'t set up. To continue working with this app, please go to Settings and set a lock screen method.</string>
<string name="lock_settings">Lock settings</string>
<string name="lock_exit">Exit</string>
<string name="unlock_screen_title_android">Unlock screen</string>
<string name="unlock_screen_prompt_android">Please unlock your Android device to continue.</string>
<string name="sending_progress">Sending...</string>
<string name="lock_title">Lock screen</string>
<string name="lock_body">Secure lock screen hasn\'t set up. It is not safe.</string>
<string name="lock_settings">Lock settings</string>
<string name="lock_exit">Exit</string>
<string name="unlock_screen_title_android">Unlock screen</string>
<string name="unlock_screen_prompt_android">Please unlock your Android device to continue.</string>
<string name="sending_progress">Sending...</string>
<string name="backup_new_password_text">Think of a password that will be installed on the backup.\nThe password will be available for this account.</string>
<string name="do_manage_make_backup">Did you manage to make a backup?</string>
<string name="yes_continue">Yes, continue</string>
<string name="no_repeat">No, repeat</string>
<string name="unable_unblock_device">Unable to unlock the device.</string>
<string name="gas_limit">Gas Limit</string>
<string name="gas_price">Gas Price (Wei)</string>
<string name="skip">Skip</string>
</resources>

Loading…
Cancel
Save