From e23c3196d669c4156b59bba1229d96c6bc85e259 Mon Sep 17 00:00:00 2001 From: Ghattamaneni Venkateswararao Date: Sat, 10 Oct 2026 08:30:22 +0530 Subject: [PATCH 1/2] Go foreground first when the streaming service starts FileStreamerIntentService is started with startForegroundService(), but it called startForeground() only deep in onHandleIntent on the worker thread. When no G-code file was found it returned early without it, the service stopped, and Android killed the app with ForegroundServiceDidNotStartInTimeException (RemoteServiceException on Android 11 and older). Call startForeground() first in onStartCommand, on every start, with the same notification. Drop the later calls and their always-true SDK checks. Fixes #186 --- .../service/FileStreamerIntentService.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/in/co/gorest/grblcontroller/service/FileStreamerIntentService.java b/app/src/main/java/in/co/gorest/grblcontroller/service/FileStreamerIntentService.java index 26953c4..68ed705 100644 --- a/app/src/main/java/in/co/gorest/grblcontroller/service/FileStreamerIntentService.java +++ b/app/src/main/java/in/co/gorest/grblcontroller/service/FileStreamerIntentService.java @@ -25,7 +25,6 @@ import android.app.Notification; import android.content.Context; import android.content.Intent; -import android.os.Build; import android.os.PowerManager; import android.os.Process; import androidx.core.app.NotificationCompat; @@ -105,6 +104,16 @@ public void onDestroy(){ EventBus.getDefault().unregister(this); } + @Override + public int onStartCommand(Intent intent, int flags, int startId){ + // Android kills the app when a service started with startForegroundService() stops, or runs + // for 10 s, without calling startForeground(). So call it first, on every start, before any work. + boolean isCheckMode = intent != null && intent.getBooleanExtra(CHECK_MODE_ENABLED, false); + String title = getString(isCheckMode ? R.string.text_file_checking_started : R.string.text_file_streaming_started); + startForeground(Constants.FILE_STREAMING_NOTIFICATION_ID, getNotification(title, FileSenderListener.getInstance().getGcodeFileName())); + return super.onStartCommand(intent, flags, startId); + } + @Override protected void onHandleIntent(Intent intent){ fileSenderListener = FileSenderListener.getInstance(); @@ -151,20 +160,12 @@ public void run() { EventBus.getDefault().post(new StreamingStartedEvent()); if(isCheckMode){ - if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1){ - startForeground(Constants.FILE_STREAMING_NOTIFICATION_ID, getNotification(getString(R.string.text_file_checking_started), fileSenderListener.getGcodeFile().getName())); - } - if(defaultConnectionType != null && defaultConnectionType.equals(Constants.SERIAL_CONNECTION_TYPE_BLUETOOTH)){ this.checkGcodeFile(); }else{ this.startStreaming(555); } }else{ - if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1){ - startForeground(Constants.FILE_STREAMING_NOTIFICATION_ID, getNotification(getString(R.string.text_file_streaming_started), fileSenderListener.getGcodeFile().getName())); - } - this.startStreaming(5); } From 70cf336838f6365a13f7b37825de14077f80c296 Mon Sep 17 00:00:00 2001 From: Ghattamaneni Venkateswararao Date: Sat, 10 Oct 2026 08:30:22 +0530 Subject: [PATCH 2/2] Do not crash when Android refuses the USB service start UsbConnectionActivity.onStart() calls startService(), which throws BackgroundServiceStartNotAllowedException while Android counts the app as in the background. The bind in onCreate already creates and keeps the service alive, so catch the refusal and log it. Fixes #189 --- .../co/gorest/grblcontroller/UsbConnectionActivity.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/in/co/gorest/grblcontroller/UsbConnectionActivity.java b/app/src/main/java/in/co/gorest/grblcontroller/UsbConnectionActivity.java index 69f7eb3..f2146b1 100644 --- a/app/src/main/java/in/co/gorest/grblcontroller/UsbConnectionActivity.java +++ b/app/src/main/java/in/co/gorest/grblcontroller/UsbConnectionActivity.java @@ -35,6 +35,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -79,7 +80,13 @@ public void onStart(){ // The service goes foreground on its own once a USB device permission is granted. // startForegroundService would crash here on Android 14+ when no device is granted yet. - startService(new Intent(getApplicationContext(), GrblUsbSerialService.class)); + try{ + startService(new Intent(getApplicationContext(), GrblUsbSerialService.class)); + }catch(IllegalStateException e){ + // Android refuses this while it counts the app as in the background. + // The bind in onCreate already keeps the service alive. + Log.w("UsbConnectionActivity", "could not start the USB service", e); + } } @Override