implement SDK di MainActivity

This commit is contained in:
2025-06-11 23:07:35 +07:00
parent 991f77dabe
commit 13ab6b717e
28 changed files with 3153 additions and 98 deletions

View File

@@ -1,18 +1,29 @@
package com.example.bdkipoc;
// Import SDK Sunmi
import sunmi.paylib.SunmiPayKernel;
import com.sunmi.pay.hardware.aidlv2.emv.EMVOptV2;
import com.sunmi.pay.hardware.aidlv2.system.BasicOptV2;
import com.sunmi.pay.hardware.aidlv2.pinpad.PinPadOptV2;
import com.sunmi.pay.hardware.aidlv2.readcard.ReadCardOptV2;
import com.sunmi.pay.hardware.aidlv2.security.SecurityOptV2;
import com.sunmi.pay.hardware.aidlv2.tax.TaxOptV2;
import com.sunmi.pay.hardware.aidlv2.etc.ETCOptV2;
import com.sunmi.pay.hardware.aidlv2.print.PrinterOptV2;
import android.util.Log;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.WindowManager;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.cardview.widget.CardView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
@@ -21,9 +32,81 @@ import com.google.android.material.button.MaterialButton;
public class MainActivity extends AppCompatActivity {
// SDK Variables
private EMVOptV2 emvOptV2;
private BasicOptV2 basicOptV2;
private PinPadOptV2 pinPadOptV2;
private ReadCardOptV2 readCardOptV2;
private SecurityOptV2 securityOptV2;
private TaxOptV2 taxOptV2;
private ETCOptV2 etcOptV2;
private PrinterOptV2 printerOptV2;
private boolean connectPaySDK = false;
// UI Variables
private boolean isExpanded = false; // False = showing only 9 main menus, True = showing all 15 menus
private MaterialButton btnLainnya;
public void bindPaySDKService() {
Log.d("SDK_CHECK", "Starting SDK initialization...");
try {
final SunmiPayKernel payKernel = SunmiPayKernel.getInstance();
Log.d("SDK_CHECK", "SunmiPayKernel instance obtained successfully");
payKernel.initPaySDK(this, new SunmiPayKernel.ConnectCallback() {
@Override
public void onConnectPaySDK() {
Log.d("SDK_CHECK", "✅ SDK Connected Successfully!");
try {
emvOptV2 = payKernel.mEMVOptV2;
basicOptV2 = payKernel.mBasicOptV2;
pinPadOptV2 = payKernel.mPinPadOptV2;
readCardOptV2 = payKernel.mReadCardOptV2;
securityOptV2 = payKernel.mSecurityOptV2;
taxOptV2 = payKernel.mTaxOptV2;
etcOptV2 = payKernel.mETCOptV2;
printerOptV2 = payKernel.mPrinterOptV2;
// Log detail komponen
Log.d("SDK_CHECK", "EMVOptV2: " + (emvOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "BasicOptV2: " + (basicOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "PinPadOptV2: " + (pinPadOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "ReadCardOptV2: " + (readCardOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "SecurityOptV2: " + (securityOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "TaxOptV2: " + (taxOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "ETCOptV2: " + (etcOptV2 != null ? "✅ Available" : "❌ Not Available"));
Log.d("SDK_CHECK", "PrinterOptV2: " + (printerOptV2 != null ? "✅ Available" : "❌ Not Available"));
connectPaySDK = true;
Toast.makeText(getApplicationContext(), "✅ Sunmi SDK Connected!", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e("SDK_CHECK", "❌ Error initializing SDK components: " + e.getMessage());
Toast.makeText(getApplicationContext(), "SDK Connection Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@Override
public void onDisconnectPaySDK() {
Log.w("SDK_CHECK", "❌ SDK Disconnected");
connectPaySDK = false;
emvOptV2 = null;
basicOptV2 = null;
pinPadOptV2 = null;
readCardOptV2 = null;
securityOptV2 = null;
taxOptV2 = null;
etcOptV2 = null;
printerOptV2 = null;
Toast.makeText(getApplicationContext(), "❌ Sunmi SDK Disconnected", Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
Log.e("SDK_CHECK", "❌ Critical Error - Failed to initialize SDK: " + e.getMessage());
e.printStackTrace();
Toast.makeText(this, "❌ Failed to initialize Sunmi SDK: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
@@ -67,6 +150,9 @@ public class MainActivity extends AppCompatActivity {
// Setup menu listeners
setupMenuListeners();
// Initialize Sunmi SDK
bindPaySDKService();
}
private void setupInitialMenuState() {
@@ -99,7 +185,9 @@ public class MainActivity extends AppCompatActivity {
// Set initial button text
isExpanded = false;
btnLainnya.setText("Lainnya");
if (btnLainnya != null) {
btnLainnya.setText("Lainnya");
}
}
private void checkTransactionCompletion() {
@@ -157,26 +245,49 @@ public class MainActivity extends AppCompatActivity {
CardView cardView = findViewById(cardId);
if (cardView != null) {
cardView.setOnClickListener(v -> {
Log.d("MENU_CLICK", "Card clicked: " + getResources().getResourceEntryName(cardId));
if (cardId == R.id.card_kartu_kredit) {
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
// Check SDK before navigating to payment
if (connectPaySDK) {
Log.d("NAVIGATION", "Navigating to PaymentActivity - Kartu Kredit");
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
} else {
Toast.makeText(this, "SDK belum terhubung. Harap tunggu...", Toast.LENGTH_SHORT).show();
}
} else if (cardId == R.id.card_kartu_debit) {
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
if (connectPaySDK) {
Log.d("NAVIGATION", "Navigating to PaymentActivity - Kartu Debit");
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
} else {
Toast.makeText(this, "SDK belum terhubung. Harap tunggu...", Toast.LENGTH_SHORT).show();
}
} else if (cardId == R.id.card_qris) {
Log.d("NAVIGATION", "Navigating to QrisActivity");
startActivity(new Intent(MainActivity.this, QrisActivity.class));
} else if (cardId == R.id.card_uang_elektronik) {
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
if (connectPaySDK) {
Log.d("NAVIGATION", "Navigating to PaymentActivity - Uang Elektronik");
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
} else {
Toast.makeText(this, "SDK belum terhubung. Harap tunggu...", Toast.LENGTH_SHORT).show();
}
} else if (cardId == R.id.card_cetak_ulang) {
Log.d("NAVIGATION", "Navigating to TransactionActivity");
startActivity(new Intent(MainActivity.this, TransactionActivity.class));
} else if (cardId == R.id.card_settlement) {
Log.d("NAVIGATION", "Navigating to SettlementActivity");
startActivity(new Intent(MainActivity.this, SettlementActivity.class));
} else if (cardId == R.id.card_histori) {
Log.d("NAVIGATION", "Navigating to HistoryActivity");
startActivity(new Intent(MainActivity.this, HistoryActivity.class));
} else if (cardId == R.id.card_bantuan) {
Toast.makeText(this, "Bantuan - Coming Soon", Toast.LENGTH_SHORT).show();
} else if (cardId == R.id.card_info_toko) {
Toast.makeText(this, "Info Toko - Coming Soon", Toast.LENGTH_SHORT).show();
} else if (cardId == R.id.card_dummy_menu_1) {
Toast.makeText(this, "Dummy Menu 1 - Coming Soon", Toast.LENGTH_SHORT).show();
// Use dummy menu 1 untuk SDK test
testSDKIntegration();
} else if (cardId == R.id.card_dummy_menu_2) {
Toast.makeText(this, "Dummy Menu 2 - Coming Soon", Toast.LENGTH_SHORT).show();
} else if (cardId == R.id.card_dummy_menu_3) {
@@ -206,49 +317,123 @@ public class MainActivity extends AppCompatActivity {
};
// Set up "Lainnya" button click listener
btnLainnya.setOnClickListener(v -> {
isExpanded = !isExpanded;
if (isExpanded) {
// Show the 6 dummy menus with animation
for (CardView card : toggleableCards) {
if (card != null) {
card.setVisibility(View.VISIBLE);
card.setAlpha(0f);
card.animate()
.alpha(1f)
.setDuration(300)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
if (btnLainnya != null) {
btnLainnya.setOnClickListener(v -> {
Log.d("MENU_TOGGLE", "Lainnya button clicked. Current state: " + (isExpanded ? "expanded" : "collapsed"));
isExpanded = !isExpanded;
if (isExpanded) {
// Show the 6 dummy menus with animation
for (CardView card : toggleableCards) {
if (card != null) {
card.setVisibility(View.VISIBLE);
card.setAlpha(0f);
card.animate()
.alpha(1f)
.setDuration(300)
.setInterpolator(new AccelerateDecelerateInterpolator())
.start();
}
}
}
btnLainnya.setText("Tampilkan Lebih Sedikit");
} else {
// Hide the 6 dummy menus with animation
for (CardView card : toggleableCards) {
if (card != null) {
card.animate()
.alpha(0f)
.setDuration(300)
.setInterpolator(new AccelerateDecelerateInterpolator())
.withEndAction(() -> card.setVisibility(View.GONE))
.start();
btnLainnya.setText("Tampilkan Lebih Sedikit");
} else {
// Hide the 6 dummy menus with animation
for (CardView card : toggleableCards) {
if (card != null) {
card.animate()
.alpha(0f)
.setDuration(300)
.setInterpolator(new AccelerateDecelerateInterpolator())
.withEndAction(() -> card.setVisibility(View.GONE))
.start();
}
}
btnLainnya.setText("Lainnya");
}
btnLainnya.setText("Lainnya");
}
});
});
}
// Set up scan dan bayar card click listener
LinearLayout scanBayarContent = findViewById(R.id.scan_bayar_content);
if (scanBayarContent != null) {
scanBayarContent.setOnClickListener(v -> {
Log.d("NAVIGATION", "Scan dan Bayar clicked - Navigating to QrisActivity");
// Navigate to QRIS payment activity
startActivity(new Intent(MainActivity.this, QrisActivity.class));
});
} else {
Log.w("MENU_SETUP", "scan_bayar_content not found in layout");
}
}
private void testSDKIntegration() {
StringBuilder testResult = new StringBuilder();
testResult.append("=== SUNMI SDK INTEGRATION TEST ===\n\n");
// Test 1: SDK Connection Status
testResult.append("1. SDK Connection: ");
if (connectPaySDK) {
testResult.append("✅ CONNECTED\n");
} else {
testResult.append("❌ NOT CONNECTED\n");
}
// Test 2: Component Availability
testResult.append("\n2. SDK Components:\n");
testResult.append(" - EMVOptV2: ").append(emvOptV2 != null ? "" : "").append("\n");
testResult.append(" - BasicOptV2: ").append(basicOptV2 != null ? "" : "").append("\n");
testResult.append(" - PinPadOptV2: ").append(pinPadOptV2 != null ? "" : "").append("\n");
testResult.append(" - ReadCardOptV2: ").append(readCardOptV2 != null ? "" : "").append("\n");
testResult.append(" - SecurityOptV2: ").append(securityOptV2 != null ? "" : "").append("\n");
testResult.append(" - TaxOptV2: ").append(taxOptV2 != null ? "" : "").append("\n");
testResult.append(" - ETCOptV2: ").append(etcOptV2 != null ? "" : "").append("\n");
testResult.append(" - PrinterOptV2: ").append(printerOptV2 != null ? "" : "").append("\n");
// Test 3: Basic Function Tests
testResult.append("\n3. Function Tests:\n");
if (connectPaySDK) {
try {
if (basicOptV2 != null) {
testResult.append(" - BasicOpt: ✅ Ready\n");
}
if (printerOptV2 != null) {
testResult.append(" - Printer: ✅ Ready\n");
}
if (emvOptV2 != null) {
testResult.append(" - EMV: ✅ Ready\n");
}
testResult.append("\n✅ SDK Integration: SUCCESS!");
} catch (Exception e) {
testResult.append(" - Error: ❌ ").append(e.getMessage()).append("\n");
testResult.append("\n❌ SDK Integration: PARTIAL");
}
} else {
testResult.append(" - Cannot test: SDK not connected\n");
testResult.append("\n❌ SDK Integration: FAILED");
}
Log.d("SDK_TEST", testResult.toString());
// Show result in a dialog
showSDKTestDialog(testResult.toString());
}
private void showSDKTestDialog(String testResult) {
new AlertDialog.Builder(this)
.setTitle("Sunmi SDK Integration Test")
.setMessage(testResult)
.setPositiveButton("OK", null)
.setNeutralButton("Copy to Log", (dialog, which) -> {
Log.i("SDK_TEST_RESULT", testResult);
Toast.makeText(this, "Test result copied to log", Toast.LENGTH_SHORT).show();
})
.show();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);

View File

@@ -488,6 +488,8 @@ public class PaymentActivity extends AppCompatActivity {
} else {
navigateBack();
}
super.onBackPressed();
}
@Override

View File

@@ -520,6 +520,7 @@ public class PinActivity extends AppCompatActivity {
return;
}
navigateBack();
super.onBackPressed();
}
@Override

View File

@@ -898,6 +898,7 @@ public class QrisResultActivity extends AppCompatActivity {
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finishAffinity();
super.onBackPressed();
}
private void pollPendingPaymentLog(final String orderId) {

View File

@@ -834,5 +834,6 @@ public class ReceiptActivity extends AppCompatActivity {
public void onBackPressed() {
// Use the smart back navigation
handleBackNavigation();
super.onBackPressed();
}
}

View File

@@ -44,6 +44,8 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Calendar;
import java.util.Collections;
import android.app.DatePickerDialog;
import android.widget.DatePicker;
@@ -464,7 +466,7 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
}
// ✅ SORT SEARCH RESULTS by date
filteredList.sort((t1, t2) -> {
Collections.sort(filteredList, (t1, t2) -> {
try {
Date date1 = parseCreatedAtDate(t1.createdAt);
Date date2 = parseCreatedAtDate(t2.createdAt);
@@ -699,7 +701,7 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
transactionList.addAll(transactions);
// ✅ CRITICAL: FORCE SORT AGAIN after adding to main list
transactionList.sort((t1, t2) -> {
Collections.sort(filteredList, (t1, t2) -> {
try {
Date date1 = parseCreatedAtDate(t1.createdAt);
Date date2 = parseCreatedAtDate(t2.createdAt);
@@ -794,7 +796,13 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
for (Transaction tx : rawTransactions) {
String refId = tx.referenceId;
groupedByRef.computeIfAbsent(refId, k -> new ArrayList<>()).add(tx);
List<Transaction> list = groupedByRef.get(refId);
if (list == null) {
list = new ArrayList<>();
groupedByRef.put(refId, list);
}
list.add(tx);
}
List<Transaction> deduplicatedList = new ArrayList<>();
@@ -811,7 +819,7 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
Log.d("TransactionActivity", "✅ Unique transaction: " + referenceId);
} else {
// Multiple transactions with same reference_id - sort group by date first
group.sort((t1, t2) -> {
Collections.sort(group, (t1, t2) -> {
try {
Date date1 = parseCreatedAtDate(t1.createdAt);
Date date2 = parseCreatedAtDate(t2.createdAt);

View File

@@ -25,7 +25,8 @@
android:focusable="true"
android:padding="4dp"
android:src="@android:drawable/ic_menu_revert"
android:tint="@android:color/white" />
app:tint="@android:color/white" />
<!-- Title -->
<TextView

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#F5F5F5"
@@ -22,7 +23,7 @@
android:clickable="true"
android:focusable="true"
android:src="@android:drawable/ic_menu_revert"
android:tint="@android:color/white" />
app:tint="@android:color/white" />
<TextView
android:layout_width="wrap_content"

View File

@@ -139,7 +139,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_credit_card"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -172,7 +172,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_debit_card"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -205,7 +205,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qris"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -239,7 +239,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_e_money"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -272,7 +272,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_reprint"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -305,7 +305,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_settlement"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -339,7 +339,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_history"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -373,7 +373,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_help"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -407,7 +407,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_store_info"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -442,7 +442,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -476,7 +476,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -510,7 +510,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -545,7 +545,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -579,7 +579,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -613,7 +613,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="#E31937"/>
app:tint="#E31937"/>
<TextView
android:layout_width="wrap_content"
@@ -669,7 +669,7 @@
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_qr_code"
android:tint="@android:color/white"/>
app:tint="@android:color/white"/>
<LinearLayout
android:layout_width="0dp"

View File

@@ -233,7 +233,7 @@
android:src="@drawable/ic_backspace"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:padding="12dp"
android:tint="#666666"/>
app:tint="#666666"/>
</LinearLayout>
</GridLayout>

View File

@@ -52,7 +52,7 @@
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_arrow_back"
android:tint="@android:color/white"
app:tint="@android:color/white"
android:contentDescription="Kembali" />
<!-- Title Text -->
@@ -479,7 +479,7 @@
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_print"
android:tint="#666666"
app:tint="#666666"
android:layout_marginEnd="8dp"/>
<TextView
@@ -509,7 +509,7 @@
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@drawable/ic_email"
android:tint="#666666"
app:tint="#666666"
android:layout_marginEnd="8dp"/>
<TextView

View File

@@ -25,7 +25,7 @@
android:focusable="true"
android:padding="4dp"
android:src="@android:drawable/ic_menu_revert"
android:tint="@android:color/white" />
app:tint="@android:color/white" />
<!-- Title -->
<TextView

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
@@ -17,7 +18,7 @@
android:background="#F7FAFC"
android:padding="8dp"
android:src="@android:drawable/ic_menu_gallery"
android:tint="#E53E3E" />
app:tint="#E53E3E" />
<!-- Content -->
<LinearLayout
@@ -67,4 +68,4 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>