/*
* Copyright 2011-2013 the original author or authors.
*
* 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.digitalcoin.ui;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.MenuItem;
import com.google.digitalcoin.core.ProtocolException;
import com.google.digitalcoin.core.Sha256Hash;
import com.google.digitalcoin.core.Transaction;
import com.google.digitalcoin.core.VerificationException;
import com.google.digitalcoin.core.Wallet;
import de.schildbach.wallet.digitalcoin.Constants;
import de.schildbach.wallet.digitalcoin.WalletApplication;
import de.schildbach.wallet.digitalcoin.util.Base43;
import de.schildbach.wallet.digitalcoin.util.NfcTools;
import de.schildbach.wallet.digitalcoin.R;
/**
* @author Andreas Schildbach
*/
public final class TransactionActivity extends AbstractWalletActivity
{
public static final String INTENT_EXTRA_TRANSACTION_HASH = "transaction_hash";
private static final String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; // API level 10
private Object nfcManager;
private Transaction tx;
public static void show(final Context context, final Transaction tx)
{
final Intent intent = new Intent(context, TransactionActivity.class);
intent.putExtra(TransactionActivity.INTENT_EXTRA_TRANSACTION_HASH, tx.getHash());
context.startActivity(intent);
}
@SuppressLint("InlinedApi")
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
nfcManager = getSystemService(Context.NFC_SERVICE);
setContentView(R.layout.transaction_content);
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
handleIntent(getIntent());
}
@Override
protected void onResume()
{
super.onResume();
updateView();
}
@Override
public void onPause()
{
if (nfcManager != null)
NfcTools.unpublish(nfcManager, this);
super.onPause();
}
private void handleIntent(final Intent intent)
{
final Uri intentUri = intent.getData();
final String scheme = intentUri != null ? intentUri.getScheme() : null;
if (intent.hasExtra(INTENT_EXTRA_TRANSACTION_HASH))
{
final Wallet wallet = ((WalletApplication) getApplication()).getWallet();
tx = wallet.getTransaction((Sha256Hash) intent.getSerializableExtra(INTENT_EXTRA_TRANSACTION_HASH));
}
else if (intentUri != null && "ltctx".equals(scheme))
{
try
{
// decode transaction URI
final String part = intentUri.getSchemeSpecificPart();
final boolean useCompression = part.charAt(0) == 'Z';
final byte[] bytes = Base43.decode(part.substring(1));
InputStream is = new ByteArrayInputStream(bytes);
if (useCompression)
is = new GZIPInputStream(is);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final byte[] buf = new byte[4096];
int read;
while (-1 != (read = is.read(buf)))
baos.write(buf, 0, read);
baos.close();
is.close();
tx = new Transaction(Constants.NETWORK_PARAMETERS, baos.toByteArray());
processPendingTransaction(tx);
}
catch (final IOException x)
{
throw new RuntimeException(x);
}
catch (final ProtocolException x)
{
throw new RuntimeException(x);
}
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1 && Constants.MIMETYPE_TRANSACTION.equals(intent.getType()))
{
final Object ndefMessage = intent.getParcelableArrayExtra(EXTRA_NDEF_MESSAGES)[0];
final byte[] payload = NfcTools.extractMimePayload(Constants.MIMETYPE_TRANSACTION, ndefMessage);
try
{
tx = new Transaction(Constants.NETWORK_PARAMETERS, payload);
processPendingTransaction(tx);
}
catch (final ProtocolException x)
{
throw new RuntimeException(x);
}
}
if (tx == null)
throw new IllegalArgumentException("no tx");
}
@Override
public boolean onOptionsItemSelected(final MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateView()
{
final TransactionFragment transactionFragment = (TransactionFragment) getSupportFragmentManager().findFragmentById(R.id.transaction_fragment);
transactionFragment.update(tx);
if (nfcManager != null)
NfcTools.publishMimeObject(nfcManager, this, Constants.MIMETYPE_TRANSACTION, tx.unsafeDigitalcoinSerialize(), false);
}
private void processPendingTransaction(final Transaction tx)
{
final Wallet wallet = ((WalletApplication) getApplication()).getWallet();
try
{
if (wallet.isTransactionRelevant(tx))
// TODO dependent transactions
wallet.receivePending(tx, null);
}
catch (final VerificationException x)
{
throw new RuntimeException(x);
}
}
}