Java tutorial
/* * Copyright 2013, 2014 Megion Research and Development GmbH * * Licensed under the Microsoft Reference Source License (MS-RSL) * * This license governs use of the accompanying software. If you use the software, you accept this license. * If you do not accept the license, do not use the software. * * 1. Definitions * The terms "reproduce," "reproduction," and "distribution" have the same meaning here as under U.S. copyright law. * "You" means the licensee of the software. * "Your company" means the company you worked for when you downloaded the software. * "Reference use" means use of the software within your company as a reference, in read only form, for the sole purposes * of debugging your products, maintaining your products, or enhancing the interoperability of your products with the * software, and specifically excludes the right to distribute the software outside of your company. * "Licensed patents" means any Licensor patent claims which read directly on the software as distributed by the Licensor * under this license. * * 2. Grant of Rights * (A) Copyright Grant- Subject to the terms of this license, the Licensor grants you a non-transferable, non-exclusive, * worldwide, royalty-free copyright license to reproduce the software for reference use. * (B) Patent Grant- Subject to the terms of this license, the Licensor grants you a non-transferable, non-exclusive, * worldwide, royalty-free patent license under licensed patents for reference use. * * 3. Limitations * (A) No Trademark License- This license does not grant you any rights to use the Licensors name, logo, or trademarks. * (B) If you begin patent litigation against the Licensor over patents that you think may apply to the software * (including a cross-claim or counterclaim in a lawsuit), your license to the software ends automatically. * (C) The software is licensed "as-is." You bear the risk of using it. The Licensor gives no express warranties, * guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot * change. To the extent permitted under your local laws, the Licensor excludes the implied warranties of merchantability, * fitness for a particular purpose and non-infringement. */ package com.mycelium.wallet.activity; import android.app.Activity; import android.app.Fragment; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; import com.google.common.collect.Iterables; import com.mrd.bitlib.crypto.HdKeyNode; import com.mrd.bitlib.model.hdpath.HdKeyPath; import com.mycelium.wallet.MbwManager; import com.mycelium.wallet.R; import com.mycelium.wallet.Utils; import com.mycelium.wapi.wallet.AccountScanManager; import com.mycelium.wallet.activity.util.MasterseedPasswordSetter; import com.mycelium.wallet.activity.util.AbstractAccountScanManager; import com.mycelium.wapi.model.Balance; import com.mycelium.wapi.wallet.SyncMode; import com.mycelium.wapi.wallet.WalletAccount; import com.mycelium.wapi.wallet.WalletManager; import com.mycelium.wapi.wallet.bip44.Bip44Account; import com.squareup.otto.Subscribe; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.UUID; public abstract class HdAccountSelectorActivity extends Activity implements MasterseedPasswordSetter { protected final static int REQUEST_SEND = 1; public static final String PASSPHRASE_FRAGMENT_TAG = "passphrase"; protected ArrayList<HdAccountWrapper> accounts = new ArrayList<HdAccountWrapper>(); protected AccountsAdapter accountsAdapter; protected AbstractAccountScanManager masterseedScanManager; private ListView lvAccounts; protected TextView txtStatus; protected abstract AbstractAccountScanManager initMasterseedManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setView(); lvAccounts = (ListView) findViewById(R.id.lvAccounts); txtStatus = (TextView) findViewById(R.id.txtStatus); // Accounts listview + adapter accountsAdapter = new AccountsAdapter(this, R.id.lvAccounts, accounts); lvAccounts.setAdapter(accountsAdapter); lvAccounts.setOnItemClickListener(accountClickListener()); masterseedScanManager = initMasterseedManager(); startBackgroundScan(); updateUi(); } protected void startBackgroundScan() { masterseedScanManager.startBackgroundAccountScan(new AccountScanManager.AccountCallback() { @Override public UUID checkForTransactions(AbstractAccountScanManager.HdKeyNodeWrapper account) { MbwManager mbwManager = MbwManager.getInstance(getApplicationContext()); WalletManager walletManager = mbwManager.getWalletManager(true); UUID id = masterseedScanManager.createOnTheFlyAccount(account.accountRoot, walletManager, account.keyPath.getLastIndex()); Bip44Account tempAccount = (Bip44Account) walletManager.getAccount(id); tempAccount.doSynchronization(SyncMode.NORMAL_WITHOUT_TX_LOOKUP); if (tempAccount.hasHadActivity()) { return id; } else { tempAccount.dropCachedData(); return null; } } }); } abstract protected AdapterView.OnItemClickListener accountClickListener(); abstract protected void setView(); @Override public void finish() { super.finish(); masterseedScanManager.stopBackgroundAccountScan(); } @Override protected void onResume() { super.onResume(); MbwManager.getInstance(this).getEventBus().register(this); } @Override protected void onPause() { MbwManager.getInstance(getApplicationContext()).getEventBus().unregister(this); super.onPause(); } protected void updateUi() { if (masterseedScanManager.currentAccountState == AccountScanManager.AccountStatus.scanning) { findViewById(R.id.llStatus).setVisibility(View.VISIBLE); if (accounts.size() > 0) { txtStatus.setText( String.format(getString(R.string.account_found), Iterables.getLast(accounts).name)); findViewById(R.id.llSelectAccount).setVisibility(View.VISIBLE); } } else if (masterseedScanManager.currentAccountState == AccountScanManager.AccountStatus.done) { // DONE findViewById(R.id.llStatus).setVisibility(View.GONE); findViewById(R.id.llSelectAccount).setVisibility(View.VISIBLE); if (accounts.size() == 0) { // no accounts found findViewById(R.id.tvNoAccounts).setVisibility(View.VISIBLE); findViewById(R.id.lvAccounts).setVisibility(View.GONE); } else { findViewById(R.id.tvNoAccounts).setVisibility(View.GONE); findViewById(R.id.lvAccounts).setVisibility(View.VISIBLE); } } accountsAdapter.notifyDataSetChanged(); } @Override public void onBackPressed() { super.onBackPressed(); clearTempData(); } protected void clearTempData() { // remove all account-data from the tempWalletManager, to improve privacy MbwManager.getInstance(this).forgetColdStorageWalletManager(); masterseedScanManager.forgetAccounts(); } @Override public void setPassphrase(String passphrase) { masterseedScanManager.setPassphrase(passphrase); if (passphrase == null) { // user choose cancel -> leave this activity finish(); } else { // close the dialog fragment Fragment fragPassphrase = getFragmentManager().findFragmentByTag(PASSPHRASE_FRAGMENT_TAG); if (fragPassphrase != null) { getFragmentManager().beginTransaction().remove(fragPassphrase).commit(); } } } protected class HdAccountWrapper implements Serializable { public UUID id; public HdKeyPath accountHdKeyPath; public HdKeyNode xPub; public String name; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; HdAccountWrapper that = (HdAccountWrapper) o; if (id != null ? !id.equals(that.id) : that.id != null) return false; return true; } @Override public int hashCode() { return id != null ? id.hashCode() : 0; } } protected class AccountsAdapter extends ArrayAdapter<HdAccountWrapper> { private AccountsAdapter(Context context, int resource, List<HdAccountWrapper> objects) { super(context, resource, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) getContext() .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View row; if (convertView == null) { row = inflater.inflate(R.layout.record_row, parent, false); } else { row = convertView; } HdAccountWrapper account = getItem(position); ((TextView) row.findViewById(R.id.tvLabel)).setText(account.name); WalletAccount walletAccount = MbwManager.getInstance(getContext()).getWalletManager(true) .getAccount(account.id); Balance balance = walletAccount.getBalance(); String balanceString = MbwManager.getInstance(getContext()) .getBtcValueString(balance.confirmed + balance.pendingChange); if (balance.getSendingBalance() > 0) { balanceString += " " + String.format(getString(R.string.account_balance_sending_amount), MbwManager.getInstance(getContext()).getBtcValueString(balance.getSendingBalance())); } Drawable drawableForAccount = Utils.getDrawableForAccount(walletAccount, true, getResources()); ((TextView) row.findViewById(R.id.tvBalance)).setText(balanceString); ((TextView) row.findViewById(R.id.tvAddress)).setVisibility(View.GONE); ((ImageView) row.findViewById(R.id.ivIcon)).setImageDrawable(drawableForAccount); ((TextView) row.findViewById(R.id.tvLegacyAccountWarning)).setVisibility(View.GONE); ((TextView) row.findViewById(R.id.tvBackupMissingWarning)).setVisibility(View.GONE); return row; } } @Subscribe public void onScanError(AccountScanManager.OnScanError event) { Utils.showSimpleMessageDialog(this, event.errorMessage); } @Subscribe public void onStatusChanged(AccountScanManager.OnStatusChanged event) { updateUi(); } @Subscribe public void onAccountFound(AccountScanManager.OnAccountFound event) { HdAccountWrapper acc = new HdAccountWrapper(); acc.id = event.account.accountId; acc.accountHdKeyPath = event.account.keyPath; if (event.account.keyPath.equals(HdKeyPath.BIP32_ROOT)) { acc.name = getString(R.string.bip32_root_account); } else { acc.name = String.format(getString(R.string.account_number), event.account.keyPath.getLastIndex() + 1); } acc.xPub = event.account.accountRoot; if (!accounts.contains(acc)) { accountsAdapter.add(acc); updateUi(); } } @Subscribe public void onPassphraseRequest(AccountScanManager.OnPassphraseRequest event) { MasterseedPasswordDialog pwd = new MasterseedPasswordDialog(); pwd.show(getFragmentManager(), PASSPHRASE_FRAGMENT_TAG); } }