Android Open Source - bitfynd-wallet-android Maintenance Dialog 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.
 */*from  www . j a  v  a  2  s  . c om*/
 * 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 java.util.Collections;
import java.util.List;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.Wallet;
import org.bitcoinj.crypto.KeyCrypterException;
import org.bitcoinj.utils.MonetaryFormat;
import org.bitcoinj.wallet.DeterministicUpgradeRequiresPassword;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.crypto.params.KeyParameter;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.content.DialogInterface.OnShowListener;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.google.common.util.concurrent.ListenableFuture;

import de.schildbach.wallet.WalletApplication;
import de.schildbach.wallet.ui.AbstractWalletActivity;
import de.schildbach.wallet.ui.DialogBuilder;
import de.schildbach.wallet.R;

/**
 * @author Andreas Schildbach
 */
public class MaintenanceDialogFragment extends DialogFragment
{
  private static final String FRAGMENT_TAG = MaintenanceDialogFragment.class.getName();

  public static void show(final FragmentManager fm)
  {
    Fragment fragment = fm.findFragmentByTag(FRAGMENT_TAG);
    if (fragment == null)
    {
      fragment = new MaintenanceDialogFragment();
      fm.beginTransaction().add(fragment, FRAGMENT_TAG).commit();
    }
  }

  private AbstractWalletActivity activity;
  private WalletApplication application;
  private Wallet wallet;

  @CheckForNull
  private AlertDialog dialog;

  private View passwordGroup;
  private EditText passwordView;
  private View badPasswordView;
  private Button positiveButton, negativeButton;

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

  private enum State
  {
    INPUT, DECRYPTING, DONE
  }

  private State state = State.INPUT;

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

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

    this.activity = (AbstractWalletActivity) activity;
    this.application = (WalletApplication) activity.getApplication();
    this.wallet = application.getWallet();
  }

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

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

  @Override
  public Dialog onCreateDialog(final Bundle savedInstanceState)
  {
    final View view = LayoutInflater.from(activity).inflate(R.layout.maintenance_dialog, null);

    Coin value = Coin.ZERO;
    Coin fee = Coin.ZERO;
    for (final Transaction tx : determineMaintenanceTransactions())
    {
      value = value.add(tx.getValueSentFromMe(wallet));
      fee = fee.add(tx.getFee());
    }
    final TextView messageView = (TextView) view.findViewById(R.id.maintenance_dialog_message);
    final MonetaryFormat format = application.getConfiguration().getFormat();
    messageView.setText(getString(R.string.maintenance_dialog_message, format.format(value), format.format(fee)));

    passwordGroup = view.findViewById(R.id.maintenance_dialog_password_group);

    passwordView = (EditText) view.findViewById(R.id.maintenance_dialog_password);
    passwordView.setText(null);

    badPasswordView = view.findViewById(R.id.maintenance_dialog_bad_password);

    final DialogBuilder builder = new DialogBuilder(activity);
    builder.setTitle(R.string.maintenance_dialog_title);
    builder.setView(view);
    builder.setPositiveButton(R.string.maintenance_dialog_button_move, null); // dummy, just to make it show
    builder.setNegativeButton(R.string.button_dismiss, null);
    builder.setCancelable(false);

    final AlertDialog dialog = builder.create();
    dialog.setCanceledOnTouchOutside(false);

    dialog.setOnShowListener(new OnShowListener()
    {
      @Override
      public void onShow(final DialogInterface d)
      {
        positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
        negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);

        positiveButton.setTypeface(Typeface.DEFAULT_BOLD);
        positiveButton.setOnClickListener(new OnClickListener()
        {
          @Override
          public void onClick(final View v)
          {
            log.info("user decided to do maintenance");
            handleGo();
          }
        });
        negativeButton.setOnClickListener(new OnClickListener()
        {
          @Override
          public void onClick(final View v)
          {
            log.info("user decided to dismiss");
            dismiss();
          }
        });

        passwordView.addTextChangedListener(textWatcher);

        MaintenanceDialogFragment.this.dialog = dialog;
        updateView();
      }
    });

    log.info("showing maintenance dialog");

    return dialog;
  }

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

    updateView();
  }

  @Override
  public void onDismiss(final DialogInterface dialog)
  {
    wipePasswords();

    this.dialog = null;

    super.onDismiss(dialog);
  }

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

    super.onDestroy();
  }

  private void handleGo()
  {
    state = State.DECRYPTING;
    updateView();

    if (wallet.isEncrypted())
    {
      new DeriveKeyTask(backgroundHandler)
      {
        @Override
        protected void onSuccess(@Nonnull KeyParameter encryptionKey)
        {
          doMaintenance(encryptionKey);
        }
      }.deriveKey(wallet.getKeyCrypter(), passwordView.getText().toString().trim());

      updateView();
    }
    else
    {
      doMaintenance(null);
    }
  }

  private void doMaintenance(final KeyParameter encryptionKey)
  {
    backgroundHandler.post(new Runnable()
    {
      @Override
      public void run()
      {
        try
        {
          wallet.doMaintenance(encryptionKey, true);

          handler.post(new Runnable()
          {
            @Override
            public void run()
            {
              state = State.DONE;
              updateView();

              delayedDismiss();
            }
          });
        }
        catch (final KeyCrypterException x)
        {
          handler.post(new Runnable()
          {
            @Override
            public void run()
            {
              badPasswordView.setVisibility(View.VISIBLE);

              state = State.INPUT;
              updateView();

              passwordView.requestFocus();

              log.info("bad spending password");
            }
          });
        }
      }
    });
  }

  private void delayedDismiss()
  {
    handler.postDelayed(new Runnable()
    {
      @Override
      public void run()
      {
        dismiss();
      }
    }, 2000);
  }

  private void wipePasswords()
  {
    passwordView.setText(null);
  }

  private void updateView()
  {
    if (dialog == null)
      return;

    passwordGroup.setVisibility(wallet.isEncrypted() ? View.VISIBLE : View.GONE);

    if (state == State.INPUT)
    {
      positiveButton.setText(R.string.maintenance_dialog_button_move);
      positiveButton.setEnabled(true);
      negativeButton.setEnabled(true);
    }
    else if (state == State.DECRYPTING)
    {
      positiveButton.setText(R.string.maintenance_dialog_state_decrypting);
      positiveButton.setEnabled(false);
      negativeButton.setEnabled(false);
    }
    else if (state == State.DONE)
    {
      positiveButton.setText(R.string.maintenance_dialog_state_done);
      positiveButton.setEnabled(false);
      negativeButton.setEnabled(false);
    }
  }

  private List<Transaction> determineMaintenanceTransactions()
  {
    try
    {
      final ListenableFuture<List<Transaction>> result = wallet.doMaintenance(null, false);
      return result.get();
    }
    catch (final DeterministicUpgradeRequiresPassword x)
    {
      return Collections.emptyList();
    }
    catch (final Exception x)
    {
      throw new RuntimeException(x);
    }
  }

  private final TextWatcher textWatcher = new TextWatcher()
  {
    @Override
    public void onTextChanged(final CharSequence s, final int start, final int before, final int count)
    {
      badPasswordView.setVisibility(View.INVISIBLE);
      updateView();
    }

    @Override
    public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after)
    {
    }

    @Override
    public void afterTextChanged(final Editable s)
    {
    }
  };
}




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