Updated on 2026-08-14
This commit is contained in:
parent
782e909ebd
commit
d71ee3f4d5
8 changed files with 213 additions and 234 deletions
|
|
@ -1,14 +1,8 @@
|
|||
package com.tangem.presentation.activity;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.Tag;
|
||||
import android.os.Bundle;
|
||||
|
|
@ -34,110 +28,63 @@ import com.tangem.domain.wallet.DeviceNFCAntennaLocation;
|
|||
import com.tangem.domain.wallet.LastSignStorage;
|
||||
import com.tangem.domain.wallet.Logger;
|
||||
import com.tangem.domain.wallet.PINStorage;
|
||||
import com.tangem.presentation.dialog.RootFoundDialog;
|
||||
import com.tangem.presentation.fragment.MainFragment;
|
||||
import com.tangem.util.CommonUtil;
|
||||
import com.tangem.util.PhoneUtility;
|
||||
import com.tangem.wallet.BuildConfig;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuItemClickListener {
|
||||
public static final String TAG = MainActivity.class.getSimpleName();
|
||||
|
||||
public static final int DIALOG_ENABLE_INTERNET = 1;
|
||||
private static final int REQUEST_CODE_SEND_EMAIL = 2;
|
||||
private String logTag = "MainActivity";
|
||||
|
||||
private File zipFile = null;
|
||||
private NfcAdapter.ReaderCallback onNFCReaderCallback;
|
||||
private OnCardsClean onCardsClean;
|
||||
private FloatingActionButton fab;
|
||||
private LinearLayout llTapPrompt;
|
||||
|
||||
public interface OnCardsClean {
|
||||
void doClean();
|
||||
}
|
||||
|
||||
// public interface OnCreateNFCDialog {
|
||||
// Dialog CreateNFCDialog(int id, AlertDialogWrapper.Builder builder, LayoutInflater li);
|
||||
// }
|
||||
|
||||
|
||||
// OnCreateNFCDialog onCreateNFCDialog;
|
||||
|
||||
|
||||
public void setOnCardsClean(OnCardsClean onCardsClean) {
|
||||
this.onCardsClean = onCardsClean;
|
||||
}
|
||||
|
||||
// public void setOnCreateNFCDialog(OnCreateNFCDialog onCreateNFCDialog) {
|
||||
// this.onCreateNFCDialog = onCreateNFCDialog;
|
||||
// }
|
||||
|
||||
public void setNfcAdapterReaderCallback(NfcAdapter.ReaderCallback callback) {
|
||||
this.onNFCReaderCallback = callback;
|
||||
}
|
||||
|
||||
public void showCleanButton() {
|
||||
findViewById(R.id.tvTapPrompt).setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void hideCleanButton() {
|
||||
findViewById(R.id.tvTapPrompt).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public static class RootFoundDialog extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle("Your Android device is rooted. Security at risk!")
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("Got it",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
}
|
||||
}
|
||||
)
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
TextView tvNFCHint = findViewById(R.id.tvNFCHint);
|
||||
llTapPrompt = findViewById(R.id.llTapPrompt);
|
||||
LinearLayout hand = findViewById(R.id.llHand);
|
||||
LinearLayout nfc = findViewById(R.id.llNFC);
|
||||
RippleBackground rippleBackground = findViewById(R.id.imNFC);
|
||||
fab = findViewById(R.id.fab);
|
||||
|
||||
// check if device root
|
||||
RootBeer rootBeer = new RootBeer(this);
|
||||
if (rootBeer.isRootedWithoutBusyBoxCheck()) {
|
||||
new RootFoundDialog().show(getFragmentManager(), "RootFoundDialog");
|
||||
}
|
||||
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
|
||||
|
||||
commonInit(getApplicationContext());
|
||||
|
||||
if (tvNFCHint != null) {
|
||||
// tvNFCHint.setText("Scan a banknote with your\n" + PhoneUtility.GetPhoneName() + "\nas shown above");
|
||||
tvNFCHint.setText("Scan a banknote with your\n smartphone as shown above");
|
||||
}
|
||||
rippleBackground.startRippleAnimation();
|
||||
|
||||
// tvNFCHint.setText("Scan a banknote with your\n" + PhoneUtility.GetPhoneName() + "\nas shown above");
|
||||
tvNFCHint.setText(R.string.scan_banknote);
|
||||
|
||||
DeviceNFCAntennaLocation antenna = new DeviceNFCAntennaLocation();
|
||||
antenna.getAntennaLocation();
|
||||
final LinearLayout hand = findViewById(R.id.llHand);
|
||||
final LinearLayout nfc = findViewById(R.id.llNFC);
|
||||
|
||||
// animate
|
||||
final RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) hand.getLayoutParams();
|
||||
final RelativeLayout.LayoutParams lp2 = (RelativeLayout.LayoutParams) nfc.getLayoutParams();
|
||||
final float dp = getResources().getDisplayMetrics().density;
|
||||
|
|
@ -153,24 +100,21 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
hand.setLayoutParams(lp);
|
||||
}
|
||||
};
|
||||
a.setDuration(2000); // in ms
|
||||
a.setDuration(2000);
|
||||
a.setInterpolator(new DecelerateInterpolator());
|
||||
hand.startAnimation(a);
|
||||
|
||||
// set listeners
|
||||
fab.setOnClickListener(this::showMenu);
|
||||
|
||||
// add fragment
|
||||
MainFragment mainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.fragmentMain);
|
||||
if (mainFragment.getCardListAdapter().getItemCount() > 0) {
|
||||
if (mainFragment.getCardListAdapter().getItemCount() > 0)
|
||||
showCleanButton();
|
||||
} else {
|
||||
else
|
||||
hideCleanButton();
|
||||
}
|
||||
|
||||
final RippleBackground rippleBackground = findViewById(R.id.imNFC);
|
||||
rippleBackground.startRippleAnimation();
|
||||
|
||||
|
||||
// NFC
|
||||
Intent intent = getIntent();
|
||||
if (intent != null && (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))) {
|
||||
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
||||
|
|
@ -178,12 +122,11 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
onNFCReaderCallback.onTagDiscovered(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
// Logger.StopSaveToFile(getApplicationContext());
|
||||
super.onDestroy();
|
||||
// check if device root
|
||||
RootBeer rootBeer = new RootBeer(this);
|
||||
if (rootBeer.isRootedWithoutBusyBoxCheck())
|
||||
new RootFoundDialog().show(getFragmentManager(), RootFoundDialog.TAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -208,9 +151,13 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
return super.onKeyDown(keycode, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@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_main, menu);
|
||||
if (BuildConfig.DEBUG) {
|
||||
for (int i = 0; i < menu.size(); i++) menu.getItem(i).setVisible(true);
|
||||
|
|
@ -218,78 +165,21 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
return true;
|
||||
}
|
||||
|
||||
public class Compress {
|
||||
private static final int BUFFER = 2048;
|
||||
|
||||
private String[] _files;
|
||||
private String _zipFile;
|
||||
|
||||
Compress(String[] files, String zipFile) {
|
||||
_files = files;
|
||||
_zipFile = zipFile;
|
||||
}
|
||||
|
||||
void zip() {
|
||||
try {
|
||||
BufferedInputStream origin = null;
|
||||
FileOutputStream dest = new FileOutputStream(_zipFile);
|
||||
|
||||
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
|
||||
|
||||
byte data[] = new byte[BUFFER];
|
||||
|
||||
for (String _file : _files) {
|
||||
Log.v("Compress", "Adding: " + _file);
|
||||
FileInputStream fi = new FileInputStream(_file);
|
||||
origin = new BufferedInputStream(fi, BUFFER);
|
||||
ZipEntry entry = new ZipEntry(_file.substring(_file.lastIndexOf("/") + 1));
|
||||
out.putNextEntry(entry);
|
||||
int count;
|
||||
while ((count = origin.read(data, 0, BUFFER)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
origin.close();
|
||||
}
|
||||
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CODE_SEND_EMAIL) {
|
||||
if (zipFile != null) {
|
||||
zipFile.delete();
|
||||
zipFile = null;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
|
||||
//noinspection SimplifiableIfStatement
|
||||
// noinspection SimplifiableIfStatement
|
||||
switch (id) {
|
||||
case R.id.sendLogs:
|
||||
File f = null;
|
||||
try {
|
||||
f = Logger.collectLogs(this);
|
||||
if (f != null) {
|
||||
Log.e(logTag, String.format("Collect %d log bytes", f.length()));
|
||||
sendEmail("Logs", PhoneUtility.getDeviceInfo(), new File[]{f});
|
||||
Log.e(TAG, String.format("Collect %d log bytes", f.length()));
|
||||
CommonUtil.sendEmail(this, zipFile, TAG, "Logs", PhoneUtility.getDeviceInfo(), new File[]{f});
|
||||
} else {
|
||||
Log.e(logTag, "Can't create temporaly log file");
|
||||
Log.e(TAG, "Can't create temporaly log file");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
|
@ -320,6 +210,17 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CODE_SEND_EMAIL) {
|
||||
if (zipFile != null) {
|
||||
zipFile.delete();
|
||||
zipFile = null;
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
public static void commonInit(Context context) {
|
||||
if (PINStorage.needInit()) {
|
||||
PINStorage.Init(context);
|
||||
|
|
@ -329,6 +230,14 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
}
|
||||
}
|
||||
|
||||
public void showCleanButton() {
|
||||
llTapPrompt.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void hideCleanButton() {
|
||||
llTapPrompt.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void showLogoActivity() {
|
||||
Intent intent = new Intent(getBaseContext(), LogoActivity.class);
|
||||
intent.putExtra(LogoActivity.TAG, true);
|
||||
|
|
@ -363,41 +272,4 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI
|
|||
popup.show();
|
||||
}
|
||||
|
||||
private void sendEmail(String subject, String text, File[] fileLocations) {
|
||||
if (zipFile != null) return;
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND)
|
||||
//.setData(new Uri.Builder().scheme("mailto").build())
|
||||
.setType("text/plain")
|
||||
.putExtra(Intent.EXTRA_EMAIL, new String[]{"android@tangem.com"})
|
||||
.putExtra(Intent.EXTRA_SUBJECT, subject)
|
||||
.putExtra(Intent.EXTRA_TEXT, text);
|
||||
|
||||
if (fileLocations != null && fileLocations.length > 0) {
|
||||
String[] fileNames = new String[fileLocations.length];
|
||||
for (int i = 0; i < fileLocations.length; i++)
|
||||
fileNames[i] = fileLocations[i].getAbsolutePath();
|
||||
zipFile = File.createTempFile("tangemLogs", ".zip", fileLocations[0].getParentFile());
|
||||
Compress compress = new Compress(fileNames, zipFile.getAbsolutePath());
|
||||
compress.zip();
|
||||
Log.e(logTag, String.format("Send %d bytes zip with logs", zipFile.length()));
|
||||
Uri attachment = Uri.parse("content://" + getString(R.string.log_file_provider_authorities) + "/" + zipFile.getName());
|
||||
|
||||
intent.putExtra(Intent.EXTRA_STREAM, attachment);
|
||||
zipFile.deleteOnExit();
|
||||
}
|
||||
|
||||
List<ResolveInfo> activities = getPackageManager().queryIntentActivities(intent, 0);
|
||||
boolean isIntentSafe = activities.size() > 0;
|
||||
|
||||
if (isIntentSafe) {
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,23 +9,17 @@ import android.os.Bundle;
|
|||
import com.tangem.wallet.R;
|
||||
|
||||
public class NoExtendedLengthSupportDialog extends DialogFragment {
|
||||
public static final String TAG = NoExtendedLengthSupportDialog.class.getSimpleName();
|
||||
|
||||
public static boolean allreadyShowed=false;
|
||||
public static boolean allreadyShowed = false;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle("Warning")
|
||||
.setMessage("The NFC adapter of the device does not support extended length APDU, it's possible that some functions will not work!")
|
||||
.setPositiveButton("Got it",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
NoExtendedLengthSupportDialog.allreadyShowed=true;
|
||||
}
|
||||
}
|
||||
)
|
||||
.setTitle(R.string.warning)
|
||||
.setMessage(R.string.the_nfc_adapter_length_apdu)
|
||||
.setPositiveButton(R.string.got_it, (dialog, whichButton) -> NoExtendedLengthSupportDialog.allreadyShowed = true)
|
||||
.create();
|
||||
}
|
||||
|
||||
|
|
@ -33,4 +27,5 @@ public class NoExtendedLengthSupportDialog extends DialogFragment {
|
|||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.tangem.presentation.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
public class RootFoundDialog extends DialogFragment {
|
||||
public static final String TAG = RootFoundDialog.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle(R.string.device_is_rooted)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.got_it, null)
|
||||
.create();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -63,6 +63,7 @@ import java.util.Objects;
|
|||
// NfcManager getNfcManager(Activity activity, NfcAdapter.ReaderCallback readerCallback);
|
||||
//
|
||||
//}
|
||||
|
||||
/**
|
||||
* A placeholder fragment containing a simple view.
|
||||
*/
|
||||
|
|
@ -442,19 +443,13 @@ public class MainFragment extends Fragment implements NfcAdapter.ReaderCallback,
|
|||
if (card.getStatus() == TangemCard.Status.Empty) {
|
||||
intent = new Intent(getActivity(), EmptyWalletActivity.class);
|
||||
// Toast.makeText(getContext(), "1", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
else if (card.getStatus() == TangemCard.Status.Loaded) {
|
||||
} else if (card.getStatus() == TangemCard.Status.Loaded) {
|
||||
intent = new Intent(getActivity(), LoadedWalletActivity.class);
|
||||
// Toast.makeText(getContext(), "2", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
else if (card.getStatus() == TangemCard.Status.NotPersonalized || card.getStatus() == TangemCard.Status.Purged) {
|
||||
} else if (card.getStatus() == TangemCard.Status.NotPersonalized || card.getStatus() == TangemCard.Status.Purged) {
|
||||
// Toast.makeText(getContext(), "3", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
intent = new Intent(getActivity(), LoadedWalletActivity.class);
|
||||
// Toast.makeText(getContext(), "4", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
|
@ -676,20 +671,16 @@ public class MainFragment extends Fragment implements NfcAdapter.ReaderCallback,
|
|||
|
||||
if (cardProtocol != null) {
|
||||
if (cardProtocol.getError() == null) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
|
||||
addCard(cardProtocol.getCard());
|
||||
}
|
||||
progressBar.post(() -> {
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
|
||||
addCard(cardProtocol.getCard());
|
||||
});
|
||||
} else {
|
||||
// remove last UIDs because of error and no card read
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(getContext(), "Try to scan again", Toast.LENGTH_LONG).show();
|
||||
progressBar.post(() -> {
|
||||
if (getContext() != null) {
|
||||
Toast.makeText(getContext(), R.string.try_to_scan_again, Toast.LENGTH_LONG).show();
|
||||
unsuccessReadCount++;
|
||||
progressBar.setProgress(100);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
|
||||
|
|
@ -698,7 +689,7 @@ public class MainFragment extends Fragment implements NfcAdapter.ReaderCallback,
|
|||
doEnterPIN();
|
||||
} else if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) {
|
||||
if (!NoExtendedLengthSupportDialog.allreadyShowed) {
|
||||
new NoExtendedLengthSupportDialog().show(getActivity().getFragmentManager(), "NoExtendedLengthSupportDialog");
|
||||
new NoExtendedLengthSupportDialog().show(Objects.requireNonNull(getActivity()).getFragmentManager(), NoExtendedLengthSupportDialog.TAG);
|
||||
}
|
||||
} else {
|
||||
lastTag = null;
|
||||
|
|
@ -708,16 +699,13 @@ public class MainFragment extends Fragment implements NfcAdapter.ReaderCallback,
|
|||
}
|
||||
}
|
||||
|
||||
progressBar.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
progressBar.postDelayed(() -> {
|
||||
try {
|
||||
progressBar.setProgress(0);
|
||||
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue