Android Open Source - bitfynd-wallet-android Sweep Wallet Fragment






From Project

Back to project page bitfynd-wallet-android.

License

The source code is released under:

GNU General Public License

If you think the Android project bitfynd-wallet-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
* Copyright 2014 the original author or authors.
*/* w ww .  ja v  a 2 s.  co m*/
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package de.schildbach.wallet.ui.send;

import static com.google.common.base.Preconditions.checkState;

import java.util.Collection;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.bitcoinj.core.Address;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.DumpedPrivateKey;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.core.VersionedChecksummedBytes;
import org.bitcoinj.core.Wallet;
import org.bitcoinj.core.Wallet.BalanceType;
import org.bitcoinj.core.Wallet.SendRequest;
import org.bitcoinj.crypto.BIP38PrivateKey;
import org.bitcoinj.utils.MonetaryFormat;
import org.bitcoinj.wallet.KeyChainGroup;
import org.bitcoinj.wallet.WalletTransaction;
import org.bitcoinj.wallet.WalletTransaction.Pool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.preference.PreferenceManager;
import android.text.SpannableStringBuilder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;

import de.schildbach.wallet.BuildConfig;
import de.schildbach.wallet.Configuration;
import de.schildbach.wallet.Constants;
import de.schildbach.wallet.WalletApplication;
import de.schildbach.wallet.data.PaymentIntent;
import de.schildbach.wallet.ui.AbstractBindServiceActivity;
import de.schildbach.wallet.ui.DialogBuilder;
import de.schildbach.wallet.ui.InputParser.StringInputParser;
import de.schildbach.wallet.ui.ProgressDialogFragment;
import de.schildbach.wallet.ui.ScanActivity;
import de.schildbach.wallet.ui.TransactionsListAdapter;
import de.schildbach.wallet.util.MonetarySpannable;
import de.schildbach.wallet.util.WalletUtils;
import de.schildbach.wallet.R;

/**
 * @author Andreas Schildbach
 */
public class SweepWalletFragment extends Fragment
{
  private AbstractBindServiceActivity activity;
  private WalletApplication application;
  private Configuration config;
  private FragmentManager fragmentManager;

  private final Handler handler = new Handler();
  private HandlerThread backgroundThread;
  private Handler backgroundHandler;

    private State state = State.DECODE_KEY;
  private VersionedChecksummedBytes privateKeyToSweep = null;
  private Wallet walletToSweep = null;
  private Transaction sentTransaction = null;

    private TextView messageView;
  private View passwordViewGroup;
  private EditText passwordView;
  private View badPasswordView;
  private TextView balanceView;
  private TransactionsListAdapter sweepTransactionListAdapter;
  private View hintView;
  private ListView sweepTransactionView;
  private Button viewGo;
  private Button viewCancel;

  private MenuItem reloadAction;
  private MenuItem scanAction;

  private static final int REQUEST_CODE_SCAN = 0;

  private enum State
  {
        DECODE_KEY, CONFIRM_SWEEP, PREPARATION, SENDING, SENT, FAILED
  }

    private static final Logger log = LoggerFactory.getLogger(SweepWalletFragment.class);

  @Override
  public void onAttach(final Activity activity)
  {
    super.onAttach(activity);

    this.activity = (AbstractBindServiceActivity) activity;
    this.application = (WalletApplication) activity.getApplication();
    this.config = application.getConfiguration();
    this.config = new Configuration(PreferenceManager.getDefaultSharedPreferences(activity));
    this.fragmentManager = getFragmentManager();
  }

  @Override
  public void onCreate(final Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    setRetainInstance(true);
    setHasOptionsMenu(true);

    backgroundThread = new HandlerThread("backgroundThread", Process.THREAD_PRIORITY_BACKGROUND);
    backgroundThread.start();
    backgroundHandler = new Handler(backgroundThread.getLooper());

    if (savedInstanceState != null)
    {
      restoreInstanceState(savedInstanceState);
    }
    else
    {
      final Intent intent = activity.getIntent();

      if (intent.hasExtra(SweepWalletActivity.INTENT_EXTRA_KEY))
      {
                privateKeyToSweep = (VersionedChecksummedBytes) intent.getSerializableExtra(SweepWalletActivity.INTENT_EXTRA_KEY);

                // delay until fragment is resumed
                handler.post(maybeDecodeKeyRunnable);
      }
    }
  }

