mirror of
				https://github.com/fankes/termux-app.git
				synced 2025-10-25 13:19:21 +08:00 
			
		
		
		
	Changed: Add general compatibility fixes for minSdkVerion 21
				
					
				
			This commit is contained in:
		| @@ -48,9 +48,12 @@ public class AndroidUtils { | ||||
|             !filesDir.equals("/data/data/" + context.getPackageName() + "/files")) | ||||
|             AndroidUtils.appendPropertyToMarkdown(markdownString,"FILES_DIR", filesDir); | ||||
|  | ||||
|         Long userId = PackageUtils.getUserIdForPackage(context); | ||||
|         if (userId == null || userId != 0) | ||||
|             AndroidUtils.appendPropertyToMarkdown(markdownString,"USER_ID", userId); | ||||
|  | ||||
|         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ) { | ||||
|             Long userId = PackageUtils.getUserIdForPackage(context); | ||||
|             if (userId == null || userId != 0) | ||||
|                 AndroidUtils.appendPropertyToMarkdown(markdownString, "USER_ID", userId); | ||||
|         } | ||||
|  | ||||
|         AndroidUtils.appendPropertyToMarkdownIfSet(markdownString,"PROFILE_OWNER", PackageUtils.getProfileOwnerPackageNameForUser(context)); | ||||
|  | ||||
|   | ||||
| @@ -8,11 +8,13 @@ import android.content.Intent; | ||||
| import android.content.pm.ApplicationInfo; | ||||
| import android.content.pm.PackageInfo; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.os.Build; | ||||
| import android.os.UserHandle; | ||||
| import android.os.UserManager; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.annotation.RequiresApi; | ||||
|  | ||||
| import com.termux.shared.R; | ||||
| import com.termux.shared.data.DataUtils; | ||||
| @@ -507,6 +509,7 @@ public class PackageUtils { | ||||
|      * @param context The {@link Context} for the package. | ||||
|      * @return Returns the serial number. This will be {@code null} if failed to get it. | ||||
|      */ | ||||
|     @RequiresApi(api = Build.VERSION_CODES.N) | ||||
|     @Nullable | ||||
|     public static Long getUserIdForPackage(@NonNull Context context) { | ||||
|         UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); | ||||
| @@ -521,6 +524,7 @@ public class PackageUtils { | ||||
|      * @param context The {@link Context} for operations. | ||||
|      * @return Returns {@code true} if the current user is the primary user, otherwise [@code false}. | ||||
|      */ | ||||
|     @RequiresApi(api = Build.VERSION_CODES.N) | ||||
|     public static boolean isCurrentUserThePrimaryUser(@NonNull Context context) { | ||||
|         Long userId = getUserIdForPackage(context); | ||||
|         return userId != null && userId == 0; | ||||
|   | ||||
| @@ -93,6 +93,7 @@ public class PermissionUtils { | ||||
|      *                    will fail silently and will log an exception. | ||||
|      * @return Returns {@code true} if requesting the permission was successful, otherwise {@code false}. | ||||
|      */ | ||||
|     @RequiresApi(api = Build.VERSION_CODES.M) | ||||
|     public static boolean requestPermission(@NonNull Context context, @NonNull String permission, | ||||
|                                             int requestCode) { | ||||
|         return requestPermissions(context, new String[]{permission}, requestCode); | ||||
| @@ -116,6 +117,7 @@ public class PermissionUtils { | ||||
|      *                    will fail silently and will log an exception. | ||||
|      * @return Returns {@code true} if requesting the permissions was successful, otherwise {@code false}. | ||||
|      */ | ||||
|     @RequiresApi(api = Build.VERSION_CODES.M) | ||||
|     public static boolean requestPermissions(@NonNull Context context, @NonNull String[] permissions, | ||||
|                                              int requestCode) { | ||||
|         List<String> permissionsNotRequested = getPermissionsNotRequested(context, permissions); | ||||
| @@ -274,12 +276,13 @@ public class PermissionUtils { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         errmsg = context.getString(R.string.msg_storage_permission_not_granted); | ||||
|         Logger.logError(LOG_TAG, errmsg); | ||||
|         if (showErrorMessage) | ||||
|             Logger.showToast(context, errmsg, false); | ||||
|  | ||||
|         if (requestCode < 0) | ||||
|         if (requestCode < 0 || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) | ||||
|             return false; | ||||
|  | ||||
|         if (requestLegacyStoragePermission || Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { | ||||
| @@ -323,6 +326,7 @@ public class PermissionUtils { | ||||
|      *                    will fail silently and will log an exception. | ||||
|      * @return Returns {@code true} if requesting the permission was successful, otherwise {@code false}. | ||||
|      */ | ||||
|     @RequiresApi(api = Build.VERSION_CODES.M) | ||||
|     public static boolean requestLegacyStorageExternalPermission(@NonNull Context context, int requestCode) { | ||||
|         Logger.logInfo(LOG_TAG, "Requesting legacy external storage permission"); | ||||
|         return requestPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, requestCode); | ||||
| @@ -439,7 +443,10 @@ public class PermissionUtils { | ||||
|      * @return Returns {@code true} if permission is granted, otherwise {@code false}. | ||||
|      */ | ||||
|     public static boolean checkDisplayOverOtherAppsPermission(@NonNull Context context) { | ||||
|         return Settings.canDrawOverlays(context); | ||||
|         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) | ||||
|             return Settings.canDrawOverlays(context); | ||||
|         else | ||||
|             return true; | ||||
|     } | ||||
|  | ||||
|     /** Wrapper for {@link #requestDisplayOverOtherAppsPermission(Context, int)}. */ | ||||
| @@ -461,6 +468,9 @@ public class PermissionUtils { | ||||
|     public static Error requestDisplayOverOtherAppsPermission(@NonNull Context context, int requestCode) { | ||||
|         Logger.logInfo(LOG_TAG, "Requesting display over apps permission"); | ||||
|  | ||||
|         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) | ||||
|             return null; | ||||
|  | ||||
|         Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); | ||||
|         intent.setData(Uri.parse("package:" + context.getPackageName())); | ||||
|  | ||||
| @@ -505,8 +515,11 @@ public class PermissionUtils { | ||||
|      * @return Returns {@code true} if permission is granted, otherwise {@code false}. | ||||
|      */ | ||||
|     public static boolean checkIfBatteryOptimizationsDisabled(@NonNull Context context) { | ||||
|         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); | ||||
|         return powerManager.isIgnoringBatteryOptimizations(context.getPackageName()); | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|             PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); | ||||
|             return powerManager.isIgnoringBatteryOptimizations(context.getPackageName()); | ||||
|         } else | ||||
|             return true; | ||||
|     } | ||||
|  | ||||
|     /** Wrapper for {@link #requestDisableBatteryOptimizations(Context, int)}. */ | ||||
| @@ -530,6 +543,9 @@ public class PermissionUtils { | ||||
|     public static Error requestDisableBatteryOptimizations(@NonNull Context context, int requestCode) { | ||||
|         Logger.logInfo(LOG_TAG, "Requesting to disable battery optimizations"); | ||||
|  | ||||
|         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) | ||||
|             return null; | ||||
|  | ||||
|         Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); | ||||
|         intent.setData(Uri.parse("package:" + context.getPackageName())); | ||||
|  | ||||
|   | ||||
| @@ -32,8 +32,11 @@ package com.termux.shared.file.filesystem; | ||||
| // Those constants are initialized by native code to ensure correctness on different architectures. | ||||
| // AT_SYMLINK_NOFOLLOW (used by fstatat) and AT_REMOVEDIR (used by unlinkat) as of July 2018 do not | ||||
| // have equivalents in android.system.OsConstants so left unchanged. | ||||
| import android.os.Build; | ||||
| import android.system.OsConstants; | ||||
|  | ||||
| import androidx.annotation.RequiresApi; | ||||
|  | ||||
| /** | ||||
|  * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:libcore/ojluni/src/main/java/sun/nio/fs/UnixConstants.java | ||||
|  */ | ||||
| @@ -56,7 +59,11 @@ public class UnixConstants { | ||||
|  | ||||
|     static final int O_SYNC = OsConstants.O_SYNC; | ||||
|  | ||||
|     static final int O_DSYNC = OsConstants.O_DSYNC; | ||||
|     // Crash on Android 5. | ||||
|     // No static field O_DSYNC of type I in class Landroid/system/OsConstants; or its superclasses | ||||
|     // (declaration of 'android.system.OsConstants' appears in /system/framework/core-libart.jar) | ||||
|     //@RequiresApi(Build.VERSION_CODES.O_MR1) | ||||
|     //static final int O_DSYNC = OsConstants.O_DSYNC; | ||||
|  | ||||
|     static final int O_NOFOLLOW = OsConstants.O_NOFOLLOW; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import android.content.ClipboardManager; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.os.Build; | ||||
| import android.os.Environment; | ||||
|  | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| @@ -145,7 +146,7 @@ public class ShareUtils { | ||||
|             !PermissionUtils.checkPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { | ||||
|             Logger.logErrorAndShowToast(context, LOG_TAG, context.getString(R.string.msg_storage_permission_not_granted)); | ||||
|  | ||||
|             if (storagePermissionRequestCode >= 0) { | ||||
|             if (storagePermissionRequestCode >= 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|                 if (context instanceof AppCompatActivity) | ||||
|                     PermissionUtils.requestPermission(((AppCompatActivity) context), Manifest.permission.WRITE_EXTERNAL_STORAGE, storagePermissionRequestCode); | ||||
|                 else if (context instanceof Activity) | ||||
|   | ||||
| @@ -38,7 +38,9 @@ public class SpecialButtonState { | ||||
|     /** Set {@link #isActive}. */ | ||||
|     public void setIsActive(boolean value) { | ||||
|         isActive = value; | ||||
|         buttons.forEach(button -> button.setTextColor(value ? mExtraKeysView.getButtonActiveTextColor() : mExtraKeysView.getButtonTextColor())); | ||||
|         for (MaterialButton button : buttons) { | ||||
|             button.setTextColor(value ? mExtraKeysView.getButtonActiveTextColor() : mExtraKeysView.getButtonTextColor()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** Set {@link #isLocked}. */ | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package com.termux.shared.termux.terminal.io; | ||||
|  | ||||
| import android.os.Build; | ||||
| import android.view.KeyEvent; | ||||
| import android.view.View; | ||||
|  | ||||
| @@ -9,6 +10,7 @@ import com.google.android.material.button.MaterialButton; | ||||
| import com.termux.shared.termux.extrakeys.ExtraKeyButton; | ||||
| import com.termux.shared.termux.extrakeys.ExtraKeysView; | ||||
| import com.termux.shared.termux.extrakeys.SpecialButton; | ||||
| import com.termux.terminal.TerminalSession; | ||||
| import com.termux.view.TerminalView; | ||||
|  | ||||
| import static com.termux.shared.termux.extrakeys.ExtraKeysConstants.PRIMARY_KEY_CODES_FOR_STRINGS; | ||||
| @@ -63,9 +65,15 @@ public class TerminalExtraKeys implements ExtraKeysView.IExtraKeysView { | ||||
|             mTerminalView.onKeyDown(keyCode, keyEvent); | ||||
|         } else { | ||||
|             // not a control char | ||||
|             key.codePoints().forEach(codePoint -> { | ||||
|                 mTerminalView.inputCodePoint(codePoint, ctrlDown, altDown); | ||||
|             }); | ||||
|             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|                 key.codePoints().forEach(codePoint -> { | ||||
|                     mTerminalView.inputCodePoint(codePoint, ctrlDown, altDown); | ||||
|                 }); | ||||
|             } else { | ||||
|                 TerminalSession session = mTerminalView.getCurrentSession(); | ||||
|                 if (session != null && key.length() > 0) | ||||
|                     session.write(key); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -4,12 +4,14 @@ import android.app.Activity; | ||||
| import android.content.Context; | ||||
| import android.content.res.Configuration; | ||||
| import android.inputmethodservice.InputMethodService; | ||||
| import android.os.Build; | ||||
| import android.view.View; | ||||
| import android.view.WindowInsets; | ||||
| import android.view.WindowManager; | ||||
| import android.view.inputmethod.InputMethodManager; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.RequiresApi; | ||||
| import androidx.core.view.WindowInsetsCompat; | ||||
|  | ||||
| import com.termux.shared.logger.Logger; | ||||
| @@ -118,6 +120,7 @@ public class KeyboardUtils { | ||||
|      * @param activity The Activity of the root view for which the visibility should be checked. | ||||
|      * @return Returns {@code true} if soft keyboard is visible, otherwise {@code false}. | ||||
|      */ | ||||
|     @RequiresApi(api = Build.VERSION_CODES.M) | ||||
|     public static boolean isSoftKeyboardVisible(final Activity activity) { | ||||
|         if (activity != null && activity.getWindow() != null) { | ||||
|             WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); | ||||
|   | ||||
| @@ -6,12 +6,14 @@ import android.content.ContextWrapper; | ||||
| import android.content.res.Configuration; | ||||
| import android.graphics.Point; | ||||
| import android.graphics.Rect; | ||||
| import android.os.Build; | ||||
| import android.util.TypedValue; | ||||
| import android.view.View; | ||||
| import android.view.ViewGroup; | ||||
|  | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.appcompat.app.ActionBar; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
|  | ||||
| import com.termux.shared.logger.Logger; | ||||
| @@ -77,13 +79,13 @@ public class ViewUtils { | ||||
|         boolean isInMultiWindowMode = false; | ||||
|         Context context = view.getContext(); | ||||
|         if (context instanceof AppCompatActivity) { | ||||
|             androidx.appcompat.app.ActionBar actionBar = ((AppCompatActivity) context).getSupportActionBar(); | ||||
|             ActionBar actionBar = ((AppCompatActivity) context).getSupportActionBar(); | ||||
|             if (actionBar != null) actionBarHeight = actionBar.getHeight(); | ||||
|             isInMultiWindowMode = ((AppCompatActivity) context).isInMultiWindowMode(); | ||||
|             isInMultiWindowMode = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) && ((AppCompatActivity) context).isInMultiWindowMode(); | ||||
|         } else if (context instanceof Activity) { | ||||
|             android.app.ActionBar actionBar = ((Activity) context).getActionBar(); | ||||
|             if (actionBar != null) actionBarHeight = actionBar.getHeight(); | ||||
|             isInMultiWindowMode = ((Activity) context).isInMultiWindowMode(); | ||||
|             isInMultiWindowMode = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) && ((Activity) context).isInMultiWindowMode(); | ||||
|         } | ||||
|  | ||||
|         int displayOrientation = getDisplayOrientation(context); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user