From f91168eff44d528e82588b7e6d9f786a1ba0a1bc Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Fri, 18 Sep 2020 22:20:23 +0500 Subject: [PATCH] Fix issue where termux crashes occasionally in android >= 8 because "startForeground()" function is not being called before running "startForegroundService()" in RunCommandService. --- .../com/termux/app/RunCommandService.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/app/src/main/java/com/termux/app/RunCommandService.java b/app/src/main/java/com/termux/app/RunCommandService.java index 2a57864d..d4af178b 100644 --- a/app/src/main/java/com/termux/app/RunCommandService.java +++ b/app/src/main/java/com/termux/app/RunCommandService.java @@ -1,6 +1,10 @@ package com.termux.app; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; import android.app.Service; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Binder; @@ -8,6 +12,8 @@ import android.os.Build; import android.os.IBinder; import android.util.Log; +import com.termux.R; + import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; @@ -50,6 +56,9 @@ public class RunCommandService extends Service { public static final String RUN_COMMAND_WORKDIR = "com.termux.RUN_COMMAND_WORKDIR"; public static final String RUN_COMMAND_BACKGROUND = "com.termux.RUN_COMMAND_BACKGROUND"; + private static final String NOTIFICATION_CHANNEL_ID = "termux_run_command_notification_channel"; + private static final int NOTIFICATION_ID = 1338; + class LocalBinder extends Binder { public final RunCommandService service = RunCommandService.this; } @@ -61,7 +70,15 @@ public class RunCommandService extends Service { return mBinder; } + @Override + public void onCreate() { + runStartForeground(); + } + public int onStartCommand(Intent intent, int flags, int startId) { + // Run again in case service is already started and onCreate() is not called + runStartForeground(); + if (allowExternalApps() && RUN_COMMAND_ACTION.equals(intent.getAction())) { Uri programUri = new Uri.Builder().scheme("com.termux.file").path(intent.getStringExtra(RUN_COMMAND_PATH)).build(); @@ -78,9 +95,56 @@ public class RunCommandService extends Service { } } + runStopForeground(); + return Service.START_NOT_STICKY; } + private void runStartForeground() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + setupNotificationChannel(); + startForeground(NOTIFICATION_ID, buildNotification()); + } + } + + private void runStopForeground() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + stopForeground(true); + } + } + + private Notification buildNotification() { + Notification.Builder builder = new Notification.Builder(this); + builder.setContentTitle(getText(R.string.application_name) + " Run Command"); + builder.setSmallIcon(R.drawable.ic_service_notification); + + // Use a low priority: + builder.setPriority(Notification.PRIORITY_LOW); + + // No need to show a timestamp: + builder.setShowWhen(false); + + // Background color for small notification icon: + builder.setColor(0xFF607D8B); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + builder.setChannelId(NOTIFICATION_CHANNEL_ID); + } + + return builder.build(); + } + + private void setupNotificationChannel() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return; + + String channelName = "Termux Run Command"; + int importance = NotificationManager.IMPORTANCE_LOW; + + NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, importance); + NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + manager.createNotificationChannel(channel); + } + private boolean allowExternalApps() { File propsFile = new File(TermuxService.HOME_PATH + "/.termux/termux.properties"); if (!propsFile.exists())