From 44850ed5cef02cdd60e7d5a83672f1100a43937f Mon Sep 17 00:00:00 2001 From: Maksim Date: Tue, 12 Dec 2017 09:49:32 +0700 Subject: [PATCH] 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 --- .../trustapp/controller/Controller.java | 33 +-- .../trustapp/controller/EtherStore.java | 1 - .../trustapp/controller/EtherStoreUtils.java | 23 +-- .../trustapp/controller/EthplorerService.java | 2 +- .../controller/ServiceErrorException.java | 1 + .../com/wallet/crypto/trustapp/util/KS.java | 4 +- .../trustapp/views/AccountListActivity.java | 4 +- .../trustapp/views/CreateAccountActivity.java | 5 +- .../trustapp/views/ExportAccountActivity.java | 189 +++++++++++------- .../trustapp/views/ImportAccountActivity.java | 9 - .../crypto/trustapp/views/IntroActivity.java | 4 +- .../trustapp/views/RequestActivity.java | 13 +- .../trustapp/views/SettingsActivity.java | 2 +- .../trustapp/views/SettingsFragment.java | 5 +- .../crypto/trustapp/views/SplashActivity.java | 2 +- .../trustapp/views/TokenListActivity.java | 2 - .../views/TransactionDetailActivity.java | 4 +- .../views/TransactionDetailFragment.java | 3 +- .../views/TransactionListActivity.java | 12 +- .../trustapp/views/WarningBackupActivity.java | 6 +- .../views/barcode/BarcodeCaptureActivity.java | 6 +- .../widget/HelperTextInputLayout.java | 151 ++++++++++++++ .../main/res/drawable/splash_background.xml | 2 +- .../res/layout/activity_export_account.xml | 81 ++++++-- .../res/layout/content_export_account.xml | 63 ------ app/src/main/res/values/colors.xml | 24 ++- .../res/values/helper_input_layout_res.xml | 12 ++ app/src/main/res/values/strings.xml | 24 ++- 28 files changed, 419 insertions(+), 268 deletions(-) create mode 100644 app/src/main/java/com/wallet/crypto/trustapp/widget/HelperTextInputLayout.java delete mode 100644 app/src/main/res/layout/content_export_account.xml create mode 100644 app/src/main/res/values/helper_input_layout_res.xml diff --git a/app/src/main/java/com/wallet/crypto/trustapp/controller/Controller.java b/app/src/main/java/com/wallet/crypto/trustapp/controller/Controller.java index 352143dbe..531a52b5e 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/controller/Controller.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/controller/Controller.java @@ -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(); } diff --git a/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStore.java b/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStore.java index 1b5244982..314f416f4 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStore.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStore.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStoreUtils.java b/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStoreUtils.java index 54ffc95e1..55499a3a8 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStoreUtils.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/controller/EtherStoreUtils.java @@ -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; /** diff --git a/app/src/main/java/com/wallet/crypto/trustapp/controller/EthplorerService.java b/app/src/main/java/com/wallet/crypto/trustapp/controller/EthplorerService.java index 5af811f82..9debf976e 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/controller/EthplorerService.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/controller/EthplorerService.java @@ -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. diff --git a/app/src/main/java/com/wallet/crypto/trustapp/controller/ServiceErrorException.java b/app/src/main/java/com/wallet/crypto/trustapp/controller/ServiceErrorException.java index 2971b1b00..67ce3f422 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/controller/ServiceErrorException.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/controller/ServiceErrorException.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/util/KS.java b/app/src/main/java/com/wallet/crypto/trustapp/util/KS.java index 3d73ee117..1bfb6bf9c 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/util/KS.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/util/KS.java @@ -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()); diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/AccountListActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/AccountListActivity.java index 6fbf76437..a7f3c602f 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/AccountListActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/AccountListActivity.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/CreateAccountActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/CreateAccountActivity.java index 0a86f4d2f..0054bf2ae 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/CreateAccountActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/CreateAccountActivity.java @@ -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(); diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/ExportAccountActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/ExportAccountActivity.java index 733e0e553..6e9f2a512 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/ExportAccountActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/ExportAccountActivity.java @@ -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; + } } diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/ImportAccountActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/ImportAccountActivity.java index 4c8a75e73..2574748b3 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/ImportAccountActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/ImportAccountActivity.java @@ -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 { diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/IntroActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/IntroActivity.java index dddf3871a..9ccaabb29 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/IntroActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/IntroActivity.java @@ -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 diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/RequestActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/RequestActivity.java index 3d09d08fe..49bd769f3 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/RequestActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/RequestActivity.java @@ -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 { diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsActivity.java index 8f6929c55..6828a13c9 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsActivity.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsFragment.java b/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsFragment.java index 629813a8c..64220d34d 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsFragment.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/SettingsFragment.java @@ -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; } }); diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/SplashActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/SplashActivity.java index e5db0c80b..ee490d836 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/SplashActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/SplashActivity.java @@ -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 { diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/TokenListActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/TokenListActivity.java index 0a10c1b8f..3032802ac 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/TokenListActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/TokenListActivity.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailActivity.java index 684615675..033af90b5 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailActivity.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailFragment.java b/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailFragment.java index ac459bf6d..2ec54766f 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailFragment.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionDetailFragment.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionListActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionListActivity.java index f93fd3b9f..a16ce4b77 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionListActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/TransactionListActivity.java @@ -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(); diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/WarningBackupActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/WarningBackupActivity.java index 92720608e..44078ee67 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/WarningBackupActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/WarningBackupActivity.java @@ -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(); } } diff --git a/app/src/main/java/com/wallet/crypto/trustapp/views/barcode/BarcodeCaptureActivity.java b/app/src/main/java/com/wallet/crypto/trustapp/views/barcode/BarcodeCaptureActivity.java index 8d63da13e..43597a4ec 100644 --- a/app/src/main/java/com/wallet/crypto/trustapp/views/barcode/BarcodeCaptureActivity.java +++ b/app/src/main/java/com/wallet/crypto/trustapp/views/barcode/BarcodeCaptureActivity.java @@ -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; diff --git a/app/src/main/java/com/wallet/crypto/trustapp/widget/HelperTextInputLayout.java b/app/src/main/java/com/wallet/crypto/trustapp/widget/HelperTextInputLayout.java new file mode 100644 index 000000000..bd5047361 --- /dev/null +++ b/app/src/main/java/com/wallet/crypto/trustapp/widget/HelperTextInputLayout.java @@ -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); + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable/splash_background.xml b/app/src/main/res/drawable/splash_background.xml index bf1c40a7f..cbd2860a8 100644 --- a/app/src/main/res/drawable/splash_background.xml +++ b/app/src/main/res/drawable/splash_background.xml @@ -1,7 +1,7 @@ - + - - - - - - - - - - - + > + + + + + + + + +