diff --git a/app/src/main/java/com/termux/app/TermuxService.java b/app/src/main/java/com/termux/app/TermuxService.java index e5960e37..f81d26dc 100644 --- a/app/src/main/java/com/termux/app/TermuxService.java +++ b/app/src/main/java/com/termux/app/TermuxService.java @@ -28,6 +28,7 @@ import com.termux.app.terminal.TermuxSessionClient; import com.termux.app.terminal.TermuxSessionClientBase; import com.termux.app.utils.Logger; import com.termux.app.utils.NotificationUtils; +import com.termux.app.utils.PermissionUtils; import com.termux.app.utils.ShellUtils; import com.termux.app.utils.TextDataUtils; import com.termux.models.ExecutionCommand; @@ -513,7 +514,12 @@ public final class TermuxService extends Service { /** Launch the {@link }TermuxActivity} to bring it to foreground. */ private void startTermuxActivity() { - TermuxActivity.startTermuxActivity(this); + // For android >= 10, apps require Display over other apps permission to start foreground activities + // from background (services). If it is not granted, then termux sessions that are started will + // show in Termux notification but will not run until user manually clicks the notification. + if(PermissionUtils.validateDisplayOverOtherAppsPermissionForPostAndroid10(this)) { + TermuxActivity.startTermuxActivity(this); + } } diff --git a/app/src/main/java/com/termux/app/utils/PermissionUtils.java b/app/src/main/java/com/termux/app/utils/PermissionUtils.java new file mode 100644 index 00000000..2b8614c9 --- /dev/null +++ b/app/src/main/java/com/termux/app/utils/PermissionUtils.java @@ -0,0 +1,86 @@ +package com.termux.app.utils; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; + +import androidx.core.content.ContextCompat; + +import com.termux.R; +import com.termux.app.TermuxConstants; +import com.termux.app.settings.preferences.TermuxAppSharedPreferences; + +import java.util.Arrays; + +public class PermissionUtils { + + public static final int ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE = 0; + + private static final String LOG_TAG = "PluginUtils"; + + public static boolean checkPermissions(Context context, String[] permissions) { + int result; + + for (String p:permissions) { + result = ContextCompat.checkSelfPermission(context,p); + if (result != PackageManager.PERMISSION_GRANTED) { + return false; + } + } + return true; + } + + public static void askPermissions(Activity context, String[] permissions) { + if(context == null || permissions == null) return; + + int result; + Logger.showToast(context, context.getString(R.string.message_sudo_please_grant_permissions), true); + try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} + + for (String permission:permissions) { + result = ContextCompat.checkSelfPermission(context, permission); + if (result != PackageManager.PERMISSION_GRANTED) { + Logger.logDebug(LOG_TAG, "Requesting Permissions: " + Arrays.toString(permissions)); + context.requestPermissions(new String[]{permission}, 0); + } + } + } + + + + public static boolean checkDisplayOverOtherAppsPermission(Context context) { + boolean permissionGranted; + + permissionGranted = Settings.canDrawOverlays(context); + if (!permissionGranted) { + Logger.logWarn(LOG_TAG, TermuxConstants.TERMUX_APP_NAME + " App does not have Display over other apps (SYSTEM_ALERT_WINDOW) permission"); + return false; + } else { + Logger.logDebug(LOG_TAG, TermuxConstants.TERMUX_APP_NAME + " App already has Display over other apps (SYSTEM_ALERT_WINDOW) permission"); + return true; + } + } + + public static void askDisplayOverOtherAppsPermission(Activity context) { + Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context.getPackageName())); + context.startActivityForResult(intent, ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE); + } + + public static boolean validateDisplayOverOtherAppsPermissionForPostAndroid10(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true; + + if(!PermissionUtils.checkDisplayOverOtherAppsPermission(context)) { + TermuxAppSharedPreferences preferences = new TermuxAppSharedPreferences(context); + if(preferences.getPluginErrorNotificationsEnabled()) + Logger.showToast(context, context.getString(R.string.error_display_over_other_apps_permission_not_granted), true); + return false; + } else { + return true; + } + } + +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dc1e5c68..967650ea 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -128,6 +128,12 @@ + + Please grant permissions on next screen + &TERMUX_APP_NAME; requires \"Display over other apps\" permission to start terminal sessions from background on Android >= 10. Grants it from Settings -> Apps -> &TERMUX_APP_NAME; -> Advanced + + + Save file in ~/downloads/ Edit