  @Override
  public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
  {
    final View view = inflater.inflate(R.layout.sweep_wallet_fragment, container);

        messageView = (TextView) view.findViewById(R.id.sweep_wallet_fragment_message);

        passwordViewGroup = view.findViewById(R.id.sweep_wallet_fragment_password_group);
    passwordView = (EditText) view.findViewById(R.id.sweep_wallet_fragment_password);
    badPasswordView = view.findViewById(R.id.sweep_wallet_fragment_bad_password);

    balanceView = (TextView) view.findViewById(R.id.sweep_wallet_fragment_balance);

    hintView = view.findViewById(R.id.sweep_wallet_fragment_hint);

    sweepTransactionView = (ListView) view.findViewById(R.id.sweep_wallet_fragment_sent_transaction);
    sweepTransactionListAdapter = new TransactionsListAdapter(activity, application.getWallet(), application.maxConnectedPeers(), false);
    sweepTransactionView.setAdapter(sweepTransactionListAdapter);

    viewGo = (Button) view.findViewById(R.id.send_coins_go);
    viewGo.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(final View v)
      {
                if (state == State.DECODE_KEY)
          handleDecrypt();
        if (state == State.CONFIRM_SWEEP)
          handleSweep();
      }
    });

    viewCancel = (Button) view.findViewById(R.id.send_coins_cancel);
    viewCancel.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(final View v)
      {
        activity.finish();
      }
    });

    return view;
  }

  @Override
  public void onResume()
  {
    super.onResume();

    updateView();
  }

  @Override
  public void onDestroy()
  {
    backgroundThread.getLooper().quit();

    if (sentTransaction != null)
      sentTransaction.getConfidence().removeEventListener(sentTransactionConfidenceListener);

    super.onDestroy();
  }

  @Override
  public void onSaveInstanceState(final Bundle outState)
  {
    super.onSaveInstanceState(outState);

    saveInstanceState(outState);
  }

  private void saveInstanceState(final Bundle outState)
  {
    outState.putSerializable("state", state);
    if (walletToSweep != null)
      outState.putByteArray("wallet_to_sweep", WalletUtils.walletToByteArray(walletToSweep));
    if (sentTransaction != null)
      outState.putSerializable("sent_transaction_hash", sentTransaction.getHash());
  }

  private void restoreInstanceState(final Bundle savedInstanceState)
  {
    state = (State) savedInstanceState.getSerializable("state");
    if (savedInstanceState.containsKey("wallet_to_sweep"))
      walletToSweep = WalletUtils.walletFromByteArray(savedInstanceState.getByteArray("wallet_to_sweep"));
    if (savedInstanceState.containsKey("sent_transaction_hash"))
    {
      sentTransaction = application.getWallet().getTransaction((Sha256Hash) savedInstanceState.getSerializable("sent_transaction_hash"));
      sentTransaction.getConfidence().addEventListener(sentTransactionConfidenceListener);
    }
  }

  @Override
  public void onActivityResult(final int requestCode, final int resultCode, final Intent intent)
  {
    if (requestCode == REQUEST_CODE_SCAN)
    {
      if (resultCode == Activity.RESULT_OK)
      {
        final String input = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT);

        new StringInputParser(input)
        {
          @Override
                    protected void handlePrivateKey(@Nonnull final VersionedChecksummedBytes key)
          {
                        privateKeyToSweep = key;
            state = State.DECODE_KEY;
            maybeDecodeKey();
          }

          @Override
          protected void handlePaymentIntent(final PaymentIntent paymentIntent)
          {
            cannotClassify(input);
          }

          @Override
          protected void handleDirectTransaction(final Transaction transaction) throws VerificationException
          {
            cannotClassify(input);
          }

          @Override
          protected void error(final int messageResId, final Object... messageArgs)
          {
            dialog(activity, null, R.string.button_scan, messageResId, messageArgs);
          }
        }.parse();
      }
    }

    updateView();
  }

  @Override
  public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater)
  {
    inflater.inflate(R.menu.sweep_wallet_fragment_options, menu);

    reloadAction = menu.findItem(R.id.sweep_wallet_options_reload);
    scanAction = menu.findItem(R.id.sweep_wallet_options_scan);

    final PackageManager pm = activity.getPackageManager();
    scanAction.setVisible(pm.hasSystemFeature(PackageManager.FEATURE_CAMERA) || pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT));

    super.onCreateOptionsMenu(menu, inflater);
  }

  @Override
  public boolean onOptionsItemSelected(final MenuItem item)
  {
    switch (item.getItemId())
    {
      case R.id.sweep_wallet_options_reload:
        handleReload();
        return true;

      case R.id.sweep_wallet_options_scan:
        handleScan();
        return true;
    }

    return super.onOptionsItemSelected(item);
  }

  private void handleReload()
  {
    if (walletToSweep == null)
      return;

    requestWalletBalance();
  }

  private void handleScan()
  {
    startActivityForResult(new Intent(activity, ScanActivity.class), REQUEST_CODE_SCAN);
  }

  private final TransactionConfidence.Listener sentTransactionConfidenceListener = new TransactionConfidence.Listener()
  {
    @Override
    public void onConfidenceChanged(final Transaction tx, final TransactionConfidence.Listener.ChangeReason reason)
    {
      activity.runOnUiThread(new Runnable()
      {
        @Override
        public void run()
        {
          if (!isResumed())
            return;

          sweepTransactionListAdapter.notifyDataSetChanged();

          final TransactionConfidence confidence = sentTransaction.getConfidence();
          final TransactionConfidence.ConfidenceType confidenceType = confidence.getConfidenceType();
          final int numBroadcastPeers = confidence.numBroadcastPeers();

          if (state == State.SENDING)
          {
            if (confidenceType == TransactionConfidence.ConfidenceType.DEAD)
              state = State.FAILED;
            else if (numBroadcastPeers > 1 || confidenceType == TransactionConfidence.ConfidenceType.BUILDING)
              state = State.SENT;

            updateView();
          }

          if (reason == ChangeReason.SEEN_PEERS && confidenceType == TransactionConfidence.ConfidenceType.PENDING)
          {
            // play sound effect
            final int soundResId = getResources().getIdentifier("send_coins_broadcast_" + numBroadcastPeers, "raw",
                                BuildConfig.APPLICATION_ID);
            if (soundResId > 0)
              RingtoneManager.getRingtone(activity, Uri.parse("android.resource://" + BuildConfig.APPLICATION_ID + "/" + soundResId))
                  .play();
          }
        }
      });
    }
  };

    private final Runnable maybeDecodeKeyRunnable = new Runnable()
    {
        @Override
        public void run()
        {
            maybeDecodeKey();
        }
    };

    private void maybeDecodeKey()
    {
        checkState(state == State.DECODE_KEY);
        checkState(privateKeyToSweep != null);

        if (privateKeyToSweep instanceof DumpedPrivateKey)
        {
            final ECKey key = ((DumpedPrivateKey) privateKeyToSweep).getKey();
            askConfirmSweep(key);
        }
        else if (privateKeyToSweep instanceof BIP38PrivateKey)
        {
            badPasswordView.setVisibility(View.INVISIBLE);

            final String password = passwordView.getText().toString().trim();
            passwordView.setText(null); // TODO get rid of it asap

            if (!password.isEmpty())
            {
                ProgressDialogFragment.showProgress(fragmentManager, getString(R.string.sweep_wallet_fragment_decrypt_progress));

                new DecodePrivateKeyTask(backgroundHandler)
                {
                    @Override
                    protected void onSuccess(@Nonnull ECKey decryptedKey)
                    {
                        log.info("successfully decoded BIP38 private key");

                        ProgressDialogFragment.dismissProgress(fragmentManager);

                        askConfirmSweep(decryptedKey);
                    }

                    @Override
                    protected void onBadPassphrase()
                    {
                        log.info("failed decoding BIP38 private key (bad password)");

                        ProgressDialogFragment.dismissProgress(fragmentManager);

                        badPasswordView.setVisibility(View.VISIBLE);
                        passwordView.requestFocus();
                    }
                }.decodePrivateKey((BIP38PrivateKey) privateKeyToSweep, password);
            }
        }
        else
        {
            throw new IllegalStateException("cannot handle type: " + privateKeyToSweep.getClass().getName());
        }
    }

    private void askConfirmSweep(final ECKey key)
  {
    // create non-HD wallet
    final KeyChainGroup group = new KeyChainGroup(Constants.NETWORK_PARAMETERS);
    group.importKeys(key);
    walletToSweep = new Wallet(Constants.NETWORK_PARAMETERS, group);

        state = State.CONFIRM_SWEEP;

        // delay until fragment is resumed
        handler.post(requestWalletBalanceRunnable);
  }

    private final Runnable requestWalletBalanceRunnable = new Runnable()
  {
    @Override
    public void run()
    {
      requestWalletBalance();
    }
  };

  private void requestWalletBalance()
  {
    ProgressDialogFragment.showProgress(fragmentManager, getString(R.string.sweep_wallet_fragment_request_wallet_balance_progress));

    final RequestWalletBalanceTask.ResultCallback callback = new RequestWalletBalanceTask.ResultCallback()
    {
      @Override
      public void onResult(final Collection<Transaction> transactions)
      {
        ProgressDialogFragment.dismissProgress(fragmentManager);

        walletToSweep.clearTransactions(0);
        for (final Transaction transaction : transactions)
          walletToSweep.addWalletTransaction(new WalletTransaction(Pool.UNSPENT, transaction));

        updateView();
      }

      @Override
      public void onFail(final int messageResId, final Object... messageArgs)
      {
        ProgressDialogFragment.dismissProgress(fragmentManager);

        final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.sweep_wallet_fragment_request_wallet_balance_failed_title);
        dialog.setMessage(getString(messageResId, messageArgs));
        dialog.setPositiveButton(R.string.button_retry, new DialogInterface.OnClickListener()
        {
          @Override
          public void onClick(final DialogInterface dialog, final int which)
          {
            requestWalletBalance();
          }
        });
        dialog.setNegativeButton(R.string.button_dismiss, null);
        dialog.show();
      }
    };

    final Address address = walletToSweep.getImportedKeys().iterator().next().toAddress(Constants.NETWORK_PARAMETERS);
    new RequestWalletBalanceTask(backgroundHandler, callback, application.httpUserAgent()).requestWalletBalance(address);
  }

  private void updateView()
  {
    final MonetaryFormat btcFormat = config.getFormat();

    if (walletToSweep != null)
    {
      balanceView.setVisibility(View.VISIBLE);
      final MonetarySpannable balanceSpannable = new MonetarySpannable(btcFormat, walletToSweep.getBalance(BalanceType.ESTIMATED));
      balanceSpannable.applyMarkup(null, null, null);
      final SpannableStringBuilder balance = new SpannableStringBuilder(balanceSpannable);
      balance.insert(0, ": ");
      balance.insert(0, getString(R.string.sweep_wallet_fragment_balance));
      balanceView.setText(balance);
    }
    else
    {
      balanceView.setVisibility(View.GONE);
    }

        if (state == State.DECODE_KEY && privateKeyToSweep == null)
        {
            messageView.setVisibility(View.VISIBLE);
            messageView.setText(R.string.sweep_wallet_fragment_wallet_unknown);
        }
        else if (state == State.DECODE_KEY && privateKeyToSweep != null)
        {
            messageView.setVisibility(View.VISIBLE);
            messageView.setText(R.string.sweep_wallet_fragment_encrypted);
        }
        else if (privateKeyToSweep != null)
        {
            messageView.setVisibility(View.GONE);
        }

        passwordViewGroup.setVisibility(state == State.DECODE_KEY && privateKeyToSweep != null ? View.VISIBLE : View.GONE);

        hintView.setVisibility(state == State.DECODE_KEY && privateKeyToSweep == null ? View.VISIBLE : View.GONE);

    if (sentTransaction != null)
    {
      sweepTransactionView.setVisibility(View.VISIBLE);
      sweepTransactionListAdapter.setFormat(btcFormat);
      sweepTransactionListAdapter.replace(sentTransaction);
    }
    else
    {
      sweepTransactionView.setVisibility(View.GONE);
      sweepTransactionListAdapter.clear();
    }

        if (state == State.DECODE_KEY)
    {
      viewCancel.setText(R.string.button_cancel);
      viewGo.setText(R.string.sweep_wallet_fragment_button_decrypt);
      viewGo.setEnabled(privateKeyToSweep != null);
    }
    else if (state == State.CONFIRM_SWEEP)
    {
      viewCancel.setText(R.string.button_cancel);
      viewGo.setText(R.string.sweep_wallet_fragment_button_sweep);
            viewGo.setEnabled(walletToSweep != null && walletToSweep.getBalance(BalanceType.ESTIMATED).signum() > 0);
    }
    else if (state == State.PREPARATION)
    {
      viewCancel.setText(R.string.button_cancel);
      viewGo.setText(R.string.send_coins_preparation_msg);
            viewGo.setEnabled(false);
    }
    else if (state == State.SENDING)
    {
      viewCancel.setText(R.string.send_coins_fragment_button_back);
      viewGo.setText(R.string.send_coins_sending_msg);
            viewGo.setEnabled(false);
    }
    else if (state == State.SENT)
    {
      viewCancel.setText(R.string.send_coins_fragment_button_back);
      viewGo.setText(R.string.send_coins_sent_msg);
            viewGo.setEnabled(false);
    }
    else if (state == State.FAILED)
    {
      viewCancel.setText(R.string.send_coins_fragment_button_back);
      viewGo.setText(R.string.send_coins_failed_msg);
            viewGo.setEnabled(false);
    }

    viewCancel.setEnabled(state != State.PREPARATION);

    // enable actions
    if (reloadAction != null)
            reloadAction.setEnabled(state == State.CONFIRM_SWEEP && walletToSweep != null);
    if (scanAction != null)
            scanAction.setEnabled(state == State.DECODE_KEY || state == State.CONFIRM_SWEEP);
    }

    private void handleDecrypt()
    {
        handler.post(maybeDecodeKeyRunnable);
  }

  private void handleSweep()
  {
    state = State.PREPARATION;
    updateView();

    final SendRequest sendRequest = SendRequest.emptyWallet(application.getWallet().freshReceiveAddress());

    new SendCoinsOfflineTask(walletToSweep, backgroundHandler)
    {
      @Override
      protected void onSuccess(final Transaction transaction)
      {
        sentTransaction = transaction;

        state = State.SENDING;
        updateView();

        sentTransaction.getConfidence().addEventListener(sentTransactionConfidenceListener);

        application.processDirectTransaction(sentTransaction);
      }

      @Override
      protected void onInsufficientMoney(@Nullable final Coin missing)
      {
        state = State.FAILED;
        updateView();

        final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.sweep_wallet_fragment_insufficient_money_title);
        dialog.setMessage(R.string.sweep_wallet_fragment_insufficient_money_msg);
        dialog.setNeutralButton(R.string.button_dismiss, null);
        dialog.show();
      }

      @Override
      protected void onFailure(final Exception exception)
      {
        state = State.FAILED;
        updateView();

        final DialogBuilder dialog = DialogBuilder.warn(activity, R.string.send_coins_error_msg);
        dialog.setMessage(exception.toString());
        dialog.setNeutralButton(R.string.button_dismiss, null);
        dialog.show();
      }

      @Override
      protected void onInvalidKey()
      {
        throw new RuntimeException(); // cannot happen
      }
    }.sendCoinsOffline(sendRequest); // send asynchronously
  }
}




