From 2be01381751467a53e007546b3a1d62d96192152 Mon Sep 17 00:00:00 2001 From: ouyangwanli Date: Wed, 2 Sep 2026 14:33:10 +0800 Subject: [PATCH 1/2] fix: add debug false --- pos_android_studio_demo/pos_android_app/build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pos_android_studio_demo/pos_android_app/build.gradle b/pos_android_studio_demo/pos_android_app/build.gradle index 70b0e9e1..2271370c 100644 --- a/pos_android_studio_demo/pos_android_app/build.gradle +++ b/pos_android_studio_demo/pos_android_app/build.gradle @@ -32,7 +32,7 @@ android { minSdk 24 targetSdk 34 versionCode 145 - versionName "8.5.3-2608131115" + versionName "8.5.3-2609143125" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { // Set up supported SO library architecture @@ -41,6 +41,9 @@ android { } buildTypes { + debug { + debuggable false // + } release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' From d4465ab3b68694a2a698e5212b2cb2600dde29cd Mon Sep 17 00:00:00 2001 From: ouyangwanli Date: Wed, 2 Sep 2026 14:50:31 +0800 Subject: [PATCH 2/2] fix: fix thread rejectedExecutionException issue --- .../ConnectionSettingsFragment.java | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/pos_android_studio_demo/pos_android_app/src/main/java/com/dspread/pos/ui/setting/connection_settings/ConnectionSettingsFragment.java b/pos_android_studio_demo/pos_android_app/src/main/java/com/dspread/pos/ui/setting/connection_settings/ConnectionSettingsFragment.java index 97ec20c5..9ac84b27 100644 --- a/pos_android_studio_demo/pos_android_app/src/main/java/com/dspread/pos/ui/setting/connection_settings/ConnectionSettingsFragment.java +++ b/pos_android_studio_demo/pos_android_app/src/main/java/com/dspread/pos/ui/setting/connection_settings/ConnectionSettingsFragment.java @@ -212,8 +212,26 @@ public String getTitle() { } - // Thread pool for executing asynchronous operations - private static final java.util.concurrent.ExecutorService asyncExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(); + // Thread pool for executing asynchronous operations. + // Instance-level (not static): a static pool would be permanently terminated by the first + // fragment's onDestroy, causing RejectedExecutionException for later instances. + private final java.util.concurrent.ExecutorService asyncExecutor = java.util.concurrent.Executors.newSingleThreadExecutor(); + + /** + * Safely submit a task to the executor, guarding against a terminated pool + * (e.g. USB permission callback fired after the fragment was destroyed). + */ + private void executeAsync(Runnable task) { + if (asyncExecutor.isShutdown() || asyncExecutor.isTerminated()) { + TRACE.d("asyncExecutor already terminated, skip task submission"); + return; + } + try { + asyncExecutor.execute(task); + } catch (java.util.concurrent.RejectedExecutionException e) { + Log.e("ConnectionSettingsFragment", "submit task to executor failed: " + e.getMessage()); + } + } private void showUsbDeviceDialog() { USBClass usb = new USBClass(); @@ -221,7 +239,7 @@ private void showUsbDeviceDialog() { @Override public void onPermissionGranted(UsbDevice device) { // Get USB device list in sub-thread - asyncExecutor.execute(() -> { + executeAsync(() -> { ArrayList deviceList = usb.GetUSBDevices(getActivity()); // Update UI in main thread, using main thread's Looper new Handler(Looper.getMainLooper()).post(() -> { @@ -239,7 +257,7 @@ public void onPermissionDenied(UsbDevice device) { }); // Get USB device list in sub-thread - asyncExecutor.execute(() -> { + executeAsync(() -> { ArrayList deviceList = usb.GetUSBDevices(getActivity()); // Update UI in main thread, using main thread's Looper new Handler(Looper.getMainLooper()).post(() -> {