fixed ecr connection issues
This commit is contained in:
parent
60fbc471af
commit
acea64c89b
@ -156,6 +156,9 @@ public class MainActivity extends AppCompatActivity implements
|
|||||||
// Initialize special back handling fragments
|
// Initialize special back handling fragments
|
||||||
initSpecialBackHandlingFragments();
|
initSpecialBackHandlingFragments();
|
||||||
|
|
||||||
|
// ECR serial receive must live on Activity — MainFragment destroy clears listeners.
|
||||||
|
registerEcrSerialBridge();
|
||||||
|
|
||||||
final Handler handler = new Handler(Looper.getMainLooper());
|
final Handler handler = new Handler(Looper.getMainLooper());
|
||||||
handler.postDelayed(new Runnable() {
|
handler.postDelayed(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@ -167,6 +170,23 @@ public class MainActivity extends AppCompatActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void registerEcrSerialBridge() {
|
||||||
|
boolean ecrOn = SystemParamsOperation.getInstance().getECRStatus();
|
||||||
|
boolean cmhlOn = SystemParamsOperation.getInstance().isCMHLEnabled();
|
||||||
|
LogUtil.d(TAG, "RegisterEcrSerialBridge ecr=" + ecrOn + " cmhl=" + cmhlOn);
|
||||||
|
|
||||||
|
ECRHelper.INSTANCE.initSerialPort(getApplicationContext());
|
||||||
|
ECRHelper.INSTANCE.setOnECRReceive(bytes -> {
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
LogUtil.d(TAG, "ECR bridge forwarding len=" + bytes.length);
|
||||||
|
sharedViewModel.ecrSerialData.postValue(bytes);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void initKey(){
|
private void initKey(){
|
||||||
// SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius");
|
// SystemParamsOperation.getInstance().setTmsAddress("https://api-tms-uat.kbzbank.com:8443/sirius");
|
||||||
@ -443,6 +463,9 @@ public class MainActivity extends AppCompatActivity implements
|
|||||||
SystemParamsOperation.getInstance().setSetupEcr(false);
|
SystemParamsOperation.getInstance().setSetupEcr(false);
|
||||||
SystemParamsOperation.getInstance().setDownloadedParams(false);
|
SystemParamsOperation.getInstance().setDownloadedParams(false);
|
||||||
|
|
||||||
|
// Re-bind in case a fragment cleared the listener.
|
||||||
|
registerEcrSerialBridge();
|
||||||
|
|
||||||
handleAutoSettlementIntent(getIntent());
|
handleAutoSettlementIntent(getIntent());
|
||||||
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
|
BaseApplication.getInstance().deviceEngine.getPlatform().hideNavigationBar();
|
||||||
}
|
}
|
||||||
@ -557,6 +580,7 @@ public class MainActivity extends AppCompatActivity implements
|
|||||||
// Clean up RxJava disposables
|
// Clean up RxJava disposables
|
||||||
compositeDisposable.clear();
|
compositeDisposable.clear();
|
||||||
// Reset screen mode
|
// Reset screen mode
|
||||||
|
ECRHelper.INSTANCE.setOnECRReceive(null);
|
||||||
// Disconnect serial port
|
// Disconnect serial port
|
||||||
ECRHelper.INSTANCE.releaseSerialPort();
|
ECRHelper.INSTANCE.releaseSerialPort();
|
||||||
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
|
BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
|
||||||
|
|||||||
@ -43,7 +43,6 @@ import com.utsmyanmar.baselib.util.DataBindingConfig;
|
|||||||
import com.utsmyanmar.baselib.util.DialogCallback;
|
import com.utsmyanmar.baselib.util.DialogCallback;
|
||||||
import com.utsmyanmar.baselib.util.TerminalUtil;
|
import com.utsmyanmar.baselib.util.TerminalUtil;
|
||||||
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
|
import com.utsmyanmar.checkxread.sdk.NexGoSDK;
|
||||||
import com.utsmyanmar.ecr.ECRHelper;
|
|
||||||
import com.utsmyanmar.ecr.ECRProcess;
|
import com.utsmyanmar.ecr.ECRProcess;
|
||||||
import com.utsmyanmar.ecr.data.ResultOf;
|
import com.utsmyanmar.ecr.data.ResultOf;
|
||||||
import com.utsmyanmar.ecr.data.model.Transactions;
|
import com.utsmyanmar.ecr.data.model.Transactions;
|
||||||
@ -139,24 +138,16 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
||||||
if (SystemParamsOperation.getInstance().getECRStatus()) {
|
|
||||||
ECRHelper.INSTANCE.setOnECRReceive(bytes -> {
|
|
||||||
if (getActivity() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
requireActivity().runOnUiThread(() -> handleSerialData(bytes));
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
ECRHelper.INSTANCE.initSerialPort(requireContext().getApplicationContext());
|
|
||||||
LogUtil.d(TAG, "ECR SerialPortDriver listening");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStop() {
|
public void onStop() {
|
||||||
super.onStop();
|
super.onStop();
|
||||||
ECRHelper.INSTANCE.setOnECRReceive(bytes -> null);
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSerialData(byte[] data) {
|
private void handleSerialData(byte[] data) {
|
||||||
@ -167,8 +158,10 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
|
|
||||||
if (SystemParamsOperation.getInstance().isCMHLEnabled()) {
|
if (SystemParamsOperation.getInstance().isCMHLEnabled()) {
|
||||||
ECRActionCHML(data);
|
ECRActionCHML(data);
|
||||||
} else {
|
} else if (SystemParamsOperation.getInstance().getECRStatus()) {
|
||||||
ECRAction(new String(data, StandardCharsets.UTF_8));
|
ECRAction(new String(data, StandardCharsets.UTF_8));
|
||||||
|
} else {
|
||||||
|
LogUtil.e(TAG, "ECR/CMHL disabled — ignoring serial packet");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,15 +251,6 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
// BaseApplication.getInstance().deviceEngine.getPlatform().showNavigationBar();
|
|
||||||
// enableTaskButton();
|
|
||||||
// enableHomeButton();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
@ -288,6 +272,14 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
}
|
}
|
||||||
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
|
sharedViewModel.setManualEntryStatus(SystemParamsOperation.getInstance().getManualEntryStatus());
|
||||||
|
|
||||||
|
sharedViewModel.ecrSerialData.observe(getViewLifecycleOwner(), bytes -> {
|
||||||
|
if (bytes == null || bytes.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LogUtil.d(TAG, "ECR LiveData received len=" + bytes.length);
|
||||||
|
handleSerialData(bytes);
|
||||||
|
});
|
||||||
|
|
||||||
// queryAidCAPKList();
|
// queryAidCAPKList();
|
||||||
queryAidCAPKList();
|
queryAidCAPKList();
|
||||||
// generateMockQR();
|
// generateMockQR();
|
||||||
@ -786,9 +778,10 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
|
|
||||||
private void ECRActionCHML(byte[] data) {
|
private void ECRActionCHML(byte[] data) {
|
||||||
|
|
||||||
// LogUtil.d(TAG, "ECR msg here : " + msg);
|
LogUtil.d(TAG, "ECR CMHL packet len=" + data.length);
|
||||||
try {
|
try {
|
||||||
EcrPacket ecrPacket = EcrManager.parsePacket(data);
|
EcrPacket ecrPacket = EcrManager.parsePacket(data);
|
||||||
|
LogUtil.d(TAG, "ECR CMHL cmd=0x" + Integer.toHexString(ecrPacket.getCommandCode() & 0xFF));
|
||||||
|
|
||||||
EcrRequestDispatcher.dispatch(ecrPacket, new EcrRequestListener() {
|
EcrRequestDispatcher.dispatch(ecrPacket, new EcrRequestListener() {
|
||||||
@Override
|
@Override
|
||||||
@ -809,6 +802,8 @@ public class MainFragment extends DataBindingFragment {
|
|||||||
if (CoreUtils.getInstance(sharedViewModel).setUpECRSale(request)) {
|
if (CoreUtils.getInstance(sharedViewModel).setUpECRSale(request)) {
|
||||||
LogUtil.d(TAG,"Starting to process sale transaction!");
|
LogUtil.d(TAG,"Starting to process sale transaction!");
|
||||||
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
|
delayFunctionCall(() -> isRouteValidAndNavigateToRoute(R.id.action_nav_main_to_cardWaitingFragment));
|
||||||
|
} else {
|
||||||
|
LogUtil.e(TAG, "CMHL Sale setup failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -87,6 +87,8 @@ public class SharedViewModel extends ViewModel {
|
|||||||
/*May 31 2022*/
|
/*May 31 2022*/
|
||||||
public SingleLiveEvent<Boolean> isEcrFinished = new SingleLiveEvent<>();
|
public SingleLiveEvent<Boolean> isEcrFinished = new SingleLiveEvent<>();
|
||||||
|
|
||||||
|
public final SingleLiveEvent<byte[]> ecrSerialData = new SingleLiveEvent<>();
|
||||||
|
|
||||||
/*Jun 3 2022*/
|
/*Jun 3 2022*/
|
||||||
public SingleLiveEvent<Boolean> isEmv = new SingleLiveEvent<>();
|
public SingleLiveEvent<Boolean> isEmv = new SingleLiveEvent<>();
|
||||||
|
|
||||||
|
|||||||
@ -250,7 +250,7 @@ public class CoreUtils implements OldECRSetups,ECRSetups,ECRSetupsCMHL {
|
|||||||
try{
|
try{
|
||||||
|
|
||||||
LogUtil.d(TAG, "amount is "+trans.getAmount());
|
LogUtil.d(TAG, "amount is "+trans.getAmount());
|
||||||
if (trans.getAmount() == null && Long.parseLong(trans.getAmount()) <= 0) {
|
if (trans.getAmount() == null || Long.parseLong(trans.getAmount()) <= 0) {
|
||||||
|
|
||||||
LogUtil.d(TAG,"Amount field is invalid!");
|
LogUtil.d(TAG,"Amount field is invalid!");
|
||||||
return false;
|
return false;
|
||||||
@ -276,7 +276,7 @@ public class CoreUtils implements OldECRSetups,ECRSetups,ECRSetupsCMHL {
|
|||||||
try{
|
try{
|
||||||
|
|
||||||
LogUtil.d(TAG, "amount is "+trans.getAmount());
|
LogUtil.d(TAG, "amount is "+trans.getAmount());
|
||||||
if (trans.getAmount() == null && Long.parseLong(trans.getAmount()) <= 0) {
|
if (trans.getAmount() == null || Long.parseLong(trans.getAmount()) <= 0) {
|
||||||
|
|
||||||
LogUtil.d(TAG,"Amount field is invalid!");
|
LogUtil.d(TAG,"Amount field is invalid!");
|
||||||
return false;
|
return false;
|
||||||
@ -324,7 +324,7 @@ public class CoreUtils implements OldECRSetups,ECRSetups,ECRSetupsCMHL {
|
|||||||
try{
|
try{
|
||||||
|
|
||||||
LogUtil.d(TAG, "amount is "+trans.getAmount());
|
LogUtil.d(TAG, "amount is "+trans.getAmount());
|
||||||
if (trans.getAmount() == null && Long.parseLong(trans.getAmount()) <= 0) {
|
if (trans.getAmount() == null || Long.parseLong(trans.getAmount()) <= 0) {
|
||||||
|
|
||||||
LogUtil.d(TAG,"Amount field is invalid!");
|
LogUtil.d(TAG,"Amount field is invalid!");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.utsmyanmar.ecr
|
package com.utsmyanmar.ecr
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import com.nexgo.oaf.apiv3.APIProxy
|
import com.nexgo.oaf.apiv3.APIProxy
|
||||||
import com.nexgo.oaf.apiv3.SdkResult
|
import com.nexgo.oaf.apiv3.SdkResult
|
||||||
import com.nexgo.oaf.apiv3.device.serialport.SerialCfgEntity
|
import com.nexgo.oaf.apiv3.device.serialport.SerialCfgEntity
|
||||||
@ -8,6 +10,7 @@ import com.nexgo.oaf.apiv3.device.serialport.SerialPortDriver
|
|||||||
import com.utsmyanmar.paylibs.utils.LogUtil
|
import com.utsmyanmar.paylibs.utils.LogUtil
|
||||||
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil
|
import com.utsmyanmar.paylibs.utils.core_utils.ByteUtil
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NexGo SerialPortDriver wrapper (port 0 = physical USB serial).
|
* NexGo SerialPortDriver wrapper (port 0 = physical USB serial).
|
||||||
@ -17,13 +20,15 @@ object ECRHelper {
|
|||||||
|
|
||||||
val TAG: String = ECRHelper::class.java.simpleName
|
val TAG: String = ECRHelper::class.java.simpleName
|
||||||
|
|
||||||
private const val PORT_NO = 101
|
private const val PORT_NO = 0
|
||||||
private const val RECV_BUFFER_SIZE = 2048
|
private const val RECV_BUFFER_SIZE = 2048
|
||||||
private const val RECV_TIMEOUT_MS = 3000L
|
private const val RECV_TIMEOUT_MS = 3000L
|
||||||
|
|
||||||
private var serialPort: SerialPortDriver? = null
|
private var serialPort: SerialPortDriver? = null
|
||||||
private var receiveThread: Thread? = null
|
private var receiveThread: Thread? = null
|
||||||
private val receiving = AtomicBoolean(false)
|
private val receiving = AtomicBoolean(false)
|
||||||
|
private val mainHandler = Handler(Looper.getMainLooper())
|
||||||
|
private val receiveListener = AtomicReference<((ByteArray) -> Unit)?>(null)
|
||||||
|
|
||||||
var onBindSuccess: () -> Unit = { }
|
var onBindSuccess: () -> Unit = { }
|
||||||
var onBindFailure: () -> Unit = { }
|
var onBindFailure: () -> Unit = { }
|
||||||
@ -34,7 +39,11 @@ object ECRHelper {
|
|||||||
var onSendSuccess: () -> Unit = { }
|
var onSendSuccess: () -> Unit = { }
|
||||||
var onSendFailure: (Int, String) -> Unit = { _, _ -> }
|
var onSendFailure: (Int, String) -> Unit = { _, _ -> }
|
||||||
|
|
||||||
var onECRReceive: (bytes: ByteArray) -> Unit = { }
|
/** Thread-safe receive callback. Invoked on the main thread. */
|
||||||
|
fun setOnECRReceive(listener: ((ByteArray) -> Unit)?) {
|
||||||
|
receiveListener.set(listener)
|
||||||
|
LogUtil.d(TAG, "onECRReceive listener ${if (listener != null) "registered" else "cleared"}")
|
||||||
|
}
|
||||||
|
|
||||||
val isConnected: Boolean
|
val isConnected: Boolean
|
||||||
get() = serialPort != null
|
get() = serialPort != null
|
||||||
@ -139,6 +148,22 @@ object ECRHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun dispatchReceive(data: ByteArray) {
|
||||||
|
val listener = receiveListener.get()
|
||||||
|
if (listener == null) {
|
||||||
|
LogUtil.e(TAG, "Serial data dropped: no onECRReceive listener")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mainHandler.post {
|
||||||
|
try {
|
||||||
|
listener.invoke(data)
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
LogUtil.e(TAG, "onECRReceive error: ${ex.message}")
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startReceiveLoop() {
|
private fun startReceiveLoop() {
|
||||||
if (receiving.getAndSet(true)) {
|
if (receiving.getAndSet(true)) {
|
||||||
return
|
return
|
||||||
@ -153,8 +178,8 @@ object ECRHelper {
|
|||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
val data = buffer.copyOf(len)
|
val data = buffer.copyOf(len)
|
||||||
LogUtil.d(TAG, "Serial recv len=$len")
|
LogUtil.d(TAG, "Serial recv len=$len")
|
||||||
LogUtil.d(TAG," Receive packet : "+ ByteUtil.bytes2HexStr(data));
|
LogUtil.d(TAG, " Receive packet : " + ByteUtil.bytes2HexStr(data))
|
||||||
onECRReceive(data)
|
dispatchReceive(data)
|
||||||
}
|
}
|
||||||
// timeout / no data: keep listening
|
// timeout / no data: keep listening
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user