Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pos_android_studio_demo/pos_android_app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ android {
minSdk 24
targetSdk 34
versionCode 146
versionName "8.5.4-2608201515"
versionName "8.5.4-2609021540"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
// Set up supported SO library architecture
Expand All @@ -41,6 +41,9 @@ android {
}

buildTypes {
debug {
debuggable false
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,16 +212,34 @@ 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();
usb.setUsbPermissionListener(new USBClass.UsbPermissionListener() {
@Override
public void onPermissionGranted(UsbDevice device) {
// Get USB device list in sub-thread
asyncExecutor.execute(() -> {
executeAsync(() -> {
ArrayList<String> deviceList = usb.GetUSBDevices(getActivity());
// Update UI in main thread, using main thread's Looper
new Handler(Looper.getMainLooper()).post(() -> {
Expand All @@ -239,7 +257,7 @@ public void onPermissionDenied(UsbDevice device) {
});

// Get USB device list in sub-thread
asyncExecutor.execute(() -> {
executeAsync(() -> {
ArrayList<String> deviceList = usb.GetUSBDevices(getActivity());
// Update UI in main thread, using main thread's Looper
new Handler(Looper.getMainLooper()).post(() -> {
Expand Down
Loading