Display UI card read

This commit is contained in:
riz081 2025-06-18 11:44:11 +07:00
parent 124da43a1e
commit 8add903edb

View File

@ -15,6 +15,8 @@ import com.sunmi.pay.hardware.aidl.AidlConstants.CardType;
import com.sunmi.pay.hardware.aidlv2.readcard.CheckCardCallbackV2; import com.sunmi.pay.hardware.aidlv2.readcard.CheckCardCallbackV2;
public class CreditCardActivity extends AppCompatActivity { public class CreditCardActivity extends AppCompatActivity {
private static final String TAG = "CreditCard";
private TextView tvResult; private TextView tvResult;
private Button btnCheckCard; private Button btnCheckCard;
private boolean checkingCard; private boolean checkingCard;
@ -22,22 +24,26 @@ public class CreditCardActivity extends AppCompatActivity {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
android.util.Log.d("CreditCard", "onCreate called"); android.util.Log.d(TAG, "onCreate called");
setContentView(R.layout.activity_credit_card); setContentView(R.layout.activity_credit_card);
initView(); initView();
// Check PaySDK status // Check PaySDK status
checkPaySDKStatus();
}
private void checkPaySDKStatus() {
if (MyApplication.app != null) { if (MyApplication.app != null) {
android.util.Log.d("CreditCard", "MyApplication.app exists"); android.util.Log.d(TAG, "MyApplication.app exists");
android.util.Log.d("CreditCard", "PaySDK connected: " + MyApplication.app.isConnectPaySDK()); android.util.Log.d(TAG, "PaySDK connected: " + MyApplication.app.isConnectPaySDK());
android.util.Log.d("CreditCard", "readCardOptV2 null: " + (MyApplication.app.readCardOptV2 == null)); android.util.Log.d(TAG, "readCardOptV2 null: " + (MyApplication.app.readCardOptV2 == null));
} else { } else {
android.util.Log.e("CreditCard", "MyApplication.app is null"); android.util.Log.e(TAG, "MyApplication.app is null");
} }
} }
private void initView() { private void initView() {
android.util.Log.d("CreditCard", "initView called"); android.util.Log.d(TAG, "initView called");
// Setup Toolbar as ActionBar // Setup Toolbar as ActionBar
androidx.appcompat.widget.Toolbar toolbar = findViewById(R.id.toolbar); androidx.appcompat.widget.Toolbar toolbar = findViewById(R.id.toolbar);
@ -53,20 +59,20 @@ public class CreditCardActivity extends AppCompatActivity {
btnCheckCard = findViewById(R.id.btn_check_card); btnCheckCard = findViewById(R.id.btn_check_card);
if (btnCheckCard != null) { if (btnCheckCard != null) {
android.util.Log.d("CreditCard", "Button found, setting click listener"); android.util.Log.d(TAG, "Button found, setting click listener");
btnCheckCard.setOnClickListener(v -> { btnCheckCard.setOnClickListener(v -> {
android.util.Log.d("CreditCard", "Button clicked!"); android.util.Log.d(TAG, "Button clicked!");
switchCheckCard(); switchCheckCard();
}); });
} else { } else {
android.util.Log.e("CreditCard", "Button not found!"); android.util.Log.e(TAG, "Button not found!");
} }
if (tvResult != null) { if (tvResult != null) {
tvResult.setText("Ready to scan card..."); tvResult.setText("Ready to scan card...");
android.util.Log.d("CreditCard", "TextView initialized"); android.util.Log.d(TAG, "TextView initialized");
} else { } else {
android.util.Log.e("CreditCard", "TextView not found!"); android.util.Log.e(TAG, "TextView not found!");
} }
} }
@ -77,56 +83,75 @@ public class CreditCardActivity extends AppCompatActivity {
} }
private void switchCheckCard() { private void switchCheckCard() {
android.util.Log.d("CreditCard", "switchCheckCard called, checkingCard: " + checkingCard); android.util.Log.d(TAG, "switchCheckCard called, checkingCard: " + checkingCard);
try { try {
if (checkingCard) { if (checkingCard) {
android.util.Log.d("CreditCard", "Stopping card check"); android.util.Log.d(TAG, "Stopping card check");
MyApplication.app.readCardOptV2.cancelCheckCard(); stopCardCheck();
btnCheckCard.setText(R.string.card_start_check_card);
checkingCard = false;
} else { } else {
android.util.Log.d("CreditCard", "Starting card check"); android.util.Log.d(TAG, "Starting card check");
checkCreditCard(); startCardCheck();
checkingCard = true;
btnCheckCard.setText(R.string.card_stop_check_card);
} }
} catch (Exception e) { } catch (Exception e) {
android.util.Log.e("CreditCard", "Error in switchCheckCard: " + e.getMessage()); android.util.Log.e(TAG, "Error in switchCheckCard: " + e.getMessage());
e.printStackTrace(); e.printStackTrace();
updateUI("Error: " + e.getMessage(), false);
}
}
private void startCardCheck() {
try {
checkCreditCard();
checkingCard = true;
btnCheckCard.setText(R.string.card_stop_check_card);
} catch (Exception e) {
android.util.Log.e(TAG, "Error starting card check: " + e.getMessage());
updateUI("Error starting card check: " + e.getMessage(), false);
}
}
private void stopCardCheck() {
try {
if (MyApplication.app != null && MyApplication.app.readCardOptV2 != null) {
MyApplication.app.readCardOptV2.cancelCheckCard();
}
checkingCard = false;
btnCheckCard.setText(R.string.card_start_check_card);
updateUI("Card check stopped", false);
} catch (Exception e) {
android.util.Log.e(TAG, "Error stopping card check: " + e.getMessage());
checkingCard = false;
btnCheckCard.setText(R.string.card_start_check_card);
} }
} }
private void checkCreditCard() { private void checkCreditCard() {
try { try {
// Ensure PaySDK is bound first // Validate application state
if (MyApplication.app == null) { if (!validateApplicationState()) {
tvResult.setText("Error: Application not initialized");
android.util.Log.e("CreditCard", "MyApplication.app is null");
return; return;
} }
// If not connected, try to bind first // If not connected, try to bind first
if (!MyApplication.app.isConnectPaySDK()) { if (!MyApplication.app.isConnectPaySDK()) {
tvResult.setText("Connecting to PaySDK..."); tvResult.setText("Connecting to PaySDK...");
android.util.Log.d("CreditCard", "PaySDK not connected, binding service..."); android.util.Log.d(TAG, "PaySDK not connected, binding service...");
MyApplication.app.bindPaySDKService(); MyApplication.app.bindPaySDKService();
// Wait a bit and retry // Wait and retry
btnCheckCard.postDelayed(() -> { btnCheckCard.postDelayed(() -> {
if (MyApplication.app.isConnectPaySDK() && MyApplication.app.readCardOptV2 != null) { if (MyApplication.app.isConnectPaySDK() && MyApplication.app.readCardOptV2 != null) {
startCardScan(); startCardScan();
} else { } else {
tvResult.setText("Error: Failed to connect to PaySDK"); updateUI("Error: Failed to connect to PaySDK", false);
checkingCard = false;
btnCheckCard.setText(R.string.card_start_check_card);
} }
}, 2000); // Wait 2 seconds }, 2000);
return; return;
} }
if (MyApplication.app.readCardOptV2 == null) { if (MyApplication.app.readCardOptV2 == null) {
tvResult.setText("Error: Card reader not initialized"); updateUI("Error: Card reader not initialized", false);
android.util.Log.e("CreditCard", "readCardOptV2 is null"); android.util.Log.e(TAG, "readCardOptV2 is null");
return; return;
} }
@ -134,36 +159,61 @@ public class CreditCardActivity extends AppCompatActivity {
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
android.util.Log.e("CreditCard", "Error in checkCreditCard: " + e.getMessage()); android.util.Log.e(TAG, "Error in checkCreditCard: " + e.getMessage());
tvResult.setText("Error starting card scan: " + e.getMessage()); updateUI("Error starting card scan: " + e.getMessage(), false);
} }
} }
private boolean validateApplicationState() {
if (MyApplication.app == null) {
updateUI("Error: Application not initialized", false);
android.util.Log.e(TAG, "MyApplication.app is null");
return false;
}
return true;
}
private void startCardScan() { private void startCardScan() {
try { try {
int cardType = CardType.MAGNETIC.getValue() | CardType.IC.getValue() | CardType.NFC.getValue(); int cardType = CardType.MAGNETIC.getValue() | CardType.IC.getValue() | CardType.NFC.getValue();
tvResult.setText("Starting card scan...\nPlease insert or swipe your card"); tvResult.setText("Starting card scan...\nPlease insert, swipe, or tap your card");
// Log for debugging android.util.Log.d(TAG, "Starting checkCard with cardType: " + cardType);
android.util.Log.d("CreditCard", "Starting checkCard with cardType: " + cardType); android.util.Log.d(TAG, "CardType values - MAGNETIC: " + CardType.MAGNETIC.getValue() +
", IC: " + CardType.IC.getValue() + ", NFC: " + CardType.NFC.getValue());
MyApplication.app.readCardOptV2.checkCard(cardType, mCheckCardCallback, 60); MyApplication.app.readCardOptV2.checkCard(cardType, mCheckCardCallback, 60);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
android.util.Log.e("CreditCard", "Error in startCardScan: " + e.getMessage()); android.util.Log.e(TAG, "Error in startCardScan: " + e.getMessage());
tvResult.setText("Error starting card scan: " + e.getMessage()); updateUI("Error starting card scan: " + e.getMessage(), false);
} }
} }
private void updateUI(String message, boolean isCardDetected) {
runOnUiThread(() -> {
if (tvResult != null) {
tvResult.setText(message);
}
if (isCardDetected) {
checkingCard = false;
btnCheckCard.setText(R.string.card_start_check_card);
}
});
}
// ====== CALLBACK IMPLEMENTATION ======
private final CheckCardCallbackV2 mCheckCardCallback = new CheckCardCallbackV2.Stub() { private final CheckCardCallbackV2 mCheckCardCallback = new CheckCardCallbackV2.Stub() {
@Override @Override
public void findMagCard(Bundle info) throws RemoteException { public void findMagCard(Bundle info) throws RemoteException {
android.util.Log.d(TAG, "findMagCard callback triggered");
runOnUiThread(() -> handleMagCardResult(info)); runOnUiThread(() -> handleMagCardResult(info));
} }
@Override @Override
public void findICCard(String atr) throws RemoteException { public void findICCard(String atr) throws RemoteException {
android.util.Log.d(TAG, "findICCard callback triggered with ATR: " + atr);
Bundle info = new Bundle(); Bundle info = new Bundle();
info.putString("atr", atr); info.putString("atr", atr);
runOnUiThread(() -> handleICCardResult(info)); runOnUiThread(() -> handleICCardResult(info));
@ -171,7 +221,7 @@ public class CreditCardActivity extends AppCompatActivity {
@Override @Override
public void findRFCard(String uuid) throws RemoteException { public void findRFCard(String uuid) throws RemoteException {
// Handle RF card detection - changed to single parameter android.util.Log.d(TAG, "findRFCard callback triggered with UUID: " + uuid);
Bundle info = new Bundle(); Bundle info = new Bundle();
info.putString("uuid", uuid); info.putString("uuid", uuid);
runOnUiThread(() -> handleRFCardResult(info)); runOnUiThread(() -> handleRFCardResult(info));
@ -179,6 +229,7 @@ public class CreditCardActivity extends AppCompatActivity {
@Override @Override
public void onError(int code, String message) throws RemoteException { public void onError(int code, String message) throws RemoteException {
android.util.Log.e(TAG, "onError callback triggered - Code: " + code + ", Message: " + message);
Bundle info = new Bundle(); Bundle info = new Bundle();
info.putInt("code", code); info.putInt("code", code);
info.putString("message", message); info.putString("message", message);
@ -187,78 +238,184 @@ public class CreditCardActivity extends AppCompatActivity {
@Override @Override
public void findICCardEx(Bundle info) throws RemoteException { public void findICCardEx(Bundle info) throws RemoteException {
android.util.Log.d(TAG, "findICCardEx callback triggered");
runOnUiThread(() -> handleICCardResult(info)); runOnUiThread(() -> handleICCardResult(info));
} }
@Override @Override
public void findRFCardEx(Bundle info) throws RemoteException { public void findRFCardEx(Bundle info) throws RemoteException {
android.util.Log.d(TAG, "findRFCardEx callback triggered");
runOnUiThread(() -> handleRFCardResult(info)); runOnUiThread(() -> handleRFCardResult(info));
} }
@Override @Override
public void onErrorEx(Bundle info) throws RemoteException { public void onErrorEx(Bundle info) throws RemoteException {
android.util.Log.e(TAG, "onErrorEx callback triggered");
runOnUiThread(() -> handleErrorResult(info)); runOnUiThread(() -> handleErrorResult(info));
} }
}; };
// ====== CARD RESULT HANDLERS ======
private void handleMagCardResult(Bundle info) { private void handleMagCardResult(Bundle info) {
android.util.Log.d("CreditCard", "=== MAGNETIC CARD DATA ==="); // Log dengan detail lengkap
logMagneticCardData(info);
// Update UI
String track1 = Utility.null2String(info.getString("TRACK1")); String track1 = Utility.null2String(info.getString("TRACK1"));
String track2 = Utility.null2String(info.getString("TRACK2")); String track2 = Utility.null2String(info.getString("TRACK2"));
String track3 = Utility.null2String(info.getString("TRACK3")); String track3 = Utility.null2String(info.getString("TRACK3"));
// Log detailed track data StringBuilder sb = new StringBuilder()
android.util.Log.d("CreditCard", "Track1: " + track1); .append(getString(R.string.card_mag_card_detected)).append("\n")
android.util.Log.d("CreditCard", "Track2: " + track2); .append("Track1: ").append(track1.isEmpty() ? "N/A" : track1).append("\n")
android.util.Log.d("CreditCard", "Track3: " + track3); .append("Track2: ").append(track2.isEmpty() ? "N/A" : track2).append("\n")
.append("Track3: ").append(track3.isEmpty() ? "N/A" : track3);
// Log error codes if available updateUI(sb.toString(), true);
}
private void handleICCardResult(Bundle info) {
// Log dengan detail lengkap
logICCardData(info);
// Update UI
String atr = info.getString("atr", "");
int cardType = info.getInt("cardType", -1);
StringBuilder sb = new StringBuilder();
sb.append(getString(R.string.card_ic_card_detected)).append("\n")
.append("ATR: ").append(atr.isEmpty() ? "N/A" : atr).append("\n");
if (cardType != -1) {
sb.append("Card Type: ").append(cardType).append("\n");
}
updateUI(sb.toString(), true);
}
private void handleRFCardResult(Bundle info) {
// Log dengan detail lengkap
logRFCardData(info);
// Update UI
String uuid = info.getString("uuid", "");
String ats = info.getString("ats", "");
int sak = info.getInt("sak", -1);
StringBuilder sb = new StringBuilder();
sb.append("RF/NFC Card Detected").append("\n")
.append("UUID: ").append(uuid.isEmpty() ? "N/A" : uuid).append("\n");
if (!ats.isEmpty()) {
sb.append("ATS: ").append(ats).append("\n");
}
if (sak != -1) {
sb.append("SAK: ").append(String.format("0x%02X", sak)).append("\n");
sb.append("Type: ").append(analyzeCardTypeBySAK(sak)).append("\n");
}
updateUI(sb.toString(), true);
}
private void handleErrorResult(Bundle info) {
// Log dengan detail lengkap
logCardError(info);
// Update UI
int code = info.getInt("code", -1);
String msg = info.getString("message", "Unknown error");
String error = "Error: " + msg + " (Code: " + code + ")";
updateUI(error, true);
}
// ====== ENHANCED LOGGING METHODS ======
private void logMagneticCardData(Bundle info) {
android.util.Log.d(TAG, "=======================================");
android.util.Log.d(TAG, " MAGNETIC CARD DETECTED ");
android.util.Log.d(TAG, "=======================================");
// Track Data
String track1 = Utility.null2String(info.getString("TRACK1"));
String track2 = Utility.null2String(info.getString("TRACK2"));
String track3 = Utility.null2String(info.getString("TRACK3"));
android.util.Log.d(TAG, "TRACK DATA:");
android.util.Log.d(TAG, " Track1: " + (track1.isEmpty() ? "N/A" : track1));
android.util.Log.d(TAG, " Track2: " + (track2.isEmpty() ? "N/A" : track2));
android.util.Log.d(TAG, " Track3: " + (track3.isEmpty() ? "N/A" : track3));
// Error Codes
int track1ErrorCode = info.getInt("track1ErrorCode", 0); int track1ErrorCode = info.getInt("track1ErrorCode", 0);
int track2ErrorCode = info.getInt("track2ErrorCode", 0); int track2ErrorCode = info.getInt("track2ErrorCode", 0);
int track3ErrorCode = info.getInt("track3ErrorCode", 0); int track3ErrorCode = info.getInt("track3ErrorCode", 0);
android.util.Log.d("CreditCard", "Track1 Error Code: " + track1ErrorCode); android.util.Log.d(TAG, "ERROR CODES:");
android.util.Log.d("CreditCard", "Track2 Error Code: " + track2ErrorCode); android.util.Log.d(TAG, " Track1 Error: " + track1ErrorCode);
android.util.Log.d("CreditCard", "Track3 Error Code: " + track3ErrorCode); android.util.Log.d(TAG, " Track2 Error: " + track2ErrorCode);
android.util.Log.d(TAG, " Track3 Error: " + track3ErrorCode);
// Log additional info if available // Additional Data
String pan = info.getString("pan", ""); String pan = info.getString("pan", "");
String serviceCode = info.getString("servicecode", ""); String servicecode = info.getString("servicecode", "");
if (!pan.isEmpty()) android.util.Log.d("CreditCard", "PAN: " + pan); String expiryDate = info.getString("expiry", "");
if (!serviceCode.isEmpty()) android.util.Log.d("CreditCard", "Service Code: " + serviceCode); String cardholderName = info.getString("cardholder", "");
StringBuilder sb = new StringBuilder() android.util.Log.d(TAG, "PARSED DATA:");
.append(getString(R.string.card_mag_card_detected)).append("\n") android.util.Log.d(TAG, " PAN: " + (pan.isEmpty() ? "N/A" : maskPAN(pan)));
.append("Track1:").append(track1).append("\n") android.util.Log.d(TAG, " Service Code: " + (servicecode.isEmpty() ? "N/A" : servicecode));
.append("Track2:").append(track2).append("\n") android.util.Log.d(TAG, " Expiry Date: " + (expiryDate.isEmpty() ? "N/A" : expiryDate));
.append("Track3:").append(track3); android.util.Log.d(TAG, " Cardholder: " + (cardholderName.isEmpty() ? "N/A" : cardholderName));
tvResult.setText(sb);
switchCheckCard(); // Raw Bundle Data
android.util.Log.d(TAG, "RAW BUNDLE DATA:");
android.util.Log.d(TAG, " " + bundleToString(info));
android.util.Log.d(TAG, "=======================================");
} }
private void handleICCardResult(Bundle info) { private void logICCardData(Bundle info) {
android.util.Log.d("CreditCard", "=== IC CARD DATA ==="); android.util.Log.d(TAG, "=======================================");
android.util.Log.d(TAG, " IC CARD DETECTED ");
android.util.Log.d(TAG, "=======================================");
String atr = info.getString("atr", ""); String atr = info.getString("atr", "");
int cardType = info.getInt("cardType", -1); int cardType = info.getInt("cardType", -1);
String cardTypeStr = info.getString("cardTypeStr", "");
int errorCode = info.getInt("errorCode", 0);
android.util.Log.d("CreditCard", "ATR: " + atr); android.util.Log.d(TAG, "BASIC INFO:");
android.util.Log.d("CreditCard", "Card Type: " + cardType); android.util.Log.d(TAG, " ATR: " + (atr.isEmpty() ? "N/A" : atr));
android.util.Log.d("CreditCard", "Full IC Card Data: " + bundleToString(info)); android.util.Log.d(TAG, " Card Type: " + cardType);
android.util.Log.d(TAG, " Card Type String: " + (cardTypeStr.isEmpty() ? "N/A" : cardTypeStr));
android.util.Log.d(TAG, " Error Code: " + errorCode);
StringBuilder sb = new StringBuilder(); // Parse ATR if available
sb.append(getString(R.string.card_ic_card_detected)).append("\n") if (!atr.isEmpty()) {
.append("ATR:").append(atr).append("\n"); android.util.Log.d(TAG, "ATR ANALYSIS:");
if (cardType != -1) { android.util.Log.d(TAG, " ATR Length: " + atr.length() + " characters");
sb.append("Card Type:").append(cardType).append("\n"); android.util.Log.d(TAG, " ATR Bytes: " + atr.length()/2 + " bytes");
} }
tvResult.setText(sb);
switchCheckCard(); // Check for additional fields
String[] possibleKeys = {"voltage", "protocol", "clockRate", "baudRate",
"historicalBytes", "interfaceBytes", "checkByte"};
android.util.Log.d(TAG, "ADDITIONAL DATA:");
for (String key : possibleKeys) {
if (info.containsKey(key)) {
android.util.Log.d(TAG, " " + key + ": " + info.get(key));
}
}
// Raw Bundle Data
android.util.Log.d(TAG, "RAW BUNDLE DATA:");
android.util.Log.d(TAG, " " + bundleToString(info));
android.util.Log.d(TAG, "=======================================");
} }
private void handleRFCardResult(Bundle info) { private void logRFCardData(Bundle info) {
android.util.Log.d("CreditCard", "=== RF/NFC CARD DATA ==="); android.util.Log.d(TAG, "=======================================");
android.util.Log.d(TAG, " RF/NFC CARD DETECTED ");
android.util.Log.d(TAG, "=======================================");
String uuid = info.getString("uuid", ""); String uuid = info.getString("uuid", "");
String ats = info.getString("ats", ""); String ats = info.getString("ats", "");
@ -266,54 +423,128 @@ public class CreditCardActivity extends AppCompatActivity {
int sak = info.getInt("sak", -1); int sak = info.getInt("sak", -1);
int cardCategory = info.getInt("cardCategory", -1); int cardCategory = info.getInt("cardCategory", -1);
byte[] atqa = info.getByteArray("atqa"); byte[] atqa = info.getByteArray("atqa");
int errorCode = info.getInt("errorCode", 0);
android.util.Log.d("CreditCard", "UUID: " + uuid); android.util.Log.d(TAG, "BASIC INFO:");
android.util.Log.d("CreditCard", "ATS: " + ats); android.util.Log.d(TAG, " UUID: " + (uuid.isEmpty() ? "N/A" : uuid));
android.util.Log.d("CreditCard", "Card Type: " + cardType); android.util.Log.d(TAG, " ATS: " + (ats.isEmpty() ? "N/A" : ats));
android.util.Log.d("CreditCard", "SAK: " + sak); android.util.Log.d(TAG, " Card Type: " + cardType);
android.util.Log.d("CreditCard", "Card Category: " + cardCategory); android.util.Log.d(TAG, " SAK: " + (sak == -1 ? "N/A" : String.format("0x%02X (%d)", sak, sak)));
if (atqa != null) { android.util.Log.d(TAG, " Card Category: " + cardCategory);
android.util.Log.d("CreditCard", "ATQA: " + ByteUtil.bytes2HexStr(atqa)); android.util.Log.d(TAG, " Error Code: " + errorCode);
}
android.util.Log.d("CreditCard", "Full RF Card Data: " + bundleToString(info));
StringBuilder sb = new StringBuilder(); if (atqa != null && atqa.length > 0) {
sb.append("RF Card Detected").append("\n") android.util.Log.d(TAG, " ATQA: " + ByteUtil.bytes2HexStr(atqa) +
.append("UUID: ").append(uuid).append("\n"); " (" + atqa.length + " bytes)");
if (!ats.isEmpty()) { } else {
sb.append("ATS: ").append(ats).append("\n"); android.util.Log.d(TAG, " ATQA: N/A");
} }
// Analyze card type based on SAK
if (sak != -1) { if (sak != -1) {
sb.append("SAK: ").append(String.format("0x%02X", sak)).append("\n"); String cardTypeAnalysis = analyzeCardTypeBySAK(sak);
android.util.Log.d(TAG, "CARD TYPE ANALYSIS:");
android.util.Log.d(TAG, " " + cardTypeAnalysis);
} }
tvResult.setText(sb);
switchCheckCard(); // Check for additional NFC fields
String[] possibleKeys = {"historicalBytes", "applicationData", "protocolInfo",
"maxDataRate", "supportedProtocols", "manufacturerData"};
android.util.Log.d(TAG, "ADDITIONAL DATA:");
for (String key : possibleKeys) {
if (info.containsKey(key)) {
Object value = info.get(key);
if (value instanceof byte[]) {
android.util.Log.d(TAG, " " + key + ": " +
ByteUtil.bytes2HexStr((byte[]) value));
} else {
android.util.Log.d(TAG, " " + key + ": " + value);
}
}
}
// Raw Bundle Data
android.util.Log.d(TAG, "RAW BUNDLE DATA:");
android.util.Log.d(TAG, " " + bundleToString(info));
android.util.Log.d(TAG, "=======================================");
} }
private void handleErrorResult(Bundle info) { private void logCardError(Bundle info) {
int code = info.getInt("code"); android.util.Log.e(TAG, "=======================================");
String msg = info.getString("message"); android.util.Log.e(TAG, " CARD READ ERROR ");
String error = "Error: " + msg + " (Code: " + code + ")"; android.util.Log.e(TAG, "=======================================");
tvResult.setText(error);
switchCheckCard(); int code = info.getInt("code", -1);
String message = info.getString("message", "");
String details = info.getString("details", "");
android.util.Log.e(TAG, "ERROR INFO:");
android.util.Log.e(TAG, " Error Code: " + code);
android.util.Log.e(TAG, " Error Message: " + (message.isEmpty() ? "N/A" : message));
android.util.Log.e(TAG, " Error Details: " + (details.isEmpty() ? "N/A" : details));
// Interpret common error codes
String interpretation = interpretErrorCode(code);
android.util.Log.e(TAG, " Interpretation: " + interpretation);
// Raw Bundle Data
android.util.Log.e(TAG, "RAW ERROR DATA:");
android.util.Log.e(TAG, " " + bundleToString(info));
android.util.Log.e(TAG, "=======================================");
} }
@Override // ====== HELPER METHODS ======
protected void onDestroy() { private String analyzeCardTypeBySAK(int sak) {
cancelCheckCard(); switch (sak & 0xFF) {
super.onDestroy(); case 0x00: return "MIFARE Ultralight";
} case 0x04: return "MIFARE Classic 1K";
case 0x08: return "MIFARE Classic 1K";
private void cancelCheckCard() { case 0x09: return "MIFARE Mini";
try { case 0x18: return "MIFARE Classic 4K";
MyApplication.app.readCardOptV2.cardOff(CardType.NFC.getValue()); case 0x20: return "MIFARE Plus/DESFire";
MyApplication.app.readCardOptV2.cardOff(CardType.IC.getValue()); case 0x28: return "JCOP 30";
MyApplication.app.readCardOptV2.cancelCheckCard(); case 0x38: return "MIFARE DESFire";
} catch (Exception e) { case 0x88: return "Infineon my-d move";
e.printStackTrace(); case 0x98: return "Gemplus MPCOS";
default: return "Unknown card type (SAK: 0x" + String.format("%02X", sak) + ")";
} }
} }
private String maskPAN(String pan) {
if (pan == null || pan.length() < 8) {
return pan;
}
String firstFour = pan.substring(0, 4);
String lastFour = pan.substring(pan.length() - 4);
StringBuilder middle = new StringBuilder();
for (int i = 0; i < pan.length() - 8; i++) {
middle.append("*");
}
return firstFour + middle.toString() + lastFour;
}
private String interpretErrorCode(int errorCode) {
switch (errorCode) {
case 0: return "No Error";
case -1: return "General Error";
case -2: return "Timeout";
case -3: return "User Cancelled";
case -4: return "Card Removed";
case -5: return "Hardware Error";
case -6: return "Communication Error";
case -7: return "Card Not Supported";
case -8: return "Invalid Parameter";
case -9: return "Service Not Available";
case -10: return "Permission Denied";
default: return "Unknown Error Code: " + errorCode;
}
}
/** /**
* Helper method to convert Bundle to readable string for logging * Helper method to convert Bundle to readable string for logging
*/ */
@ -338,4 +569,46 @@ public class CreditCardActivity extends AppCompatActivity {
sb.append("}"); sb.append("}");
return sb.toString(); return sb.toString();
} }
// ====== LIFECYCLE METHODS ======
@Override
protected void onDestroy() {
android.util.Log.d(TAG, "onDestroy called");
cancelCheckCard();
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
android.util.Log.d(TAG, "onPause called");
// Optionally cancel card check when app goes to background
if (checkingCard) {
android.util.Log.d(TAG, "App paused, stopping card check");
stopCardCheck();
}
}
@Override
protected void onResume() {
super.onResume();
android.util.Log.d(TAG, "onResume called");
// Check PaySDK status when returning to app
checkPaySDKStatus();
}
private void cancelCheckCard() {
try {
if (MyApplication.app != null && MyApplication.app.readCardOptV2 != null) {
android.util.Log.d(TAG, "Cancelling card operations...");
MyApplication.app.readCardOptV2.cardOff(CardType.NFC.getValue());
MyApplication.app.readCardOptV2.cardOff(CardType.IC.getValue());
MyApplication.app.readCardOptV2.cancelCheckCard();
android.util.Log.d(TAG, "Card operations cancelled successfully");
}
} catch (Exception e) {
android.util.Log.e(TAG, "Error cancelling card operations: " + e.getMessage());
e.printStackTrace();
}
}
} }