Java Source Code List

de.schildbach.wallet.AddressBookProvider.java
de.schildbach.wallet.Configuration.java
de.schildbach.wallet.Constants.java
de.schildbach.wallet.ExchangeRatesProvider.java
de.schildbach.wallet.FileAttachmentProvider.java
de.schildbach.wallet.WalletApplication.java
de.schildbach.wallet.WalletBalanceWidgetProvider.java
de.schildbach.wallet.camera.CameraManager.java
de.schildbach.wallet.data.PaymentIntent.java
de.schildbach.wallet.integration.android.BitcoinIntegration.java
de.schildbach.wallet.offline.AcceptBluetoothService.java
de.schildbach.wallet.offline.AcceptBluetoothThread.java
de.schildbach.wallet.offline.DirectPaymentTask.java
de.schildbach.wallet.service.AutosyncReceiver.java
de.schildbach.wallet.service.BlockchainServiceImpl.java
de.schildbach.wallet.service.BlockchainService.java
de.schildbach.wallet.service.BlockchainStateLoader.java
de.schildbach.wallet.service.BlockchainState.java
de.schildbach.wallet.service.UpgradeWalletService.java
de.schildbach.wallet.ui.AbstractBindServiceActivity.java
de.schildbach.wallet.ui.AbstractWalletActivity.java
de.schildbach.wallet.ui.AddressAndLabel.java
de.schildbach.wallet.ui.AddressBookActivity.java
de.schildbach.wallet.ui.BlockListFragment.java
de.schildbach.wallet.ui.CurrencyAmountView.java
de.schildbach.wallet.ui.CurrencyCalculatorLink.java
de.schildbach.wallet.ui.CurrencySymbolDrawable.java
de.schildbach.wallet.ui.CurrencyTextView.java
de.schildbach.wallet.ui.DialogBuilder.java
de.schildbach.wallet.ui.EditAddressBookEntryFragment.java
de.schildbach.wallet.ui.EncryptKeysDialogFragment.java
de.schildbach.wallet.ui.ExchangeRateLoader.java
de.schildbach.wallet.ui.ExchangeRatesActivity.java
de.schildbach.wallet.ui.ExchangeRatesFragment.java
de.schildbach.wallet.ui.FancyListFragment.java
de.schildbach.wallet.ui.FileAdapter.java
de.schildbach.wallet.ui.HelpDialogFragment.java
de.schildbach.wallet.ui.ImportDialogButtonEnablerListener.java
de.schildbach.wallet.ui.InputParser.java
de.schildbach.wallet.ui.MaybeMaintenanceFragment.java
de.schildbach.wallet.ui.NetworkMonitorActivity.java
de.schildbach.wallet.ui.PeerListFragment.java
de.schildbach.wallet.ui.ProgressDialogFragment.java
de.schildbach.wallet.ui.ReportIssueDialogBuilder.java
de.schildbach.wallet.ui.RequestCoinsActivity.java
de.schildbach.wallet.ui.RequestCoinsFragment.java
de.schildbach.wallet.ui.RestoreWalletActivity.java
de.schildbach.wallet.ui.ScanActivity.java
de.schildbach.wallet.ui.ScannerView.java
de.schildbach.wallet.ui.SendCoinsQrActivity.java
de.schildbach.wallet.ui.SendingAddressesFragment.java
de.schildbach.wallet.ui.ShowPasswordCheckListener.java
de.schildbach.wallet.ui.TransactionsListAdapter.java
de.schildbach.wallet.ui.TransactionsListFragment.java
de.schildbach.wallet.ui.WalletActionsFragment.java
de.schildbach.wallet.ui.WalletActivity.java
de.schildbach.wallet.ui.WalletAddressFragment.java
de.schildbach.wallet.ui.WalletAddressesAdapter.java
de.schildbach.wallet.ui.WalletAddressesFragment.java
de.schildbach.wallet.ui.WalletBalanceFragment.java
de.schildbach.wallet.ui.WalletBalanceLoader.java
de.schildbach.wallet.ui.WalletDisclaimerFragment.java
de.schildbach.wallet.ui.WalletTransactionsFragment.java
de.schildbach.wallet.ui.preference.AboutFragment.java
de.schildbach.wallet.ui.preference.DiagnosticsFragment.java
de.schildbach.wallet.ui.preference.PreferenceActivity.java
de.schildbach.wallet.ui.preference.SettingsFragment.java
de.schildbach.wallet.ui.send.DecodePrivateKeyTask.java
de.schildbach.wallet.ui.send.DeriveKeyTask.java
de.schildbach.wallet.ui.send.MaintenanceDialogFragment.java
de.schildbach.wallet.ui.send.RequestPaymentRequestTask.java
de.schildbach.wallet.ui.send.RequestWalletBalanceTask.java
de.schildbach.wallet.ui.send.SendCoinsActivity.java
de.schildbach.wallet.ui.send.SendCoinsFragment.java
de.schildbach.wallet.ui.send.SendCoinsOfflineTask.java
de.schildbach.wallet.ui.send.SweepWalletActivity.java
de.schildbach.wallet.ui.send.SweepWalletFragment.java
de.schildbach.wallet.util.Base43.java
de.schildbach.wallet.util.BitmapFragment.java
de.schildbach.wallet.util.Bluetooth.java
de.schildbach.wallet.util.CircularProgressView.java
de.schildbach.wallet.util.CrashReporter.java
de.schildbach.wallet.util.Crypto.java
de.schildbach.wallet.util.Formats.java
de.schildbach.wallet.util.GenericUtils.java
de.schildbach.wallet.util.HttpGetThread.java
de.schildbach.wallet.util.Io.java
de.schildbach.wallet.util.Iso8601Format.java
de.schildbach.wallet.util.LinuxSecureRandom.java
de.schildbach.wallet.util.MonetarySpannable.java
de.schildbach.wallet.util.Nfc.java
de.schildbach.wallet.util.Qr.java
de.schildbach.wallet.util.ThrottlingWalletChangeListener.java
de.schildbach.wallet.util.ViewPagerTabs.java
de.schildbach.wallet.util.WalletUtils.java
de.schildbach.wallet.util.WholeStringBuilder.java