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"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.MainActivity"
|
android:name="com.tangem.presentation.activity.MainActivity"
|
||||||
|
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar">
|
android:theme="@style/AppTheme.NoActionBar">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="www.tangem.com"
|
android:host="www.tangem.com"
|
||||||
android:scheme="http"/>
|
android:scheme="http"/>
|
||||||
|
|
@ -64,75 +62,73 @@
|
||||||
android:name="android.nfc.action.TECH_DISCOVERED"
|
android:name="android.nfc.action.TECH_DISCOVERED"
|
||||||
android:resource="@xml/nfc_tech_filter"/>
|
android:resource="@xml/nfc_tech_filter"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.RequestPINActivity"
|
android:name="com.tangem.presentation.activity.RequestPINActivity"
|
||||||
|
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.EmptyWalletActivity"
|
android:name="com.tangem.presentation.activity.EmptyWalletActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
<activity
|
|
||||||
android:name="com.tangem.presentation.activity.SelectBlockchainActivity"
|
|
||||||
android:screenOrientation="portrait"
|
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.SavePINActivity"
|
android:name="com.tangem.presentation.activity.SavePINActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
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
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.LoadedWalletActivity"
|
android:name="com.tangem.presentation.activity.LoadedWalletActivity"
|
||||||
android:label="@string/title_activity_loaded_wallet"
|
android:label="@string/title_activity_loaded_wallet"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.VerifyCardActivity"
|
android:name="com.tangem.presentation.activity.VerifyCardActivity"
|
||||||
android:label="@string/title_activity_loaded_wallet"
|
android:label="@string/title_activity_loaded_wallet"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.CreateNewWalletActivity"
|
android:name="com.tangem.presentation.activity.CreateNewWalletActivity"
|
||||||
|
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.PreparePaymentActivity"
|
android:name="com.tangem.presentation.activity.PreparePaymentActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.ConfirmPaymentActivity"
|
android:name="com.tangem.presentation.activity.ConfirmPaymentActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.SignPaymentActivity"
|
android:name="com.tangem.presentation.activity.SignPaymentActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.PurgeActivity"
|
android:name="com.tangem.presentation.activity.PurgeActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.SwapPINActivity"
|
android:name="com.tangem.presentation.activity.SwapPINActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.QRScanActivity"
|
android:name="com.tangem.presentation.activity.QRScanActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.tangem.presentation.activity.SendTransactionActivity"
|
android:name="com.tangem.presentation.activity.SendTransactionActivity"
|
||||||
android:screenOrientation="portrait"
|
android:screenOrientation="portrait"
|
||||||
android:theme="@style/AppTheme.NoActionBar"/>
|
android:theme="@style/AppTheme.NoActionBar"/>
|
||||||
<activity
|
|
||||||
android:name="com.tangem.presentation.activity.SettingsFeatureActivity"
|
|
||||||
android:label="@string/title_activity_settings_feature">
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
</application>
|
</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 android.widget.Toast;
|
||||||
|
|
||||||
import com.tangem.data.network.request.ElectrumRequest;
|
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.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.Blockchain;
|
||||||
import com.tangem.domain.wallet.CoinEngine;
|
import com.tangem.domain.wallet.CoinEngine;
|
||||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
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.SharedData;
|
||||||
|
import com.tangem.domain.wallet.TangemCard;
|
||||||
import com.tangem.domain.wallet.Transaction;
|
import com.tangem.domain.wallet.Transaction;
|
||||||
import com.tangem.domain.wallet.UnspentOutputInfo;
|
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;
|
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_SIGN_PAYMENT = 1;
|
||||||
private static final int REQUEST_CODE_REQUEST_PIN2 = 2;
|
private static final int REQUEST_CODE_REQUEST_PIN2 = 2;
|
||||||
Button btnSend;
|
private Button btnSend;
|
||||||
boolean feeRequestSuccess = false;
|
private boolean feeRequestSuccess = false;
|
||||||
boolean balanceRequestSuccess = false;
|
private boolean balanceRequestSuccess = false;
|
||||||
EditText etWallet;
|
private EditText etWallet;
|
||||||
TextView tvCardID, tvBalance, tvCurrency, tvCurrency2, tvBalanceEquivalent, tvAmountEquivalent, tvFeeEquivalent;
|
private TextView tvAmountEquivalent;
|
||||||
EditText etAmount;
|
private TextView tvFeeEquivalent;
|
||||||
EditText etFee;
|
private EditText etAmount;
|
||||||
ImageView ivCamera;
|
private EditText etFee;
|
||||||
TangemCard mCard;
|
private ImageView ivCamera;
|
||||||
RadioGroup rgFee;
|
private TangemCard mCard;
|
||||||
String minFee = null, maxFee = null, normalFee = null;
|
private RadioGroup rgFee;
|
||||||
Long minFeeInInternalUnits = 0L;
|
private String minFee = null, maxFee = null, normalFee = null;
|
||||||
|
private Long minFeeInInternalUnits = 0L;
|
||||||
private NfcManager mNfcManager;
|
private NfcManager mNfcManager;
|
||||||
int requestPIN2Count = 0;
|
private int requestPIN2Count = 0;
|
||||||
ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
boolean nodeCheck = false;
|
private boolean nodeCheck = false;
|
||||||
Date dtVerifyed = null;
|
private 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 class ConnectTask extends ElectrumTask {
|
private class ConnectTask extends ElectrumTask {
|
||||||
public ConnectTask(String host, int port) {
|
public ConnectTask(String host, int port) {
|
||||||
super(host, port);
|
super(host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConnectTask(String host, int port, SharedData sharedData) {
|
ConnectTask(String host, int port, SharedData sharedData) {
|
||||||
super(host, port, sharedData);
|
super(host, port, sharedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -588,7 +227,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ConnectFeeTask extends FeeTask {
|
private class ConnectFeeTask extends FeeTask {
|
||||||
public ConnectFeeTask(SharedData sharedData) {
|
ConnectFeeTask(SharedData sharedData) {
|
||||||
super(sharedData);
|
super(sharedData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -598,9 +237,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
||||||
for (FeeRequest request : requests) {
|
for (FeeRequest request : requests) {
|
||||||
if (request.error == null) {
|
if (request.error == null) {
|
||||||
long minFeeRate = 0;
|
long minFeeRate = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String tmpAnswer = request.getAsString();
|
String tmpAnswer = request.getAsString();
|
||||||
BigDecimal minFeeBD = new BigDecimal(tmpAnswer);
|
BigDecimal minFeeBD = new BigDecimal(tmpAnswer);
|
||||||
|
|
@ -696,20 +333,219 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSetFee(int checkedRadioButtonId) {
|
@Override
|
||||||
switch (checkedRadioButtonId) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
case R.id.rbMinimalFee:
|
super.onCreate(savedInstanceState);
|
||||||
if (minFee != null) etFee.setText(minFee);
|
setContentView(R.layout.activity_confirm_payment);
|
||||||
else etFee.setText("?");
|
|
||||||
break;
|
MainActivity.commonInit(getApplicationContext());
|
||||||
case R.id.rbNormalFee:
|
mNfcManager = new NfcManager(this, this);
|
||||||
if (normalFee != null) etFee.setText(normalFee);
|
|
||||||
else etFee.setText("?");
|
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||||
break;
|
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||||
case R.id.rbMaximumFee:
|
|
||||||
if (maxFee != null) etFee.setText(maxFee);
|
progressBar = findViewById(R.id.progressBar);
|
||||||
else etFee.setText("?");
|
btnSend = findViewById(R.id.btnSend);
|
||||||
break;
|
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();
|
super.onStop();
|
||||||
mNfcManager.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;
|
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
|
||||||
|
|
||||||
public class CreateNewWalletActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications {
|
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;
|
public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER;
|
||||||
private TangemCard mCard;
|
private TangemCard mCard;
|
||||||
private TextView tvCardID;
|
|
||||||
private NfcManager mNfcManager;
|
private NfcManager mNfcManager;
|
||||||
private static final String logTag = "CreateNewActivity";
|
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private CreateNewWalletTask createNewWalletTask;
|
private CreateNewWalletTask createNewWalletTask;
|
||||||
private boolean lastReadSuccess = true;
|
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 {
|
private class CreateNewWalletTask extends Thread {
|
||||||
|
|
||||||
IsoDep mIsoDep;
|
private IsoDep mIsoDep;
|
||||||
CardProtocol.Notifications mNotifications;
|
private CardProtocol.Notifications mNotifications;
|
||||||
private boolean isCancelled = false;
|
private boolean isCancelled = false;
|
||||||
|
|
||||||
public CreateNewWalletTask(IsoDep isoDep, CardProtocol.Notifications notifications) {
|
public CreateNewWalletTask(IsoDep isoDep, CardProtocol.Notifications notifications) {
|
||||||
|
|
@ -198,13 +118,85 @@ public class CreateNewWalletActivity extends AppCompatActivity implements NfcAda
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReadStart(CardProtocol cardProtocol) {
|
@Override
|
||||||
progressBar.post(new Runnable() {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@Override
|
super.onCreate(savedInstanceState);
|
||||||
public void run() {
|
setContentView(R.layout.activity_create_new_wallet);
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
|
||||||
progressBar.setProgress(5);
|
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 != null) {
|
||||||
if (cardProtocol.getError() == null) {
|
if (cardProtocol.getError() == null) {
|
||||||
progressBar.post(new Runnable() {
|
progressBar.post(() -> {
|
||||||
@Override
|
progressBar.setProgress(100);
|
||||||
public void run() {
|
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
|
||||||
progressBar.setProgress(100);
|
Intent intent = new Intent();
|
||||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
|
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
||||||
Intent intent = new Intent();
|
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
||||||
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
setResult(Activity.RESULT_OK, intent);
|
||||||
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
finish();
|
||||||
setResult(Activity.RESULT_OK, intent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
lastReadSuccess = false;
|
lastReadSuccess = false;
|
||||||
if (cardProtocol.getError() instanceof CardProtocol.TangemException_InvalidPIN) {
|
if (cardProtocol.getError() instanceof CardProtocol.TangemException_InvalidPIN) {
|
||||||
progressBar.post(new Runnable() {
|
progressBar.post(() -> {
|
||||||
@Override
|
progressBar.setProgress(100);
|
||||||
public void run() {
|
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
||||||
progressBar.setProgress(100);
|
|
||||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
progressBar.postDelayed(new Runnable() {
|
progressBar.postDelayed(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
progressBar.setProgress(0);
|
||||||
try {
|
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||||
progressBar.setProgress(0);
|
progressBar.setVisibility(View.INVISIBLE);
|
||||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
Intent intent = new Intent();
|
||||||
progressBar.setVisibility(View.INVISIBLE);
|
intent.putExtra("message", "Cannot create wallet. Make sure you enter correct PIN2!");
|
||||||
Intent intent = new Intent();
|
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
||||||
intent.putExtra("message", "Cannot create wallet. Make sure you enter correct PIN2!");
|
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
||||||
intent.putExtra("UID", cardProtocol.getCard().getUID());
|
setResult(RESULT_INVALID_PIN, intent);
|
||||||
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
|
finish();
|
||||||
setResult(RESULT_INVALID_PIN, intent);
|
} catch (Exception e) {
|
||||||
finish();
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
progressBar.post(new Runnable() {
|
progressBar.post(() -> {
|
||||||
@Override
|
if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) {
|
||||||
public void run() {
|
if (!NoExtendedLengthSupportDialog.allreadyShowed) {
|
||||||
if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) {
|
new NoExtendedLengthSupportDialog().show(getFragmentManager(), NoExtendedLengthSupportDialog.TAG);
|
||||||
if (!NoExtendedLengthSupportDialog.allreadyShowed) {
|
|
||||||
new NoExtendedLengthSupportDialog().show(getFragmentManager(), "NoExtendedLengthSupportDialog");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Toast.makeText(getBaseContext(), "Try to scan again", Toast.LENGTH_LONG).show();
|
|
||||||
}
|
}
|
||||||
progressBar.setProgress(100);
|
} else {
|
||||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
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() {
|
progressBar.postDelayed(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
progressBar.setProgress(0);
|
||||||
try {
|
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||||
progressBar.setProgress(0);
|
progressBar.setVisibility(View.INVISIBLE);
|
||||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
} catch (Exception e) {
|
||||||
progressBar.setVisibility(View.INVISIBLE);
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReadProgress(CardProtocol protocol, final int progress) {
|
public void OnReadProgress(CardProtocol protocol, final int progress) {
|
||||||
progressBar.post(new Runnable() {
|
progressBar.post(() -> progressBar.setProgress(progress));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
progressBar.setProgress(progress);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnReadCancel() {
|
public void OnReadCancel() {
|
||||||
|
|
||||||
createNewWalletTask = null;
|
createNewWalletTask = null;
|
||||||
|
|
||||||
progressBar.postDelayed(new Runnable() {
|
progressBar.postDelayed(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
progressBar.setProgress(0);
|
||||||
try {
|
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||||
progressBar.setProgress(0);
|
progressBar.setVisibility(View.INVISIBLE);
|
||||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
} catch (Exception e) {
|
||||||
progressBar.setVisibility(View.INVISIBLE);
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
@ -330,5 +298,5 @@ public class CreateNewWalletActivity extends AppCompatActivity implements NfcAda
|
||||||
public void OnReadAfterRequest() {
|
public void OnReadAfterRequest() {
|
||||||
WaitSecurityDelayDialog.onReadAfterRequest(this);
|
WaitSecurityDelayDialog.onReadAfterRequest(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.tangem.presentation.activity;
|
package com.tangem.presentation.activity;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.nfc.NfcAdapter;
|
import android.nfc.NfcAdapter;
|
||||||
|
|
@ -11,7 +12,6 @@ import android.text.Html;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
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.Blockchain;
|
||||||
import com.tangem.domain.wallet.CoinEngine;
|
import com.tangem.domain.wallet.CoinEngine;
|
||||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
import com.tangem.domain.wallet.CoinEngineFactory;
|
||||||
import com.tangem.util.FormatUtil;
|
|
||||||
import com.tangem.domain.wallet.TangemCard;
|
import com.tangem.domain.wallet.TangemCard;
|
||||||
|
import com.tangem.util.FormatUtil;
|
||||||
import com.tangem.wallet.R;
|
import com.tangem.wallet.R;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class PreparePaymentActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback {
|
public class PreparePaymentActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback {
|
||||||
|
|
||||||
private static final int REQUEST_CODE_SCAN_QR = 1;
|
private static final int REQUEST_CODE_SCAN_QR = 1;
|
||||||
private static final int REQUEST_CODE_SEND_PAYMENT = 2;
|
private static final int REQUEST_CODE_SEND_PAYMENT = 2;
|
||||||
private Button btnVerify;
|
|
||||||
private EditText etWallet;
|
private EditText etWallet;
|
||||||
private EditText etAmount;
|
private EditText etAmount;
|
||||||
private TextView tvCurrency;
|
private TextView tvAmountEquivalent;
|
||||||
private TextView tvCardId, tvBalance, tvBalanceEquivalent, tvAmountEquivalent;
|
|
||||||
private ImageView ivCamera;
|
|
||||||
boolean use_mCurrency;
|
boolean use_mCurrency;
|
||||||
private TangemCard mCard;
|
private TangemCard mCard;
|
||||||
private NfcManager mNfcManager;
|
private NfcManager mNfcManager;
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
@ -53,14 +52,14 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap
|
||||||
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
mCard = new TangemCard(getIntent().getStringExtra("UID"));
|
||||||
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card"));
|
||||||
|
|
||||||
btnVerify = findViewById(R.id.btnVerify);
|
Button btnVerify = findViewById(R.id.btnVerify);
|
||||||
etWallet = findViewById(R.id.etWallet);
|
etWallet = findViewById(R.id.etWallet);
|
||||||
etAmount = findViewById(R.id.etAmount);
|
etAmount = findViewById(R.id.etAmount);
|
||||||
ivCamera = findViewById(R.id.ivCamera);
|
ImageView ivCamera = findViewById(R.id.ivCamera);
|
||||||
tvCurrency = findViewById(R.id.tvCurrency);
|
TextView tvCurrency = findViewById(R.id.tvCurrency);
|
||||||
tvCardId = findViewById(R.id.tvCardID);
|
TextView tvCardId = findViewById(R.id.tvCardID);
|
||||||
tvBalance = findViewById(R.id.tvBalance);
|
TextView tvBalance = findViewById(R.id.tvBalance);
|
||||||
tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
|
TextView tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent);
|
||||||
tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent);
|
tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent);
|
||||||
|
|
||||||
tvCardId.setText(mCard.getCIDDescription());
|
tvCardId.setText(mCard.getCIDDescription());
|
||||||
|
|
@ -135,49 +134,60 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap
|
||||||
etAmount.setText(engine.GetBalanceValue(mCard));
|
etAmount.setText(engine.GetBalanceValue(mCard));
|
||||||
}
|
}
|
||||||
|
|
||||||
btnVerify.setOnClickListener(new View.OnClickListener() {
|
btnVerify.setOnClickListener(v -> {
|
||||||
@Override
|
String strAmount;
|
||||||
public void onClick(View v) {
|
strAmount = etAmount.getText().toString();
|
||||||
String strAmount;
|
CoinEngine engine1 = CoinEngineFactory.Create(mCard.getBlockchain());
|
||||||
strAmount = etAmount.getText().toString();
|
try {
|
||||||
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
|
if (!Objects.requireNonNull(engine1).CheckAmount(mCard, etAmount.getText().toString())) {
|
||||||
try {
|
etAmount.setError(getString(R.string.not_enough_funds_on_your_card));
|
||||||
if (!engine.CheckAmount(mCard, etAmount.getText().toString())) {
|
|
||||||
etAmount.setError("Not enough funds on your card");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
etAmount.setError("Unknown amount format");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
boolean checkAddress = engine.ValdateAddress(etWallet.getText().toString(), mCard);
|
etAmount.setError(getString(R.string.unknown_amount_format));
|
||||||
if (!checkAddress) {
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
ivCamera.setOnClickListener(v -> {
|
||||||
@Override
|
Intent intent = new Intent(getBaseContext(), QRScanActivity.class);
|
||||||
public void onClick(View v) {
|
startActivityForResult(intent, REQUEST_CODE_SCAN_QR);
|
||||||
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
|
@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="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="cmd_suffix">command</string>
|
||||||
<string name="rsp_suffix">response</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="section_format">Hello World from section: %1$d</string>
|
||||||
<string name="fingerprint_authenticate_success">Successfully authenticated!</string>
|
<string name="fingerprint_authenticate_success">Successfully authenticated!</string>
|
||||||
<string name="pin_save_success">Successfully saved!</string>
|
<string name="pin_save_success">Successfully saved!</string>
|
||||||
|
|
||||||
<string name="pin_save_fail">Saving pin failed</string>
|
<string name="pin_save_fail">Saving pin failed</string>
|
||||||
<string name="error_empty_pin">PIN is empty</string>
|
<string name="error_empty_pin">PIN is empty</string>
|
||||||
<string name="error_pin_confirmation_failed">Please enter the PIN for confirmation!</string>
|
<string name="error_pin_confirmation_failed">Please enter the PIN for confirmation!</string>
|
||||||
|
|
@ -64,14 +61,11 @@
|
||||||
<!-- MainActivity, Main -->
|
<!-- MainActivity, Main -->
|
||||||
<string name="tap_tangem_card">Tap Tangem card with your smartphone</string>
|
<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="scan_banknote">Scan a banknote with your \n smartphone as shown above</string>
|
||||||
|
|
||||||
<string name="wallet">Wallet</string>
|
<string name="wallet">Wallet</string>
|
||||||
<string name="last_unspent">Last unspent</string>
|
<string name="last_unspent">Last unspent</string>
|
||||||
|
|
||||||
<string name="no_wallet">NO WALLET</string>
|
<string name="no_wallet">NO WALLET</string>
|
||||||
<string name="erased_wallet">ERASED WALLET</string>
|
<string name="erased_wallet">ERASED WALLET</string>
|
||||||
<string name="invalid_card">INVALID CARD</string>
|
<string name="invalid_card">INVALID CARD</string>
|
||||||
|
|
||||||
<string name="developer_kit_spaces">           DEVELOPER     KIT     </string>
|
<string name="developer_kit_spaces">           DEVELOPER     KIT     </string>
|
||||||
<string name="banknote_banknote">  BANKNOTE        BANKNOTE</string>
|
<string name="banknote_banknote">  BANKNOTE        BANKNOTE</string>
|
||||||
<string name="reusable_reusable">   REUSABLE       REUSABLE   </string>
|
<string name="reusable_reusable">   REUSABLE       REUSABLE   </string>
|
||||||
|
|
@ -144,77 +138,10 @@
|
||||||
<!-- PurgeActivity -->
|
<!-- PurgeActivity -->
|
||||||
<string name="cannot_erase_wallet">Cannot erase wallet. Make sure you enter correct PIN2!</string>
|
<string name="cannot_erase_wallet">Cannot erase wallet. Make sure you enter correct PIN2!</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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 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>
|
|
||||||
|
|
||||||
</resources>
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
<style name="spinner_dropdown_item_actionbar" parent="Widget.AppCompat.DropDownItem.Spinner">
|
<style name="spinner_dropdown_item_actionbar" parent="Widget.AppCompat.DropDownItem.Spinner">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">40dp</item>
|
<item name="android:layout_height">40dp</item>
|
||||||
-->
|
|
||||||
<item name="android:fontFamily">sans-serif-condensed</item>
|
<item name="android:fontFamily">sans-serif-condensed</item>
|
||||||
<item name="android:singleLine">true</item>
|
<item name="android:singleLine">true</item>
|
||||||
<item name="android:textSize">@dimen/text_size_medium</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