Updated on 2026-08-14
This commit is contained in:
parent
5ac02ecf5b
commit
bc0a1a8b48
30 changed files with 604 additions and 1825 deletions
|
|
@ -41,17 +41,15 @@
|
|||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.MainActivity"
|
||||
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
<data
|
||||
android:host="www.tangem.com"
|
||||
android:scheme="http"/>
|
||||
|
|
@ -64,75 +62,73 @@
|
|||
android:name="android.nfc.action.TECH_DISCOVERED"
|
||||
android:resource="@xml/nfc_tech_filter"/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.RequestPINActivity"
|
||||
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.EmptyWalletActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.SelectBlockchainActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.SavePINActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.CardInfoActivity"
|
||||
android:label="@string/title_activity_card_info"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.LoadedWalletActivity"
|
||||
android:label="@string/title_activity_loaded_wallet"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.VerifyCardActivity"
|
||||
android:label="@string/title_activity_loaded_wallet"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.CreateNewWalletActivity"
|
||||
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.PreparePaymentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.ConfirmPaymentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.SignPaymentActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.PurgeActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.SwapPINActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.QRScanActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.SendTransactionActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<activity
|
||||
android:name="com.tangem.presentation.activity.SettingsFeatureActivity"
|
||||
android:label="@string/title_activity_settings_feature">
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,90 +0,0 @@
|
|||
package com.tangem.presentation.activity
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.preference.PreferenceActivity
|
||||
import android.support.annotation.LayoutRes
|
||||
import android.support.v7.app.ActionBar
|
||||
import android.support.v7.app.AppCompatDelegate
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.MenuInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
||||
/**
|
||||
* A [android.preference.PreferenceActivity] which implements and proxies the necessary calls
|
||||
* to be used with AppCompat.
|
||||
*/
|
||||
abstract class AppCompatPreferenceActivity : PreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
delegate.installViewFactory()
|
||||
delegate.onCreate(savedInstanceState)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onPostCreate(savedInstanceState: Bundle?) {
|
||||
super.onPostCreate(savedInstanceState)
|
||||
delegate.onPostCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
val supportActionBar: ActionBar?
|
||||
get() = delegate.supportActionBar
|
||||
|
||||
fun setSupportActionBar(toolbar: Toolbar?) {
|
||||
delegate.setSupportActionBar(toolbar)
|
||||
}
|
||||
|
||||
override fun getMenuInflater(): MenuInflater {
|
||||
return delegate.menuInflater
|
||||
}
|
||||
|
||||
override fun setContentView(@LayoutRes layoutResID: Int) {
|
||||
delegate.setContentView(layoutResID)
|
||||
}
|
||||
|
||||
override fun setContentView(view: View) {
|
||||
delegate.setContentView(view)
|
||||
}
|
||||
|
||||
override fun setContentView(view: View, params: ViewGroup.LayoutParams) {
|
||||
delegate.setContentView(view, params)
|
||||
}
|
||||
|
||||
override fun addContentView(view: View, params: ViewGroup.LayoutParams) {
|
||||
delegate.addContentView(view, params)
|
||||
}
|
||||
|
||||
override fun onPostResume() {
|
||||
super.onPostResume()
|
||||
delegate.onPostResume()
|
||||
}
|
||||
|
||||
override fun onTitleChanged(title: CharSequence, color: Int) {
|
||||
super.onTitleChanged(title, color)
|
||||
delegate.setTitle(title)
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
delegate.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
delegate.onStop()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
delegate.onDestroy()
|
||||
}
|
||||
|
||||
override fun invalidateOptionsMenu() {
|
||||
delegate.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
private val delegate: AppCompatDelegate by lazy {
|
||||
AppCompatDelegate.create(this, null)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
package com.tangem.presentation.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.presentation.fragment.WalletInfo;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
public class CardInfoActivity extends AppCompatActivity implements WalletInfo.OnFragmentInteractionListener {
|
||||
|
||||
/**
|
||||
* The {@link android.support.v4.view.PagerAdapter} that will provide
|
||||
* fragments for each of the sections. We use a
|
||||
* {@link FragmentPagerAdapter} derivative, which will keep every
|
||||
* loaded fragment in memory. If this becomes too memory intensive, it
|
||||
* may be best to switch to a
|
||||
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
|
||||
*/
|
||||
private SectionsPagerAdapter mSectionsPagerAdapter;
|
||||
|
||||
/**
|
||||
* The {@link ViewPager} that will host the section contents.
|
||||
*/
|
||||
private ViewPager mViewPager;
|
||||
|
||||
|
||||
private TangemCard mCard;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_card_info);
|
||||
|
||||
// Create the adapter that will return a fragment for each of the three
|
||||
// primary sections of the activity.
|
||||
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
|
||||
|
||||
// Set up the ViewPager with the sections adapter.
|
||||
mViewPager = findViewById(R.id.container);
|
||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||
|
||||
TabLayout tabLayout = findViewById(R.id.tabs);
|
||||
tabLayout.setupWithViewPager(mViewPager);
|
||||
|
||||
String UID = getIntent().getStringExtra("UID");
|
||||
mCard = new TangemCard(UID);
|
||||
mCard.LoadFromBundle(getIntent().getBundleExtra("Card"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_card_info, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
if (id == R.id.action_settings) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
|
||||
* one of the sections/tabs/pages.
|
||||
*/
|
||||
public class SectionsPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
public SectionsPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
// getItem is called to instantiate the fragment for the given page.
|
||||
// Return a PlaceholderFragment (defined as a static inner class below).
|
||||
if (position == 0) {
|
||||
return WalletInfo.newInstance(mCard);
|
||||
} /*else if (position == 1) {
|
||||
return WalletUnspentFragment.newInstance(mCard);
|
||||
} else if (position == 2) {
|
||||
return WalletHistoryFragment.newInstance(mCard);
|
||||
}*/
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
// Show 3 total pages.
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
return "Wallet info";
|
||||
case 1:
|
||||
return "Unspent";
|
||||
case 2:
|
||||
return "History";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,24 +23,24 @@ import android.widget.TextView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.data.network.request.ElectrumRequest;
|
||||
import com.tangem.data.network.request.FeeRequest;
|
||||
import com.tangem.data.network.request.InfuraRequest;
|
||||
import com.tangem.data.network.task.ElectrumTask;
|
||||
import com.tangem.data.network.task.FeeTask;
|
||||
import com.tangem.data.network.task.InfuraTask;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.util.BTCUtils;
|
||||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
||||
import com.tangem.util.DerEncodingUtil;
|
||||
import com.tangem.data.network.task.ElectrumTask;
|
||||
import com.tangem.data.network.request.FeeRequest;
|
||||
import com.tangem.data.network.task.FeeTask;
|
||||
import com.tangem.util.FormatUtil;
|
||||
import com.tangem.data.network.request.InfuraRequest;
|
||||
import com.tangem.data.network.task.InfuraTask;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.domain.wallet.SharedData;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.domain.wallet.Transaction;
|
||||
import com.tangem.domain.wallet.UnspentOutputInfo;
|
||||
import com.tangem.util.BTCUtils;
|
||||
import com.tangem.util.DerEncodingUtil;
|
||||
import com.tangem.util.FormatUtil;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
||||
|
|
@ -57,392 +57,31 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
|
||||
private static final int REQUEST_CODE_SIGN_PAYMENT = 1;
|
||||
private static final int REQUEST_CODE_REQUEST_PIN2 = 2;
|
||||
Button btnSend;
|
||||
boolean feeRequestSuccess = false;
|
||||
boolean balanceRequestSuccess = false;
|
||||
EditText etWallet;
|
||||
TextView tvCardID, tvBalance, tvCurrency, tvCurrency2, tvBalanceEquivalent, tvAmountEquivalent, tvFeeEquivalent;
|
||||
EditText etAmount;
|
||||
EditText etFee;
|
||||
ImageView ivCamera;
|
||||
TangemCard mCard;
|
||||
RadioGroup rgFee;
|
||||
String minFee = null, maxFee = null, normalFee = null;
|
||||
Long minFeeInInternalUnits = 0L;
|
||||
private Button btnSend;
|
||||
private boolean feeRequestSuccess = false;
|
||||
private boolean balanceRequestSuccess = false;
|
||||
private EditText etWallet;
|
||||
private TextView tvAmountEquivalent;
|
||||
private TextView tvFeeEquivalent;
|
||||
private EditText etAmount;
|
||||
private EditText etFee;
|
||||
private ImageView ivCamera;
|
||||
private TangemCard mCard;
|
||||
private RadioGroup rgFee;
|
||||
private String minFee = null, maxFee = null, normalFee = null;
|
||||
private Long minFeeInInternalUnits = 0L;
|
||||
private NfcManager mNfcManager;
|
||||
int requestPIN2Count = 0;
|
||||
ProgressBar progressBar;
|
||||
boolean nodeCheck = false;
|
||||
Date dtVerifyed = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_confirm_payment);
|
||||
|
||||
MainActivity.commonInit(getApplicationContext());
|
||||
mNfcManager = new NfcManager(this, this);
|
||||
|
||||
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
|
||||
btnSend = findViewById(R.id.btnSend);
|
||||
etWallet = findViewById(R.id.etWallet);
|
||||
tvCardID = findViewById(R.id.tvCardID);
|
||||
tvBalance = findViewById(R.id.tvBalance);
|
||||
tvCurrency = findViewById(R.id.tvCurrency);
|
||||
tvCurrency2 = findViewById(R.id.tvCurrency2);
|
||||
etAmount = findViewById(R.id.etAmount);
|
||||
etFee = findViewById(R.id.etFee);
|
||||
tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
|
||||
tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent);
|
||||
|
||||
tvFeeEquivalent = findViewById(R.id.tvFeeEquivalent);
|
||||
ivCamera = findViewById(R.id.ivCamera);
|
||||
|
||||
rgFee = findViewById(R.id.rgFee);
|
||||
rgFee.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||
doSetFee(checkedId);
|
||||
}
|
||||
});
|
||||
|
||||
etAmount.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
try {
|
||||
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
tvAmountEquivalent.setText(engine.GetAmountEqualentDescriptor(mCard, etAmount.getText().toString()));
|
||||
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
|
||||
tvAmountEquivalent.setError("Service unavailable");
|
||||
} else {
|
||||
tvAmountEquivalent.setError(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tvAmountEquivalent.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
etFee.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
try {
|
||||
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
String eqFee = engine.EvaluteFeeEquivalent(mCard, etFee.getText().toString());
|
||||
tvFeeEquivalent.setText(eqFee);
|
||||
|
||||
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
|
||||
tvFeeEquivalent.setError("Service unavailable");
|
||||
} else {
|
||||
tvFeeEquivalent.setError(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tvFeeEquivalent.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
//tvBalance.setText(engine.GetBalanceWithAlter(mCard));
|
||||
if (mCard.getBlockchain() == Blockchain.Token) {
|
||||
Spanned html = Html.fromHtml(engine.GetBalanceWithAlter(mCard));
|
||||
tvBalance.setText(html);
|
||||
} else {
|
||||
tvBalance.setText(engine.GetBalanceWithAlter(mCard));
|
||||
}
|
||||
etAmount.setText(getIntent().getStringExtra("Amount"));
|
||||
tvCurrency.setText(engine.GetBalanceCurrency(mCard));
|
||||
tvCurrency2.setText(engine.GetFeeCurrency());
|
||||
|
||||
tvCardID.setText(mCard.getCIDDescription());
|
||||
|
||||
//tvBalanceEquivalent.setText(mCard.getBalanceEquivalentDescription());
|
||||
tvBalanceEquivalent.setText(engine.GetBalanceEquivalent(mCard));
|
||||
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
|
||||
tvBalanceEquivalent.setError("Service unavailable");
|
||||
} else {
|
||||
tvBalanceEquivalent.setError(null);
|
||||
}
|
||||
|
||||
etWallet.setText(getIntent().getStringExtra("Wallet"));
|
||||
|
||||
etFee.setText("?");
|
||||
|
||||
btnSend.setVisibility(View.INVISIBLE);
|
||||
feeRequestSuccess = false;
|
||||
balanceRequestSuccess = false;
|
||||
btnSend.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.MINUTE, -1);
|
||||
|
||||
if (dtVerifyed == null || dtVerifyed.before(calendar.getTime())) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "The obtained data is outdated! Try again");
|
||||
return;
|
||||
}
|
||||
|
||||
CoinEngine engineCoin = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
|
||||
if (engineCoin.IsNeedCheckNode() && !nodeCheck) {
|
||||
Toast.makeText(getBaseContext(), "Cannot reach current active blockchain node. Try again", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
String txFee = etFee.getText().toString();
|
||||
String txAmount = etAmount.getText().toString();
|
||||
|
||||
|
||||
if (!engineCoin.HasBalanceInfo(mCard)) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "Cannot check balance! No connection with blockchain nodes");
|
||||
return;
|
||||
} else if (!engineCoin.IsBalanceNotZero(mCard)) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "The wallet is empty");
|
||||
return;
|
||||
} else if (!engineCoin.CheckUnspentTransaction(mCard)) {
|
||||
//else if (mCard.getUnspentTransactions().size() == 0 && mCard.getBlockchain() != Blockchain.Ethereum) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "Please wait for confirmation of incoming transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!engineCoin.CheckAmountValie(mCard, txAmount, txFee, minFeeInInternalUnits)) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "Fee exceeds payment amount. Enter correct value and repeat sending.");
|
||||
return;
|
||||
}
|
||||
|
||||
requestPIN2Count = 0;
|
||||
Intent intent = new Intent(getBaseContext(), RequestPINActivity.class);
|
||||
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2);
|
||||
}
|
||||
});
|
||||
|
||||
if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) {
|
||||
ETHRequestTask task = new ETHRequestTask(mCard.getBlockchain());
|
||||
InfuraRequest req = InfuraRequest.GetGasPrise(mCard.getWallet());
|
||||
req.setID(67);
|
||||
req.setBlockchain(mCard.getBlockchain());
|
||||
rgFee.setEnabled(false);
|
||||
task.execute(req);
|
||||
} else {
|
||||
|
||||
rgFee.setEnabled(true);
|
||||
|
||||
SharedData data = new SharedData(SharedData.COUNT_REQUEST);
|
||||
|
||||
CoinEngine engineCoin = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
|
||||
for (int i = 0; i < data.allRequest; ++i) {
|
||||
|
||||
String nodeAddress = engineCoin.GetNextNode(mCard);
|
||||
int nodePort = engineCoin.GetNextNodePort(mCard);
|
||||
//ConnectTask connectTaskEx = new ConnectTask(Blockchain.getNextServiceHost(mCard), Blockchain.getNextServicePort(mCard), data);
|
||||
ConnectTask connectTaskEx = new ConnectTask(nodeAddress, nodePort, data);
|
||||
|
||||
//connectTaskEx.execute(ElectrumRequest.CheckBalance(mCard.getWallet()));
|
||||
connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet()));
|
||||
}
|
||||
|
||||
String nodeAddress = engineCoin.GetNode(mCard);
|
||||
int nodePort = engineCoin.GetNodePort(mCard);
|
||||
ConnectTask connectTask = new ConnectTask(nodeAddress, nodePort, data);
|
||||
|
||||
//ConnectTask connectTask = new ConnectTask(Blockchain.getServiceHost(mCard), Blockchain.getServicePort(mCard));
|
||||
|
||||
connectTask.execute(/*ElectrumRequest.CheckBalance(mCard.getWallet()), */ElectrumRequest.GetFee(mCard.getWallet()));
|
||||
|
||||
int calcSize = 256;
|
||||
try {
|
||||
calcSize = BuildSize(etWallet.getText().toString(), "0.00", etAmount.getText().toString());
|
||||
} catch (Exception ex) {
|
||||
Log.e("Build Fee error", ex.getMessage());
|
||||
}
|
||||
|
||||
SharedData sharedFee = new SharedData(SharedData.COUNT_REQUEST);
|
||||
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
for (int i = 0; i < SharedData.COUNT_REQUEST; ++i) {
|
||||
|
||||
ConnectFeeTask feeTask = new ConnectFeeTask(sharedFee);
|
||||
|
||||
feeTask.execute(FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.NORMAL),
|
||||
FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.MINIMAL),
|
||||
FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.PRIORITY));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("message", "Operation canceled");
|
||||
setResult(Activity.RESULT_CANCELED, intent);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_CODE_SIGN_PAYMENT) {
|
||||
if (data != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) {
|
||||
TangemCard updatedCard = new TangemCard(data.getStringExtra("UID"));
|
||||
updatedCard.LoadFromBundle(data.getBundleExtra("Card"));
|
||||
mCard = updatedCard;
|
||||
}
|
||||
if (resultCode == SignPaymentActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
|
||||
requestPIN2Count++;
|
||||
Intent intent = new Intent(getBaseContext(), RequestPINActivity.class);
|
||||
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2);
|
||||
return;
|
||||
}
|
||||
setResult(resultCode, data);
|
||||
finish();
|
||||
} else if (requestCode == REQUEST_CODE_REQUEST_PIN2) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Intent intent = new Intent(getBaseContext(), SignPaymentActivity.class);
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
intent.putExtra("Wallet", etWallet.getText().toString());
|
||||
intent.putExtra("Amount", etAmount.getText().toString());
|
||||
intent.putExtra("Fee", etFee.getText().toString());
|
||||
startActivityForResult(intent, REQUEST_CODE_SIGN_PAYMENT);
|
||||
} else {
|
||||
Toast.makeText(getBaseContext(), "PIN2 is required to sign the payment", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FinishActivityWithError(int errorCode, String message) {
|
||||
//Snackbar.make(etFee, message, Snackbar.LENGTH_LONG).show();
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("message", message);
|
||||
setResult(errorCode, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTagDiscovered(Tag tag) {
|
||||
try {
|
||||
Log.w(getClass().getName(), "Ignore discovered tag!");
|
||||
mNfcManager.ignoreTag(tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int BuildSize(String outputAddress, String outFee, String outAmount) throws Exception {
|
||||
String myAddress = mCard.getWallet();
|
||||
String changeAddress = myAddress; //"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi";
|
||||
byte[] pbKey = mCard.getWalletPublicKey();
|
||||
byte[] pbComprKey = mCard.getWalletPublicKeyRar();
|
||||
|
||||
// Build script for our address
|
||||
List<TangemCard.UnspentTransaction> rawTxList = mCard.getUnspentTransactions();
|
||||
byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes;
|
||||
|
||||
// Collect unspent
|
||||
ArrayList<UnspentOutputInfo> unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend);
|
||||
|
||||
long fullAmount = 0;
|
||||
for (int i = 0; i < unspentOutputs.size(); ++i) {
|
||||
fullAmount += unspentOutputs.get(i).value;
|
||||
}
|
||||
|
||||
// Get first unspent
|
||||
UnspentOutputInfo outPut = unspentOutputs.get(0);
|
||||
int outPutIndex = outPut.outputIndex;
|
||||
|
||||
// get prev TX id;
|
||||
String prevTXID = rawTxList.get(0).txID;//"f67b838d6e2c0c587f476f583843e93ff20368eaf96a798bdc25e01f53f8f5d2";
|
||||
|
||||
long fees = FormatUtil.ConvertStringToLong(outFee);
|
||||
long amount = FormatUtil.ConvertStringToLong(outAmount);
|
||||
amount = amount - fees;
|
||||
|
||||
long change = fullAmount - fees - amount;
|
||||
|
||||
if (amount + fees > fullAmount) {
|
||||
throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount));
|
||||
}
|
||||
|
||||
byte[][] hashesForSign = new byte[unspentOutputs.size()][];
|
||||
|
||||
for (int i = 0; i < unspentOutputs.size(); ++i) {
|
||||
byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change);
|
||||
|
||||
byte[] hashData = Util.calculateSHA256(newTX);
|
||||
byte[] doubleHashData = Util.calculateSHA256(hashData);
|
||||
|
||||
Log.e("TX_BODY_1", BTCUtils.toHex(newTX));
|
||||
Log.e("TX_HASH_1", BTCUtils.toHex(hashData));
|
||||
Log.e("TX_HASH_2", BTCUtils.toHex(doubleHashData));
|
||||
|
||||
unspentOutputs.get(i).bodyDoubleHash = doubleHashData;
|
||||
unspentOutputs.get(i).bodyHash = hashData;
|
||||
|
||||
hashesForSign[i] = doubleHashData;
|
||||
}
|
||||
|
||||
byte[] signFromCard = new byte[64 * unspentOutputs.size()];
|
||||
|
||||
for (int i = 0; i < unspentOutputs.size(); ++i) {
|
||||
BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64));
|
||||
BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64));
|
||||
byte[] encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey);
|
||||
unspentOutputs.get(i).scriptForBuild = encodingSign;
|
||||
}
|
||||
|
||||
byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change);
|
||||
|
||||
return realTX.length;
|
||||
}
|
||||
private int requestPIN2Count = 0;
|
||||
private ProgressBar progressBar;
|
||||
private boolean nodeCheck = false;
|
||||
private Date dtVerifyed = null;
|
||||
|
||||
private class ConnectTask extends ElectrumTask {
|
||||
public ConnectTask(String host, int port) {
|
||||
super(host, port);
|
||||
}
|
||||
|
||||
public ConnectTask(String host, int port, SharedData sharedData) {
|
||||
ConnectTask(String host, int port, SharedData sharedData) {
|
||||
super(host, port, sharedData);
|
||||
}
|
||||
|
||||
|
|
@ -588,7 +227,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
}
|
||||
|
||||
private class ConnectFeeTask extends FeeTask {
|
||||
public ConnectFeeTask(SharedData sharedData) {
|
||||
ConnectFeeTask(SharedData sharedData) {
|
||||
super(sharedData);
|
||||
}
|
||||
|
||||
|
|
@ -598,9 +237,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
for (FeeRequest request : requests) {
|
||||
if (request.error == null) {
|
||||
long minFeeRate = 0;
|
||||
|
||||
try {
|
||||
|
||||
try {
|
||||
String tmpAnswer = request.getAsString();
|
||||
BigDecimal minFeeBD = new BigDecimal(tmpAnswer);
|
||||
|
|
@ -696,20 +333,219 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
}
|
||||
}
|
||||
|
||||
private void doSetFee(int checkedRadioButtonId) {
|
||||
switch (checkedRadioButtonId) {
|
||||
case R.id.rbMinimalFee:
|
||||
if (minFee != null) etFee.setText(minFee);
|
||||
else etFee.setText("?");
|
||||
break;
|
||||
case R.id.rbNormalFee:
|
||||
if (normalFee != null) etFee.setText(normalFee);
|
||||
else etFee.setText("?");
|
||||
break;
|
||||
case R.id.rbMaximumFee:
|
||||
if (maxFee != null) etFee.setText(maxFee);
|
||||
else etFee.setText("?");
|
||||
break;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_confirm_payment);
|
||||
|
||||
MainActivity.commonInit(getApplicationContext());
|
||||
mNfcManager = new NfcManager(this, this);
|
||||
|
||||
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
btnSend = findViewById(R.id.btnSend);
|
||||
etWallet = findViewById(R.id.etWallet);
|
||||
TextView tvCardID = findViewById(R.id.tvCardID);
|
||||
TextView tvBalance = findViewById(R.id.tvBalance);
|
||||
TextView tvCurrency = findViewById(R.id.tvCurrency);
|
||||
TextView tvCurrency2 = findViewById(R.id.tvCurrency2);
|
||||
etAmount = findViewById(R.id.etAmount);
|
||||
etFee = findViewById(R.id.etFee);
|
||||
TextView tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
|
||||
tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent);
|
||||
tvFeeEquivalent = findViewById(R.id.tvFeeEquivalent);
|
||||
ivCamera = findViewById(R.id.ivCamera);
|
||||
rgFee = findViewById(R.id.rgFee);
|
||||
|
||||
rgFee.setOnCheckedChangeListener((group, checkedId) -> doSetFee(checkedId));
|
||||
|
||||
etAmount.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
try {
|
||||
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
tvAmountEquivalent.setText(engine.GetAmountEqualentDescriptor(mCard, etAmount.getText().toString()));
|
||||
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
|
||||
tvAmountEquivalent.setError("Service unavailable");
|
||||
} else {
|
||||
tvAmountEquivalent.setError(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tvAmountEquivalent.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
etFee.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
try {
|
||||
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
String eqFee = engine.EvaluteFeeEquivalent(mCard, etFee.getText().toString());
|
||||
tvFeeEquivalent.setText(eqFee);
|
||||
|
||||
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
|
||||
tvFeeEquivalent.setError("Service unavailable");
|
||||
} else {
|
||||
tvFeeEquivalent.setError(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
tvFeeEquivalent.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
//tvBalance.setText(engine.GetBalanceWithAlter(mCard));
|
||||
if (mCard.getBlockchain() == Blockchain.Token) {
|
||||
Spanned html = Html.fromHtml(engine.GetBalanceWithAlter(mCard));
|
||||
tvBalance.setText(html);
|
||||
} else {
|
||||
tvBalance.setText(engine.GetBalanceWithAlter(mCard));
|
||||
}
|
||||
etAmount.setText(getIntent().getStringExtra("Amount"));
|
||||
tvCurrency.setText(engine.GetBalanceCurrency(mCard));
|
||||
tvCurrency2.setText(engine.GetFeeCurrency());
|
||||
|
||||
tvCardID.setText(mCard.getCIDDescription());
|
||||
|
||||
//tvBalanceEquivalent.setText(mCard.getBalanceEquivalentDescription());
|
||||
tvBalanceEquivalent.setText(engine.GetBalanceEquivalent(mCard));
|
||||
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
|
||||
tvBalanceEquivalent.setError("Service unavailable");
|
||||
} else {
|
||||
tvBalanceEquivalent.setError(null);
|
||||
}
|
||||
|
||||
etWallet.setText(getIntent().getStringExtra("Wallet"));
|
||||
|
||||
etFee.setText("?");
|
||||
|
||||
btnSend.setVisibility(View.INVISIBLE);
|
||||
feeRequestSuccess = false;
|
||||
balanceRequestSuccess = false;
|
||||
btnSend.setOnClickListener(v -> {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.MINUTE, -1);
|
||||
|
||||
if (dtVerifyed == null || dtVerifyed.before(calendar.getTime())) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "The obtained data is outdated! Try again");
|
||||
return;
|
||||
}
|
||||
|
||||
CoinEngine engineCoin = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
|
||||
if (engineCoin.IsNeedCheckNode() && !nodeCheck) {
|
||||
Toast.makeText(getBaseContext(), "Cannot reach current active blockchain node. Try again", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
String txFee = etFee.getText().toString();
|
||||
String txAmount = etAmount.getText().toString();
|
||||
|
||||
|
||||
if (!engineCoin.HasBalanceInfo(mCard)) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "Cannot check balance! No connection with blockchain nodes");
|
||||
return;
|
||||
} else if (!engineCoin.IsBalanceNotZero(mCard)) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "The wallet is empty");
|
||||
return;
|
||||
} else if (!engineCoin.CheckUnspentTransaction(mCard)) {
|
||||
//else if (mCard.getUnspentTransactions().size() == 0 && mCard.getBlockchain() != Blockchain.Ethereum) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "Please wait for confirmation of incoming transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!engineCoin.CheckAmountValie(mCard, txAmount, txFee, minFeeInInternalUnits)) {
|
||||
FinishActivityWithError(Activity.RESULT_CANCELED, "Fee exceeds payment amount. Enter correct value and repeat sending.");
|
||||
return;
|
||||
}
|
||||
|
||||
requestPIN2Count = 0;
|
||||
Intent intent = new Intent(getBaseContext(), RequestPINActivity.class);
|
||||
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2);
|
||||
});
|
||||
|
||||
if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) {
|
||||
ETHRequestTask task = new ETHRequestTask(mCard.getBlockchain());
|
||||
InfuraRequest req = InfuraRequest.GetGasPrise(mCard.getWallet());
|
||||
req.setID(67);
|
||||
req.setBlockchain(mCard.getBlockchain());
|
||||
rgFee.setEnabled(false);
|
||||
task.execute(req);
|
||||
|
||||
} else {
|
||||
rgFee.setEnabled(true);
|
||||
|
||||
SharedData data = new SharedData(SharedData.COUNT_REQUEST);
|
||||
|
||||
CoinEngine engineCoin = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
|
||||
for (int i = 0; i < data.allRequest; ++i) {
|
||||
|
||||
String nodeAddress = engineCoin.GetNextNode(mCard);
|
||||
int nodePort = engineCoin.GetNextNodePort(mCard);
|
||||
//ConnectTask connectTaskEx = new ConnectTask(Blockchain.getNextServiceHost(mCard), Blockchain.getNextServicePort(mCard), data);
|
||||
ConnectTask connectTaskEx = new ConnectTask(nodeAddress, nodePort, data);
|
||||
|
||||
//connectTaskEx.execute(ElectrumRequest.CheckBalance(mCard.getWallet()));
|
||||
connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet()));
|
||||
}
|
||||
|
||||
String nodeAddress = engineCoin.GetNode(mCard);
|
||||
int nodePort = engineCoin.GetNodePort(mCard);
|
||||
ConnectTask connectTask = new ConnectTask(nodeAddress, nodePort, data);
|
||||
|
||||
//ConnectTask connectTask = new ConnectTask(Blockchain.getServiceHost(mCard), Blockchain.getServicePort(mCard));
|
||||
|
||||
connectTask.execute(/*ElectrumRequest.CheckBalance(mCard.getWallet()), */ElectrumRequest.GetFee(mCard.getWallet()));
|
||||
|
||||
int calcSize = 256;
|
||||
try {
|
||||
calcSize = BuildSize(etWallet.getText().toString(), "0.00", etAmount.getText().toString());
|
||||
} catch (Exception ex) {
|
||||
Log.e("Build Fee error", ex.getMessage());
|
||||
}
|
||||
|
||||
SharedData sharedFee = new SharedData(SharedData.COUNT_REQUEST);
|
||||
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
for (int i = 0; i < SharedData.COUNT_REQUEST; ++i) {
|
||||
|
||||
ConnectFeeTask feeTask = new ConnectFeeTask(sharedFee);
|
||||
|
||||
feeTask.execute(FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.NORMAL),
|
||||
FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.MINIMAL),
|
||||
FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.PRIORITY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -730,4 +566,155 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
super.onStop();
|
||||
mNfcManager.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == REQUEST_CODE_SIGN_PAYMENT) {
|
||||
if (data != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) {
|
||||
TangemCard updatedCard = new TangemCard(data.getStringExtra("UID"));
|
||||
updatedCard.LoadFromBundle(data.getBundleExtra("Card"));
|
||||
mCard = updatedCard;
|
||||
}
|
||||
if (resultCode == SignPaymentActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
|
||||
requestPIN2Count++;
|
||||
Intent intent = new Intent(getBaseContext(), RequestPINActivity.class);
|
||||
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2);
|
||||
return;
|
||||
}
|
||||
setResult(resultCode, data);
|
||||
finish();
|
||||
} else if (requestCode == REQUEST_CODE_REQUEST_PIN2) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Intent intent = new Intent(getBaseContext(), SignPaymentActivity.class);
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
intent.putExtra("Wallet", etWallet.getText().toString());
|
||||
intent.putExtra("Amount", etAmount.getText().toString());
|
||||
intent.putExtra("Fee", etFee.getText().toString());
|
||||
startActivityForResult(intent, REQUEST_CODE_SIGN_PAYMENT);
|
||||
} else {
|
||||
Toast.makeText(getBaseContext(), "PIN2 is required to sign the payment", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BACK:
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("message", "Operation canceled");
|
||||
setResult(Activity.RESULT_CANCELED, intent);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
void FinishActivityWithError(int errorCode, String message) {
|
||||
//Snackbar.make(etFee, message, Snackbar.LENGTH_LONG).show();
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("message", message);
|
||||
setResult(errorCode, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTagDiscovered(Tag tag) {
|
||||
try {
|
||||
Log.w(getClass().getName(), "Ignore discovered tag!");
|
||||
mNfcManager.ignoreTag(tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int BuildSize(String outputAddress, String outFee, String outAmount) throws Exception {
|
||||
String myAddress = mCard.getWallet();
|
||||
String changeAddress = myAddress; //"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi";
|
||||
byte[] pbKey = mCard.getWalletPublicKey();
|
||||
byte[] pbComprKey = mCard.getWalletPublicKeyRar();
|
||||
|
||||
// Build script for our address
|
||||
List<TangemCard.UnspentTransaction> rawTxList = mCard.getUnspentTransactions();
|
||||
byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes;
|
||||
|
||||
// Collect unspent
|
||||
ArrayList<UnspentOutputInfo> unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend);
|
||||
|
||||
long fullAmount = 0;
|
||||
for (int i = 0; i < unspentOutputs.size(); ++i) {
|
||||
fullAmount += unspentOutputs.get(i).value;
|
||||
}
|
||||
|
||||
// Get first unspent
|
||||
UnspentOutputInfo outPut = unspentOutputs.get(0);
|
||||
int outPutIndex = outPut.outputIndex;
|
||||
|
||||
// get prev TX id;
|
||||
String prevTXID = rawTxList.get(0).txID;//"f67b838d6e2c0c587f476f583843e93ff20368eaf96a798bdc25e01f53f8f5d2";
|
||||
|
||||
long fees = FormatUtil.ConvertStringToLong(outFee);
|
||||
long amount = FormatUtil.ConvertStringToLong(outAmount);
|
||||
amount = amount - fees;
|
||||
|
||||
long change = fullAmount - fees - amount;
|
||||
|
||||
if (amount + fees > fullAmount) {
|
||||
throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount));
|
||||
}
|
||||
|
||||
byte[][] hashesForSign = new byte[unspentOutputs.size()][];
|
||||
|
||||
for (int i = 0; i < unspentOutputs.size(); ++i) {
|
||||
byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change);
|
||||
|
||||
byte[] hashData = Util.calculateSHA256(newTX);
|
||||
byte[] doubleHashData = Util.calculateSHA256(hashData);
|
||||
|
||||
Log.e("TX_BODY_1", BTCUtils.toHex(newTX));
|
||||
Log.e("TX_HASH_1", BTCUtils.toHex(hashData));
|
||||
Log.e("TX_HASH_2", BTCUtils.toHex(doubleHashData));
|
||||
|
||||
unspentOutputs.get(i).bodyDoubleHash = doubleHashData;
|
||||
unspentOutputs.get(i).bodyHash = hashData;
|
||||
|
||||
hashesForSign[i] = doubleHashData;
|
||||
}
|
||||
|
||||
byte[] signFromCard = new byte[64 * unspentOutputs.size()];
|
||||
|
||||
for (int i = 0; i < unspentOutputs.size(); ++i) {
|
||||
BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64));
|
||||
BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64));
|
||||
byte[] encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey);
|
||||
unspentOutputs.get(i).scriptForBuild = encodingSign;
|
||||
}
|
||||
|
||||
byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change);
|
||||
|
||||
return realTX.length;
|
||||
}
|
||||
|
||||
private void doSetFee(int checkedRadioButtonId) {
|
||||
switch (checkedRadioButtonId) {
|
||||
case R.id.rbMinimalFee:
|
||||
if (minFee != null) etFee.setText(minFee);
|
||||
else etFee.setText("?");
|
||||
break;
|
||||
case R.id.rbNormalFee:
|
||||
if (normalFee != null) etFee.setText(normalFee);
|
||||
else etFee.setText("?");
|
||||
break;
|
||||
case R.id.rbMaximumFee:
|
||||
if (maxFee != null) etFee.setText(maxFee);
|
||||
else etFee.setText("?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -25,100 +25,20 @@ import com.tangem.wallet.R;
|
|||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
|
||||
|
||||
public class CreateNewWalletActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications {
|
||||
public static final String TAG = CreateNewWalletActivity.class.getSimpleName();
|
||||
|
||||
public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER;
|
||||
private TangemCard mCard;
|
||||
private TextView tvCardID;
|
||||
private NfcManager mNfcManager;
|
||||
private static final String logTag = "CreateNewActivity";
|
||||
|
||||
private ProgressBar progressBar;
|
||||
private CreateNewWalletTask createNewWalletTask;
|
||||
private boolean lastReadSuccess = true;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_create_new_wallet);
|
||||
|
||||
MainActivity.commonInit(getApplicationContext());
|
||||
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||
|
||||
tvCardID = findViewById(R.id.tvCardID);
|
||||
tvCardID.setText(mCard.getCIDDescription());
|
||||
|
||||
mNfcManager = new NfcManager(this, this);
|
||||
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTagDiscovered(Tag tag) {
|
||||
try {
|
||||
// get IsoDep handle and run cardReader thread
|
||||
final IsoDep isoDep = IsoDep.get(tag);
|
||||
if (isoDep == null) {
|
||||
throw new CardProtocol.TangemException(getString(R.string.wrong_tag_err));
|
||||
}
|
||||
byte UID[] = tag.getId();
|
||||
String sUID = Util.byteArrayToHexString(UID);
|
||||
Log.v(logTag, "UID: " + sUID);
|
||||
|
||||
if (sUID.equals(mCard.getUID())) {
|
||||
if (lastReadSuccess) {
|
||||
isoDep.setTimeout(mCard.getPauseBeforePIN2() + 5000);
|
||||
} else {
|
||||
isoDep.setTimeout(mCard.getPauseBeforePIN2() + 65000);
|
||||
}
|
||||
createNewWalletTask = new CreateNewWalletTask(isoDep, this);
|
||||
createNewWalletTask.start();
|
||||
} else {
|
||||
Log.d(logTag, "Mismatch card UID (" + sUID + " instead of " + mCard.getUID() + ")");
|
||||
mNfcManager.ignoreTag(isoDep.getTag());
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mNfcManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mNfcManager.onPause();
|
||||
if (createNewWalletTask != null) {
|
||||
createNewWalletTask.cancel(true);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
// dismiss enable NFC dialog
|
||||
mNfcManager.onStop();
|
||||
if (createNewWalletTask != null) {
|
||||
createNewWalletTask.cancel(true);
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Dialog CreateNFCDialog(int id, AlertDialogWrapper.Builder builder, LayoutInflater li) {
|
||||
// return mNfcManager.ShowNFCEnableDialog(); //onCreateDialog(id, builder, li);
|
||||
// }
|
||||
|
||||
private class CreateNewWalletTask extends Thread {
|
||||
|
||||
IsoDep mIsoDep;
|
||||
CardProtocol.Notifications mNotifications;
|
||||
private IsoDep mIsoDep;
|
||||
private CardProtocol.Notifications mNotifications;
|
||||
private boolean isCancelled = false;
|
||||
|
||||
public CreateNewWalletTask(IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||
|
|
@ -198,13 +118,85 @@ public class CreateNewWalletActivity extends AppCompatActivity implements NfcAda
|
|||
|
||||
}
|
||||
|
||||
public void OnReadStart(CardProtocol cardProtocol) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
progressBar.setProgress(5);
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_create_new_wallet);
|
||||
|
||||
MainActivity.commonInit(getApplicationContext());
|
||||
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||
|
||||
TextView tvCardID = findViewById(R.id.tvCardID);
|
||||
tvCardID.setText(mCard.getCIDDescription());
|
||||
|
||||
mNfcManager = new NfcManager(this, this);
|
||||
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTagDiscovered(Tag tag) {
|
||||
try {
|
||||
// get IsoDep handle and run cardReader thread
|
||||
final IsoDep isoDep = IsoDep.get(tag);
|
||||
if (isoDep == null) {
|
||||
throw new CardProtocol.TangemException(getString(R.string.wrong_tag_err));
|
||||
}
|
||||
byte UID[] = tag.getId();
|
||||
String sUID = Util.byteArrayToHexString(UID);
|
||||
Log.v(TAG, "UID: " + sUID);
|
||||
|
||||
if (sUID.equals(mCard.getUID())) {
|
||||
if (lastReadSuccess) {
|
||||
isoDep.setTimeout(mCard.getPauseBeforePIN2() + 5000);
|
||||
} else {
|
||||
isoDep.setTimeout(mCard.getPauseBeforePIN2() + 65000);
|
||||
}
|
||||
createNewWalletTask = new CreateNewWalletTask(isoDep, this);
|
||||
createNewWalletTask.start();
|
||||
} else {
|
||||
Log.d(TAG, "Mismatch card UID (" + sUID + " instead of " + mCard.getUID() + ")");
|
||||
mNfcManager.ignoreTag(isoDep.getTag());
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mNfcManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mNfcManager.onPause();
|
||||
if (createNewWalletTask != null) {
|
||||
createNewWalletTask.cancel(true);
|
||||
}
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
// dismiss enable NFC dialog
|
||||
mNfcManager.onStop();
|
||||
if (createNewWalletTask != null) {
|
||||
createNewWalletTask.cancel(true);
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
public void OnReadStart(CardProtocol cardProtocol) {
|
||||
progressBar.post(() -> {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
progressBar.setProgress(5);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -214,104 +206,80 @@ public class CreateNewWalletActivity extends AppCompatActivity implements NfcAda
|
|||
|
||||
if (cardProtocol != null) {
|
||||
if (cardProtocol.getError() == null) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
||||
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
progressBar.post(() -> {
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
||||
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
finish();
|
||||
});
|
||||
} else {
|
||||
lastReadSuccess = false;
|
||||
if (cardProtocol.getError() instanceof CardProtocol.TangemException_InvalidPIN) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
||||
}
|
||||
progressBar.post(() -> {
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
||||
});
|
||||
progressBar.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("message", "Cannot create wallet. Make sure you enter correct PIN2!");
|
||||
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
||||
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
||||
setResult(RESULT_INVALID_PIN, intent);
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
progressBar.postDelayed(() -> {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("message", "Cannot create wallet. Make sure you enter correct PIN2!");
|
||||
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
||||
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
||||
setResult(RESULT_INVALID_PIN, intent);
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 500);
|
||||
return;
|
||||
} else {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) {
|
||||
if (!NoExtendedLengthSupportDialog.allreadyShowed) {
|
||||
new NoExtendedLengthSupportDialog().show(getFragmentManager(), "NoExtendedLengthSupportDialog");
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getBaseContext(), "Try to scan again", Toast.LENGTH_LONG).show();
|
||||
progressBar.post(() -> {
|
||||
if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) {
|
||||
if (!NoExtendedLengthSupportDialog.allreadyShowed) {
|
||||
new NoExtendedLengthSupportDialog().show(getFragmentManager(), NoExtendedLengthSupportDialog.TAG);
|
||||
}
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
||||
} else {
|
||||
Toast.makeText(getBaseContext(), R.string.try_to_scan_again, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progressBar.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
progressBar.postDelayed(() -> {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
public void OnReadProgress(CardProtocol protocol, final int progress) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setProgress(progress);
|
||||
}
|
||||
});
|
||||
progressBar.post(() -> progressBar.setProgress(progress));
|
||||
}
|
||||
|
||||
public void OnReadCancel() {
|
||||
|
||||
createNewWalletTask = null;
|
||||
|
||||
progressBar.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
progressBar.postDelayed(() -> {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
|
@ -330,5 +298,5 @@ public class CreateNewWalletActivity extends AppCompatActivity implements NfcAda
|
|||
public void OnReadAfterRequest() {
|
||||
WaitSecurityDelayDialog.onReadAfterRequest(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.presentation.activity;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NfcAdapter;
|
||||
|
|
@ -11,7 +12,6 @@ import android.text.Html;
|
|||
import android.text.Spanned;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
|
|
@ -21,26 +21,25 @@ import com.tangem.domain.cardReader.NfcManager;
|
|||
import com.tangem.domain.wallet.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
||||
import com.tangem.util.FormatUtil;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.util.FormatUtil;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PreparePaymentActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback {
|
||||
|
||||
private static final int REQUEST_CODE_SCAN_QR = 1;
|
||||
private static final int REQUEST_CODE_SEND_PAYMENT = 2;
|
||||
private Button btnVerify;
|
||||
private EditText etWallet;
|
||||
private EditText etAmount;
|
||||
private TextView tvCurrency;
|
||||
private TextView tvCardId, tvBalance, tvBalanceEquivalent, tvAmountEquivalent;
|
||||
private ImageView ivCamera;
|
||||
private TextView tvAmountEquivalent;
|
||||
boolean use_mCurrency;
|
||||
private TangemCard mCard;
|
||||
private NfcManager mNfcManager;
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
@ -53,14 +52,14 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||
|
||||
btnVerify = findViewById(R.id.btnVerify);
|
||||
Button btnVerify = findViewById(R.id.btnVerify);
|
||||
etWallet = findViewById(R.id.etWallet);
|
||||
etAmount = findViewById(R.id.etAmount);
|
||||
ivCamera = findViewById(R.id.ivCamera);
|
||||
tvCurrency = findViewById(R.id.tvCurrency);
|
||||
tvCardId = findViewById(R.id.tvCardID);
|
||||
tvBalance = findViewById(R.id.tvBalance);
|
||||
tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
|
||||
ImageView ivCamera = findViewById(R.id.ivCamera);
|
||||
TextView tvCurrency = findViewById(R.id.tvCurrency);
|
||||
TextView tvCardId = findViewById(R.id.tvCardID);
|
||||
TextView tvBalance = findViewById(R.id.tvBalance);
|
||||
TextView tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
|
||||
tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent);
|
||||
|
||||
tvCardId.setText(mCard.getCIDDescription());
|
||||
|
|
@ -135,49 +134,60 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
etAmount.setText(engine.GetBalanceValue(mCard));
|
||||
}
|
||||
|
||||
btnVerify.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String strAmount;
|
||||
strAmount = etAmount.getText().toString();
|
||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
try {
|
||||
if (!engine.CheckAmount(mCard, etAmount.getText().toString())) {
|
||||
etAmount.setError("Not enough funds on your card");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
etAmount.setError("Unknown amount format");
|
||||
return;
|
||||
btnVerify.setOnClickListener(v -> {
|
||||
String strAmount;
|
||||
strAmount = etAmount.getText().toString();
|
||||
CoinEngine engine1 = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||
try {
|
||||
if (!Objects.requireNonNull(engine1).CheckAmount(mCard, etAmount.getText().toString())) {
|
||||
etAmount.setError(getString(R.string.not_enough_funds_on_your_card));
|
||||
}
|
||||
|
||||
boolean checkAddress = engine.ValdateAddress(etWallet.getText().toString(), mCard);
|
||||
if (!checkAddress) {
|
||||
etWallet.setError("Incorrect destination wallet address");
|
||||
return;
|
||||
}
|
||||
|
||||
if (etWallet.getText().toString().equals(mCard.getWallet())) {
|
||||
etWallet.setError("Destination wallet address equal source address");
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(getBaseContext(), ConfirmPaymentActivity.class);
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
intent.putExtra("Wallet", etWallet.getText().toString());
|
||||
intent.putExtra("Amount", strAmount);
|
||||
startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT);
|
||||
} catch (Exception e) {
|
||||
etAmount.setError(getString(R.string.unknown_amount_format));
|
||||
return;
|
||||
}
|
||||
|
||||
boolean checkAddress = engine1.ValdateAddress(etWallet.getText().toString(), mCard);
|
||||
if (!checkAddress) {
|
||||
etWallet.setError(getString(R.string.incorrect_destination_wallet_address));
|
||||
return;
|
||||
}
|
||||
|
||||
if (etWallet.getText().toString().equals(mCard.getWallet())) {
|
||||
etWallet.setError(getString(R.string.destination_wallet_address_equal_source_address));
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(getBaseContext(), ConfirmPaymentActivity.class);
|
||||
intent.putExtra("UID", mCard.getUID());
|
||||
intent.putExtra("Card", mCard.getAsBundle());
|
||||
intent.putExtra("Wallet", etWallet.getText().toString());
|
||||
intent.putExtra("Amount", strAmount);
|
||||
startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT);
|
||||
});
|
||||
|
||||
ivCamera.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(getBaseContext(), QRScanActivity.class);
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN_QR);
|
||||
}
|
||||
ivCamera.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(getBaseContext(), QRScanActivity.class);
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN_QR);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mNfcManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mNfcManager.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mNfcManager.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -207,21 +217,4 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mNfcManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mNfcManager.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mNfcManager.onStop();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
package com.tangem.presentation.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
public class SelectBlockchainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_select_blockchain);
|
||||
|
||||
// Spinner spBlockchain = (Spinner) findViewById(R.id.spBlockchain);
|
||||
// ArrayAdapter<Blockchain> adapter = new ArrayAdapter<Blockchain>(this, android.R.layout.simple_spinner_item, Blockchain.values());
|
||||
// spBlockchain.setAdapter(adapter);
|
||||
// spBlockchain.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
// @Override
|
||||
// public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
// Intent intent = new Intent();
|
||||
// intent.putExtra("blockchain", Blockchain.values()[position].toString());
|
||||
// setResult(RESULT_OK, intent);
|
||||
// finish();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onNothingSelected(AdapterView<?> parent) {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
package com.tangem.presentation.activity
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.media.RingtoneManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.preference.*
|
||||
import android.text.TextUtils
|
||||
import android.view.MenuItem
|
||||
import com.tangem.wallet.R
|
||||
|
||||
/**
|
||||
* A [PreferenceActivity] that presents a set of application settings. On
|
||||
* handset devices, settings are presented as a single list. On tablets,
|
||||
* settings are split by category, with category headers shown to the left of
|
||||
* the list of settings.
|
||||
*
|
||||
* See [Android Design: Settings](http://developer.android.com/design/patterns/settings.html)
|
||||
* for design guidelines and the [Settings API Guide](http://developer.android.com/guide/topics/ui/settings.html)
|
||||
* for more information on developing a Settings UI.
|
||||
*/
|
||||
class SettingsFeatureActivity : AppCompatPreferenceActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setupActionBar()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the [android.app.ActionBar], if the API is available.
|
||||
*/
|
||||
private fun setupActionBar() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
override fun onIsMultiPane(): Boolean {
|
||||
return isXLargeTablet(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
override fun onBuildHeaders(target: List<PreferenceActivity.Header>) {
|
||||
loadHeadersFromResource(R.xml.pref_headers, target)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method stops fragment injection in malicious applications.
|
||||
* Make sure to deny any unknown fragments here.
|
||||
*/
|
||||
override fun isValidFragment(fragmentName: String): Boolean {
|
||||
return PreferenceFragment::class.java.name == fragmentName
|
||||
|| GeneralPreferenceFragment::class.java.name == fragmentName
|
||||
|| DataSyncPreferenceFragment::class.java.name == fragmentName
|
||||
|| NotificationPreferenceFragment::class.java.name == fragmentName
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows general preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
class GeneralPreferenceFragment : PreferenceFragment() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
addPreferencesFromResource(R.xml.pref_general)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
|
||||
// to their values. When their values change, their summaries are
|
||||
// updated to reflect the new value, per the Android Design
|
||||
// guidelines.
|
||||
bindPreferenceSummaryToValue(findPreference("example_text"))
|
||||
bindPreferenceSummaryToValue(findPreference("example_list"))
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val id = item.itemId
|
||||
if (id == android.R.id.home) {
|
||||
startActivity(Intent(activity, SettingsFeatureActivity::class.java))
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows notification preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
class NotificationPreferenceFragment : PreferenceFragment() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
addPreferencesFromResource(R.xml.pref_notification)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
|
||||
// to their values. When their values change, their summaries are
|
||||
// updated to reflect the new value, per the Android Design
|
||||
// guidelines.
|
||||
bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"))
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val id = item.itemId
|
||||
if (id == android.R.id.home) {
|
||||
startActivity(Intent(activity, SettingsFeatureActivity::class.java))
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This fragment shows data and sync preferences only. It is used when the
|
||||
* activity is showing a two-pane settings UI.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
class DataSyncPreferenceFragment : PreferenceFragment() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
addPreferencesFromResource(R.xml.pref_data_sync)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
// Bind the summaries of EditText/List/Dialog/Ringtone preferences
|
||||
// to their values. When their values change, their summaries are
|
||||
// updated to reflect the new value, per the Android Design
|
||||
// guidelines.
|
||||
bindPreferenceSummaryToValue(findPreference("sync_frequency"))
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val id = item.itemId
|
||||
if (id == android.R.id.home) {
|
||||
startActivity(Intent(activity, SettingsFeatureActivity::class.java))
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* A preference value change listener that updates the preference's summary
|
||||
* to reflect its new value.
|
||||
*/
|
||||
private val sBindPreferenceSummaryToValueListener = Preference.OnPreferenceChangeListener { preference, value ->
|
||||
val stringValue = value.toString()
|
||||
|
||||
if (preference is ListPreference) {
|
||||
// For list preferences, look up the correct display value in
|
||||
// the preference's 'entries' list.
|
||||
val listPreference = preference
|
||||
val index = listPreference.findIndexOfValue(stringValue)
|
||||
|
||||
// Set the summary to reflect the new value.
|
||||
preference.setSummary(
|
||||
if (index >= 0)
|
||||
listPreference.entries[index]
|
||||
else
|
||||
null)
|
||||
|
||||
} else if (preference is RingtonePreference) {
|
||||
// For ringtone preferences, look up the correct display value
|
||||
// using RingtoneManager.
|
||||
if (TextUtils.isEmpty(stringValue)) {
|
||||
// Empty values correspond to 'silent' (no ringtone).
|
||||
preference.setSummary(R.string.pref_ringtone_silent)
|
||||
|
||||
} else {
|
||||
val ringtone = RingtoneManager.getRingtone(
|
||||
preference.getContext(), Uri.parse(stringValue))
|
||||
|
||||
if (ringtone == null) {
|
||||
// Clear the summary if there was a lookup error.
|
||||
preference.setSummary(null)
|
||||
} else {
|
||||
// Set the summary to reflect the new ringtone display
|
||||
// name.
|
||||
val name = ringtone.getTitle(preference.getContext())
|
||||
preference.setSummary(name)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// For all other preferences, set the summary to the value's
|
||||
// simple string representation.
|
||||
preference.summary = stringValue
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to determine if the device has an extra-large screen. For
|
||||
* example, 10" tablets are extra-large.
|
||||
*/
|
||||
private fun isXLargeTablet(context: Context): Boolean {
|
||||
return context.resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK >= Configuration.SCREENLAYOUT_SIZE_XLARGE
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds a preference's summary to its value. More specifically, when the
|
||||
* preference's value is changed, its summary (line of text below the
|
||||
* preference title) is updated to reflect the value. The summary is also
|
||||
* immediately updated upon calling this method. The exact display format is
|
||||
* dependent on the type of preference.
|
||||
|
||||
* @see .sBindPreferenceSummaryToValueListener
|
||||
*/
|
||||
private fun bindPreferenceSummaryToValue(preference: Preference) {
|
||||
// Set the listener to watch for value changes.
|
||||
preference.onPreferenceChangeListener = sBindPreferenceSummaryToValueListener
|
||||
|
||||
// Trigger the listener immediately with the preference's
|
||||
// current value.
|
||||
sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
|
||||
PreferenceManager
|
||||
.getDefaultSharedPreferences(preference.context)
|
||||
.getString(preference.key, ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
package com.tangem.presentation.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import static android.text.Html.FROM_HTML_MODE_COMPACT;
|
||||
|
||||
/**
|
||||
* Created by dvol on 17.07.2017.
|
||||
*/
|
||||
|
||||
public class CardUnspentListAdapter extends BaseAdapter {
|
||||
private LayoutInflater mLayoutInflater;
|
||||
private Context mContext;
|
||||
private TangemCard mCard;
|
||||
|
||||
public CardUnspentListAdapter(LayoutInflater layoutInflater, TangemCard card) {
|
||||
mLayoutInflater = layoutInflater;
|
||||
mContext = layoutInflater.getContext();
|
||||
mCard = card;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().get(i);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().get(i).txID.hashCode();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup viewGroup) {
|
||||
if (convertView == null) {
|
||||
convertView = mLayoutInflater.inflate(R.layout.item_list_card_unspent, viewGroup,
|
||||
false);
|
||||
}
|
||||
TextView tvItem = (TextView) convertView.findViewById(R.id.tvItem);
|
||||
|
||||
TangemCard.UnspentTransaction unspentTransaction = (TangemCard.UnspentTransaction) getItem(position);
|
||||
|
||||
String html = String.format("<b>%d mBTC</b><br>%s", unspentTransaction.Amount, unspentTransaction.txID);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
tvItem.setText(Html.fromHtml(html, FROM_HTML_MODE_COMPACT));
|
||||
} else {
|
||||
tvItem.setText(Html.fromHtml(html.toString()));
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
mCard.getUnspentTransactions().clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void UpdateUnspent(String tx_hash, int value, int height) {
|
||||
TangemCard.UnspentTransaction newUT = new TangemCard.UnspentTransaction();
|
||||
newUT.txID = tx_hash;
|
||||
newUT.Amount = value;
|
||||
newUT.Height = height;
|
||||
mCard.getUnspentTransactions().add(newUT);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
package com.tangem.presentation.fragment;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.domain.wallet.TangemCard;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Activities that contain this fragment must implement the
|
||||
* {@link OnFragmentInteractionListener} interface
|
||||
* to handle interaction events.
|
||||
* Use the {@link WalletInfo#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class WalletInfo extends Fragment {
|
||||
|
||||
// TODO: Rename and change types of parameters
|
||||
private TangemCard mCard;
|
||||
|
||||
private OnFragmentInteractionListener mListener;
|
||||
|
||||
public WalletInfo() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @return A new instance of fragment WalletInfo.
|
||||
*/
|
||||
// TODO: Rename and change types and number of parameters
|
||||
public static WalletInfo newInstance(TangemCard card) {
|
||||
WalletInfo fragment = new WalletInfo();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("UID",card.getUID());
|
||||
card.SaveToBundle(args);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mCard = new TangemCard(getArguments().getString("UID"));
|
||||
mCard.LoadFromBundle(getArguments());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View result=inflater.inflate(R.layout.fr_wallet_info, container, false);
|
||||
|
||||
ImageView mImage= (ImageView)result.findViewById(R.id.qrWallet);
|
||||
try {
|
||||
mImage.setImageBitmap(generateQrCode(mCard.getWallet()));
|
||||
} catch (WriterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
TextView mText=(TextView)result.findViewById(R.id.strWallet);
|
||||
mText.setText(mCard.getWallet());
|
||||
|
||||
mText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
TextView mText = (TextView) view;
|
||||
ClipboardManager clipboard = (ClipboardManager)getActivity().getSystemService(CLIPBOARD_SERVICE);
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(mText.getText(), mText.getText()));
|
||||
Toast.makeText(getContext(),"Copied to clipboard",Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Bitmap generateQrCode(String myCodeText) throws WriterException {
|
||||
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
|
||||
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // H = 30% damage
|
||||
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
|
||||
int size = 256;
|
||||
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(myCodeText, BarcodeFormat.QR_CODE, size, size, hintMap);
|
||||
int width = bitMatrix.getWidth();
|
||||
Bitmap bmp = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < width; y++) {
|
||||
bmp.setPixel(y, x, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof OnFragmentInteractionListener) {
|
||||
mListener = (OnFragmentInteractionListener) context;
|
||||
} else {
|
||||
throw new RuntimeException(context.toString()
|
||||
+ " must implement OnFragmentInteractionListener");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface must be implemented by activities that contain this
|
||||
* fragment to allow an interaction in this fragment to be communicated
|
||||
* to the activity and potentially other fragments contained in that
|
||||
* activity.
|
||||
* <p>
|
||||
* See the Android Training lesson <a href=
|
||||
* "http://developer.android.com/training/basics/fragments/communicating.html"
|
||||
* >Communicating with Other Fragments</a> for more information.
|
||||
*/
|
||||
public interface OnFragmentInteractionListener {
|
||||
// TODO: Update argument type and name
|
||||
// void onFragmentInteraction(Uri uri);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zm1,15h-2v-6h2v6zm0,-8h-2V7h2v2z"/>
|
||||
</vector>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M11.5,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zm6.5,-6v-5.5c0,-3.07 -2.13,-5.64 -5,-6.32V3.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,2.67 10,3.5v0.68c-2.87,0.68 -5,3.25 -5,6.32V16l-2,2v1h17v-1l-2,-2z"/>
|
||||
</vector>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01,-.25 1.97,-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0,-4.42,-3.58,-8,-8,-8zm0 14c-3.31 0,-6,-2.69,-6,-6 0,-1.01.25,-1.97.7,-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4,-4,-4,-4v3z"/>
|
||||
</vector>
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="com.tangem.presentation.activity.CardInfoActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/appbar_padding_top"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.tangem.presentation.activity.QRScanActivity">
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/rvBlockchain"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</android.support.v7.widget.RecyclerView>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context="com.tangem.wallet.WalletUnspentFragment">
|
||||
|
||||
<!-- TODO: Update blank fragment layout -->
|
||||
<ListView
|
||||
android:id="@+id/lvHistory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="8dp" />
|
||||
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fabRefresh"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@drawable/ic_search_gray" />
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.tangem.wallet.com.tangem.presentation.fragment.WalletInfoFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrWallet"
|
||||
android:layout_width="256dp"
|
||||
android:layout_height="256dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="83dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@color/cardview_light_background"
|
||||
tools:layout_editor_absoluteX="72dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/strWallet"
|
||||
android:layout_width="347dp"
|
||||
android:layout_height="39dp"
|
||||
android:layout_marginBottom="76dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:ems="10"
|
||||
android:inputType="none|textPersonName"
|
||||
android:singleLine="false"
|
||||
android:text="N/A"
|
||||
android:textAlignment="center"
|
||||
android:textSize="12dp"
|
||||
android:textStyle="bold"
|
||||
android:typeface="monospace"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.509"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/qrWallet"
|
||||
tools:layout_editor_absoluteX="2dp" />
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context="com.tangem.wallet.WalletUnspentFragment">
|
||||
|
||||
<!-- TODO: Update blank fragment layout -->
|
||||
<ListView
|
||||
android:id="@+id/lvUnspent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="8dp" />
|
||||
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fabRefresh"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@drawable/ic_search_gray" />
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal" android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgBlockchain"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:src="@drawable/ic_logo_small"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCurrency"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/text_size_large"
|
||||
android:fontFamily="@font/raleway_r"
|
||||
android:layout_margin="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="96dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvItem"
|
||||
style="@style/Base.TextAppearance.AppCompat.Small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:text="History"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/separator"
|
||||
style="@style/thin_separator"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="96dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvItem"
|
||||
style="@style/Base.TextAppearance.AppCompat.Small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_margin="10dp"
|
||||
android:text="Unspent"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/separator"
|
||||
style="@style/thin_separator"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgMessage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="com.bitex.Wallet.CardInfoActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
||||
|
|
@ -13,12 +13,9 @@
|
|||
<string name="enable_nfc">This app is useless when NFC is disabled. Reader mode depends on it. Hit OK to go to Settings, where you can enable NFC.</string>
|
||||
<string name="cmd_suffix">command</string>
|
||||
<string name="rsp_suffix">response</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="title_activity_card_info">CardInfoActivity</string>
|
||||
<string name="section_format">Hello World from section: %1$d</string>
|
||||
<string name="fingerprint_authenticate_success">Successfully authenticated!</string>
|
||||
<string name="pin_save_success">Successfully saved!</string>
|
||||
|
||||
<string name="pin_save_fail">Saving pin failed</string>
|
||||
<string name="error_empty_pin">PIN is empty</string>
|
||||
<string name="error_pin_confirmation_failed">Please enter the PIN for confirmation!</string>
|
||||
|
|
@ -64,14 +61,11 @@
|
|||
<!-- MainActivity, Main -->
|
||||
<string name="tap_tangem_card">Tap Tangem card with your smartphone</string>
|
||||
<string name="scan_banknote">Scan a banknote with your \n smartphone as shown above</string>
|
||||
|
||||
<string name="wallet">Wallet</string>
|
||||
<string name="last_unspent">Last unspent</string>
|
||||
|
||||
<string name="no_wallet">NO WALLET</string>
|
||||
<string name="erased_wallet">ERASED WALLET</string>
|
||||
<string name="invalid_card">INVALID CARD</string>
|
||||
|
||||
<string name="developer_kit_spaces">           DEVELOPER     KIT     </string>
|
||||
<string name="banknote_banknote">  BANKNOTE        BANKNOTE</string>
|
||||
<string name="reusable_reusable">   REUSABLE       REUSABLE   </string>
|
||||
|
|
@ -144,77 +138,10 @@
|
|||
<!-- PurgeActivity -->
|
||||
<string name="cannot_erase_wallet">Cannot erase wallet. Make sure you enter correct PIN2!</string>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Strings related to Settings -->
|
||||
|
||||
<!-- Example General settings -->
|
||||
<string name="pref_header_general">General</string>
|
||||
|
||||
<string name="pref_title_social_recommendations">Enable social recommendations</string>
|
||||
<string name="pref_description_social_recommendations">Recommendations for people to contact based on your message history</string>
|
||||
|
||||
<string name="pref_title_display_name">Display name</string>
|
||||
<string name="pref_default_display_name">John Smith</string>
|
||||
|
||||
<string name="pref_title_add_friends_to_messages">Add friends to messages</string>
|
||||
<string-array name="pref_example_list_titles">
|
||||
<item>Always</item>
|
||||
<item>When possible</item>
|
||||
<item>Never</item>
|
||||
</string-array>
|
||||
<string-array name="pref_example_list_values">
|
||||
<item>1</item>
|
||||
<item>0</item>
|
||||
<item>-1</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Example settings for Data & Sync -->
|
||||
<string name="pref_header_data_sync">Data & sync</string>
|
||||
|
||||
<string name="pref_title_sync_frequency">Sync frequency</string>
|
||||
<string-array name="pref_sync_frequency_titles">
|
||||
<item>15 minutes</item>
|
||||
<item>30 minutes</item>
|
||||
<item>1 hour</item>
|
||||
<item>3 hours</item>
|
||||
<item>6 hours</item>
|
||||
<item>Never</item>
|
||||
</string-array>
|
||||
<string-array name="pref_sync_frequency_values">
|
||||
<item>15</item>
|
||||
<item>30</item>
|
||||
<item>60</item>
|
||||
<item>180</item>
|
||||
<item>360</item>
|
||||
<item>-1</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="list_preference_entries">
|
||||
<item>Entry 1</item>
|
||||
<item>Entry 2</item>
|
||||
<item>Entry 3</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="list_preference_entry_values">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="multi_select_list_preference_default_value"/>
|
||||
|
||||
<string name="pref_title_system_sync_settings">System sync settings</string>
|
||||
|
||||
<!-- Example settings for Notifications -->
|
||||
<string name="pref_header_notifications">Notifications</string>
|
||||
<string name="pref_title_new_message_notifications">New message notifications</string>
|
||||
<string name="pref_title_ringtone">Ringtone</string>
|
||||
<string name="pref_ringtone_silent">Silent</string>
|
||||
<string name="pref_title_vibrate">Vibrate</string>
|
||||
<!-- PreparePaymentActivity -->
|
||||
<string name="not_enough_funds_on_your_card">Not enough funds on your card</string>
|
||||
<string name="unknown_amount_format">Unknown amount format</string>
|
||||
<string name="incorrect_destination_wallet_address">Incorrect destination wallet address</string>
|
||||
<string name="destination_wallet_address_equal_source_address">Destination wallet address equal source address</string>
|
||||
|
||||
</resources>
|
||||
|
|
@ -15,7 +15,6 @@
|
|||
<style name="spinner_dropdown_item_actionbar" parent="Widget.AppCompat.DropDownItem.Spinner">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">40dp</item>
|
||||
-->
|
||||
<item name="android:fontFamily">sans-serif-condensed</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:textSize">@dimen/text_size_medium</item>
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
|
||||
dismiss it. -->
|
||||
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
|
||||
<ListPreference
|
||||
android:defaultValue="180"
|
||||
android:entries="@array/pref_sync_frequency_titles"
|
||||
android:entryValues="@array/pref_sync_frequency_values"
|
||||
android:key="sync_frequency"
|
||||
android:negativeButtonText="@null"
|
||||
android:positiveButtonText="@null"
|
||||
android:title="@string/pref_title_sync_frequency"/>
|
||||
|
||||
<!-- This preference simply launches an intent when selected. Use this UI sparingly, per
|
||||
design guidelines. -->
|
||||
<Preference android:title="@string/pref_title_system_sync_settings">
|
||||
<intent android:action="android.settings.SYNC_SETTINGS"/>
|
||||
</Preference>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="example_switch"
|
||||
android:summary="@string/pref_description_social_recommendations"
|
||||
android:title="@string/pref_title_social_recommendations"/>
|
||||
|
||||
<!-- NOTE: EditTextPreference accepts EditText attributes. -->
|
||||
<!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
|
||||
<EditTextPreference
|
||||
android:capitalize="words"
|
||||
android:defaultValue="@string/pref_default_display_name"
|
||||
android:inputType="textCapWords"
|
||||
android:key="example_text"
|
||||
android:maxLines="1"
|
||||
android:selectAllOnFocus="true"
|
||||
android:singleLine="true"
|
||||
android:title="@string/pref_title_display_name"/>
|
||||
|
||||
<!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
|
||||
dismiss it. -->
|
||||
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
|
||||
<ListPreference
|
||||
android:defaultValue="-1"
|
||||
android:entries="@array/pref_example_list_titles"
|
||||
android:entryValues="@array/pref_example_list_values"
|
||||
android:key="example_list"
|
||||
android:negativeButtonText="@null"
|
||||
android:positiveButtonText="@null"
|
||||
android:title="@string/pref_title_add_friends_to_messages"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- These settings headers are only used on tablets. -->
|
||||
|
||||
<header
|
||||
android:fragment="com.tangem.presentation.activity.SettingsFeatureActivity$GeneralPreferenceFragment"
|
||||
android:icon="@drawable/ic_info_black_24dp"
|
||||
android:title="@string/pref_header_general"/>
|
||||
|
||||
<header
|
||||
android:fragment="com.tangem.presentation.activity.SettingsFeatureActivity$NotificationPreferenceFragment"
|
||||
android:icon="@drawable/ic_notifications_black_24dp"
|
||||
android:title="@string/pref_header_notifications"/>
|
||||
|
||||
<header
|
||||
android:fragment="com.tangem.presentation.activity.SettingsFeatureActivity$DataSyncPreferenceFragment"
|
||||
android:icon="@drawable/ic_sync_black_24dp"
|
||||
android:title="@string/pref_header_data_sync"/>
|
||||
|
||||
</preference-headers>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- A 'parent' preference, which enables/disables child preferences (below)
|
||||
when checked/unchecked. -->
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="notifications_new_message"
|
||||
android:title="@string/pref_title_new_message_notifications"/>
|
||||
|
||||
<!-- Allows the user to choose a ringtone in the 'notification' category. -->
|
||||
<!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
|
||||
<!-- NOTE: RingtonePreference's summary should be set to its value by the activity code. -->
|
||||
<RingtonePreference
|
||||
android:defaultValue="content://settings/system/notification_sound"
|
||||
android:dependency="notifications_new_message"
|
||||
android:key="notifications_new_message_ringtone"
|
||||
android:ringtoneType="notification"
|
||||
android:title="@string/pref_title_ringtone"/>
|
||||
|
||||
<!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:dependency="notifications_new_message"
|
||||
android:key="notifications_new_message_vibrate"
|
||||
android:title="@string/pref_title_vibrate"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
Loading…
Add table
Add a link
Reference in a new issue