diff --git a/app/src/main/java/com/example/bdkipoc/kredit/CreditCardActivity.java b/app/src/main/java/com/example/bdkipoc/kredit/CreditCardActivity.java index bf63b06..44cfa3a 100644 --- a/app/src/main/java/com/example/bdkipoc/kredit/CreditCardActivity.java +++ b/app/src/main/java/com/example/bdkipoc/kredit/CreditCardActivity.java @@ -15,6 +15,8 @@ import com.sunmi.pay.hardware.aidl.AidlConstants.CardType; import com.sunmi.pay.hardware.aidlv2.readcard.CheckCardCallbackV2; public class CreditCardActivity extends AppCompatActivity { + private static final String TAG = "CreditCard"; + private TextView tvResult; private Button btnCheckCard; private boolean checkingCard; @@ -22,22 +24,26 @@ public class CreditCardActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - android.util.Log.d("CreditCard", "onCreate called"); + android.util.Log.d(TAG, "onCreate called"); setContentView(R.layout.activity_credit_card); initView(); // Check PaySDK status + checkPaySDKStatus(); + } + + private void checkPaySDKStatus() { if (MyApplication.app != null) { - android.util.Log.d("CreditCard", "MyApplication.app exists"); - android.util.Log.d("CreditCard", "PaySDK connected: " + MyApplication.app.isConnectPaySDK()); - android.util.Log.d("CreditCard", "readCardOptV2 null: " + (MyApplication.app.readCardOptV2 == null)); + android.util.Log.d(TAG, "MyApplication.app exists"); + android.util.Log.d(TAG, "PaySDK connected: " + MyApplication.app.isConnectPaySDK()); + android.util.Log.d(TAG, "readCardOptV2 null: " + (MyApplication.app.readCardOptV2 == null)); } else { - android.util.Log.e("CreditCard", "MyApplication.app is null"); + android.util.Log.e(TAG, "MyApplication.app is null"); } } private void initView() { - android.util.Log.d("CreditCard", "initView called"); + android.util.Log.d(TAG, "initView called"); // Setup Toolbar as ActionBar 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); 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 -> { - android.util.Log.d("CreditCard", "Button clicked!"); + android.util.Log.d(TAG, "Button clicked!"); switchCheckCard(); }); } else { - android.util.Log.e("CreditCard", "Button not found!"); + android.util.Log.e(TAG, "Button not found!"); } if (tvResult != null) { tvResult.setText("Ready to scan card..."); - android.util.Log.d("CreditCard", "TextView initialized"); + android.util.Log.d(TAG, "TextView initialized"); } 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() { - android.util.Log.d("CreditCard", "switchCheckCard called, checkingCard: " + checkingCard); + android.util.Log.d(TAG, "switchCheckCard called, checkingCard: " + checkingCard); try { if (checkingCard) { - android.util.Log.d("CreditCard", "Stopping card check"); - MyApplication.app.readCardOptV2.cancelCheckCard(); - btnCheckCard.setText(R.string.card_start_check_card); - checkingCard = false; + android.util.Log.d(TAG, "Stopping card check"); + stopCardCheck(); } else { - android.util.Log.d("CreditCard", "Starting card check"); - checkCreditCard(); - checkingCard = true; - btnCheckCard.setText(R.string.card_stop_check_card); + android.util.Log.d(TAG, "Starting card check"); + startCardCheck(); } } 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(); + 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() { try { - // Ensure PaySDK is bound first - if (MyApplication.app == null) { - tvResult.setText("Error: Application not initialized"); - android.util.Log.e("CreditCard", "MyApplication.app is null"); + // Validate application state + if (!validateApplicationState()) { return; } // If not connected, try to bind first if (!MyApplication.app.isConnectPaySDK()) { 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(); - // Wait a bit and retry + // Wait and retry btnCheckCard.postDelayed(() -> { if (MyApplication.app.isConnectPaySDK() && MyApplication.app.readCardOptV2 != null) { startCardScan(); } else { - tvResult.setText("Error: Failed to connect to PaySDK"); - checkingCard = false; - btnCheckCard.setText(R.string.card_start_check_card); + updateUI("Error: Failed to connect to PaySDK", false); } - }, 2000); // Wait 2 seconds + }, 2000); return; } if (MyApplication.app.readCardOptV2 == null) { - tvResult.setText("Error: Card reader not initialized"); - android.util.Log.e("CreditCard", "readCardOptV2 is null"); + updateUI("Error: Card reader not initialized", false); + android.util.Log.e(TAG, "readCardOptV2 is null"); return; } @@ -134,36 +159,61 @@ public class CreditCardActivity extends AppCompatActivity { } catch (Exception e) { e.printStackTrace(); - android.util.Log.e("CreditCard", "Error in checkCreditCard: " + e.getMessage()); - tvResult.setText("Error starting card scan: " + e.getMessage()); + android.util.Log.e(TAG, "Error in checkCreditCard: " + 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() { try { 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("CreditCard", "Starting checkCard with cardType: " + cardType); + android.util.Log.d(TAG, "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); } catch (Exception e) { e.printStackTrace(); - android.util.Log.e("CreditCard", "Error in startCardScan: " + e.getMessage()); - tvResult.setText("Error starting card scan: " + e.getMessage()); + android.util.Log.e(TAG, "Error in startCardScan: " + 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() { @Override public void findMagCard(Bundle info) throws RemoteException { + android.util.Log.d(TAG, "findMagCard callback triggered"); runOnUiThread(() -> handleMagCardResult(info)); } @Override public void findICCard(String atr) throws RemoteException { + android.util.Log.d(TAG, "findICCard callback triggered with ATR: " + atr); Bundle info = new Bundle(); info.putString("atr", atr); runOnUiThread(() -> handleICCardResult(info)); @@ -171,7 +221,7 @@ public class CreditCardActivity extends AppCompatActivity { @Override 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(); info.putString("uuid", uuid); runOnUiThread(() -> handleRFCardResult(info)); @@ -179,6 +229,7 @@ public class CreditCardActivity extends AppCompatActivity { @Override 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(); info.putInt("code", code); info.putString("message", message); @@ -187,78 +238,184 @@ public class CreditCardActivity extends AppCompatActivity { @Override public void findICCardEx(Bundle info) throws RemoteException { + android.util.Log.d(TAG, "findICCardEx callback triggered"); runOnUiThread(() -> handleICCardResult(info)); } @Override public void findRFCardEx(Bundle info) throws RemoteException { + android.util.Log.d(TAG, "findRFCardEx callback triggered"); runOnUiThread(() -> handleRFCardResult(info)); } @Override public void onErrorEx(Bundle info) throws RemoteException { + android.util.Log.e(TAG, "onErrorEx callback triggered"); runOnUiThread(() -> handleErrorResult(info)); } }; + // ====== CARD RESULT HANDLERS ====== 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 track2 = Utility.null2String(info.getString("TRACK2")); String track3 = Utility.null2String(info.getString("TRACK3")); - // Log detailed track data - android.util.Log.d("CreditCard", "Track1: " + track1); - android.util.Log.d("CreditCard", "Track2: " + track2); - android.util.Log.d("CreditCard", "Track3: " + track3); + StringBuilder sb = new StringBuilder() + .append(getString(R.string.card_mag_card_detected)).append("\n") + .append("Track1: ").append(track1.isEmpty() ? "N/A" : track1).append("\n") + .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 track2ErrorCode = info.getInt("track2ErrorCode", 0); int track3ErrorCode = info.getInt("track3ErrorCode", 0); - android.util.Log.d("CreditCard", "Track1 Error Code: " + track1ErrorCode); - android.util.Log.d("CreditCard", "Track2 Error Code: " + track2ErrorCode); - android.util.Log.d("CreditCard", "Track3 Error Code: " + track3ErrorCode); + android.util.Log.d(TAG, "ERROR CODES:"); + android.util.Log.d(TAG, " Track1 Error: " + track1ErrorCode); + 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 serviceCode = info.getString("servicecode", ""); - if (!pan.isEmpty()) android.util.Log.d("CreditCard", "PAN: " + pan); - if (!serviceCode.isEmpty()) android.util.Log.d("CreditCard", "Service Code: " + serviceCode); + String servicecode = info.getString("servicecode", ""); + String expiryDate = info.getString("expiry", ""); + String cardholderName = info.getString("cardholder", ""); - StringBuilder sb = new StringBuilder() - .append(getString(R.string.card_mag_card_detected)).append("\n") - .append("Track1:").append(track1).append("\n") - .append("Track2:").append(track2).append("\n") - .append("Track3:").append(track3); - tvResult.setText(sb); - switchCheckCard(); + android.util.Log.d(TAG, "PARSED DATA:"); + android.util.Log.d(TAG, " PAN: " + (pan.isEmpty() ? "N/A" : maskPAN(pan))); + android.util.Log.d(TAG, " Service Code: " + (servicecode.isEmpty() ? "N/A" : servicecode)); + android.util.Log.d(TAG, " Expiry Date: " + (expiryDate.isEmpty() ? "N/A" : expiryDate)); + android.util.Log.d(TAG, " Cardholder: " + (cardholderName.isEmpty() ? "N/A" : cardholderName)); + + // 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) { - android.util.Log.d("CreditCard", "=== IC CARD DATA ==="); + private void logICCardData(Bundle info) { + android.util.Log.d(TAG, "======================================="); + android.util.Log.d(TAG, " IC CARD DETECTED "); + android.util.Log.d(TAG, "======================================="); String atr = info.getString("atr", ""); 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("CreditCard", "Card Type: " + cardType); - android.util.Log.d("CreditCard", "Full IC Card Data: " + bundleToString(info)); + android.util.Log.d(TAG, "BASIC INFO:"); + android.util.Log.d(TAG, " ATR: " + (atr.isEmpty() ? "N/A" : atr)); + 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(); - sb.append(getString(R.string.card_ic_card_detected)).append("\n") - .append("ATR:").append(atr).append("\n"); - if (cardType != -1) { - sb.append("Card Type:").append(cardType).append("\n"); + // Parse ATR if available + if (!atr.isEmpty()) { + android.util.Log.d(TAG, "ATR ANALYSIS:"); + android.util.Log.d(TAG, " ATR Length: " + atr.length() + " characters"); + 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) { - android.util.Log.d("CreditCard", "=== RF/NFC CARD DATA ==="); + private void logRFCardData(Bundle info) { + 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 ats = info.getString("ats", ""); @@ -266,54 +423,128 @@ public class CreditCardActivity extends AppCompatActivity { int sak = info.getInt("sak", -1); int cardCategory = info.getInt("cardCategory", -1); byte[] atqa = info.getByteArray("atqa"); + int errorCode = info.getInt("errorCode", 0); - android.util.Log.d("CreditCard", "UUID: " + uuid); - android.util.Log.d("CreditCard", "ATS: " + ats); - android.util.Log.d("CreditCard", "Card Type: " + cardType); - android.util.Log.d("CreditCard", "SAK: " + sak); - android.util.Log.d("CreditCard", "Card Category: " + cardCategory); - if (atqa != null) { - android.util.Log.d("CreditCard", "ATQA: " + ByteUtil.bytes2HexStr(atqa)); - } - android.util.Log.d("CreditCard", "Full RF Card Data: " + bundleToString(info)); + android.util.Log.d(TAG, "BASIC INFO:"); + android.util.Log.d(TAG, " UUID: " + (uuid.isEmpty() ? "N/A" : uuid)); + android.util.Log.d(TAG, " ATS: " + (ats.isEmpty() ? "N/A" : ats)); + android.util.Log.d(TAG, " Card Type: " + cardType); + android.util.Log.d(TAG, " SAK: " + (sak == -1 ? "N/A" : String.format("0x%02X (%d)", sak, sak))); + android.util.Log.d(TAG, " Card Category: " + cardCategory); + android.util.Log.d(TAG, " Error Code: " + errorCode); - StringBuilder sb = new StringBuilder(); - sb.append("RF Card Detected").append("\n") - .append("UUID: ").append(uuid).append("\n"); - if (!ats.isEmpty()) { - sb.append("ATS: ").append(ats).append("\n"); + if (atqa != null && atqa.length > 0) { + android.util.Log.d(TAG, " ATQA: " + ByteUtil.bytes2HexStr(atqa) + + " (" + atqa.length + " bytes)"); + } else { + android.util.Log.d(TAG, " ATQA: N/A"); } + + // Analyze card type based on SAK 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) { - int code = info.getInt("code"); - String msg = info.getString("message"); - String error = "Error: " + msg + " (Code: " + code + ")"; - tvResult.setText(error); - switchCheckCard(); + private void logCardError(Bundle info) { + android.util.Log.e(TAG, "======================================="); + android.util.Log.e(TAG, " CARD READ ERROR "); + android.util.Log.e(TAG, "======================================="); + + 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 - protected void onDestroy() { - cancelCheckCard(); - super.onDestroy(); - } - - private void cancelCheckCard() { - try { - MyApplication.app.readCardOptV2.cardOff(CardType.NFC.getValue()); - MyApplication.app.readCardOptV2.cardOff(CardType.IC.getValue()); - MyApplication.app.readCardOptV2.cancelCheckCard(); - } catch (Exception e) { - e.printStackTrace(); + // ====== HELPER METHODS ====== + private String analyzeCardTypeBySAK(int sak) { + switch (sak & 0xFF) { + case 0x00: return "MIFARE Ultralight"; + case 0x04: return "MIFARE Classic 1K"; + case 0x08: return "MIFARE Classic 1K"; + case 0x09: return "MIFARE Mini"; + case 0x18: return "MIFARE Classic 4K"; + case 0x20: return "MIFARE Plus/DESFire"; + case 0x28: return "JCOP 30"; + case 0x38: return "MIFARE DESFire"; + case 0x88: return "Infineon my-d move"; + 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 */ @@ -338,4 +569,46 @@ public class CreditCardActivity extends AppCompatActivity { sb.append("}"); 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(); + } + } } \ No newline at end of file