From 677a5800424be462a369622b823e75a88b35a40d Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Tue, 26 Apr 2022 02:31:21 +0500 Subject: [PATCH] Changed: Add general compatibility fixes for `minSdkVerion` `21` --- app/src/main/AndroidManifest.xml | 12 ++- .../java/com/termux/app/TermuxInstaller.java | 3 +- .../java/com/termux/view/TerminalView.java | 5 +- .../support/PopupWindowCompatGingerbread.java | 75 +++++++++++++++++++ .../TextSelectionCursorController.java | 7 ++ .../TextSelectionHandleView.java | 13 +++- .../termux/shared/android/AndroidUtils.java | 9 ++- .../termux/shared/android/PackageUtils.java | 4 + .../shared/android/PermissionUtils.java | 24 +++++- .../shared/file/filesystem/UnixConstants.java | 9 ++- .../termux/shared/interact/ShareUtils.java | 3 +- .../termux/extrakeys/SpecialButtonState.java | 4 +- .../termux/terminal/io/TerminalExtraKeys.java | 14 +++- .../com/termux/shared/view/KeyboardUtils.java | 3 + .../com/termux/shared/view/ViewUtils.java | 8 +- 15 files changed, 168 insertions(+), 25 deletions(-) create mode 100644 terminal-view/src/main/java/com/termux/view/support/PopupWindowCompatGingerbread.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ca1b1e99..4a2bc2f8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -46,7 +46,8 @@ android:requestLegacyExternalStorage="true" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="false" - android:theme="@style/Theme.TermuxApp.DayNight.DarkActionBar"> + android:theme="@style/Theme.TermuxApp.DayNight.DarkActionBar" + tools:targetApi="m"> + android:theme="@style/Theme.TermuxActivity.DayNight.NoActionBar" + tools:targetApi="n"> @@ -91,7 +93,8 @@ android:exported="false" android:label="@string/application_name" android:parentActivityName=".app.TermuxActivity" - android:resizeableActivity="true" /> + android:resizeableActivity="true" + tools:targetApi="n" /> + android:taskAffinity="${TERMUX_PACKAGE_NAME}.filereceiver" + tools:targetApi="n"> diff --git a/app/src/main/java/com/termux/app/TermuxInstaller.java b/app/src/main/java/com/termux/app/TermuxInstaller.java index c3d112ad..15f48bfd 100644 --- a/app/src/main/java/com/termux/app/TermuxInstaller.java +++ b/app/src/main/java/com/termux/app/TermuxInstaller.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; +import android.os.Build; import android.os.Environment; import android.system.Os; import android.util.Pair; @@ -71,7 +72,7 @@ final class TermuxInstaller { // Termux can only be run as the primary user (device owner) since only that // account has the expected file system paths. Verify that: - if (!PackageUtils.isCurrentUserThePrimaryUser(activity)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !PackageUtils.isCurrentUserThePrimaryUser(activity)) { bootstrapErrorMessage = activity.getString(R.string.bootstrap_error_not_primary_user_message, MarkdownUtils.getMarkdownCodeForString(TERMUX_PREFIX_DIR_PATH, false)); Logger.logError(LOG_TAG, "isFilesDirectoryAccessible: " + isFilesDirectoryAccessible); Logger.logError(LOG_TAG, bootstrapErrorMessage); diff --git a/terminal-view/src/main/java/com/termux/view/TerminalView.java b/terminal-view/src/main/java/com/termux/view/TerminalView.java index 2b56d66e..b76ea858 100644 --- a/terminal-view/src/main/java/com/termux/view/TerminalView.java +++ b/terminal-view/src/main/java/com/termux/view/TerminalView.java @@ -1245,6 +1245,7 @@ public final class TerminalView extends View { * Define functions required for long hold toolbar. */ private final Runnable mShowFloatingToolbar = new Runnable() { + @RequiresApi(api = Build.VERSION_CODES.M) @Override public void run() { if (getTextSelectionActionMode() != null) { @@ -1253,6 +1254,7 @@ public final class TerminalView extends View { } }; + @RequiresApi(api = Build.VERSION_CODES.M) private void showFloatingToolbar() { if (getTextSelectionActionMode() != null) { int delay = ViewConfiguration.getDoubleTapTimeout(); @@ -1260,6 +1262,7 @@ public final class TerminalView extends View { } } + @RequiresApi(api = Build.VERSION_CODES.M) void hideFloatingToolbar() { if (getTextSelectionActionMode() != null) { removeCallbacks(mShowFloatingToolbar); @@ -1268,7 +1271,7 @@ public final class TerminalView extends View { } public void updateFloatingToolbarVisibility(MotionEvent event) { - if (getTextSelectionActionMode() != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && getTextSelectionActionMode() != null) { switch (event.getActionMasked()) { case MotionEvent.ACTION_MOVE: hideFloatingToolbar(); diff --git a/terminal-view/src/main/java/com/termux/view/support/PopupWindowCompatGingerbread.java b/terminal-view/src/main/java/com/termux/view/support/PopupWindowCompatGingerbread.java new file mode 100644 index 00000000..24a1797c --- /dev/null +++ b/terminal-view/src/main/java/com/termux/view/support/PopupWindowCompatGingerbread.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +package com.termux.view.support; + +import android.util.Log; +import android.widget.PopupWindow; + +import java.lang.reflect.Method; + +/** + * Implementation of PopupWindow compatibility that can call Gingerbread APIs. + * https://chromium.googlesource.com/android_tools/+/HEAD/sdk/extras/android/support/v4/src/gingerbread/android/support/v4/widget/PopupWindowCompatGingerbread.java + */ +public class PopupWindowCompatGingerbread { + + private static Method sSetWindowLayoutTypeMethod; + private static boolean sSetWindowLayoutTypeMethodAttempted; + private static Method sGetWindowLayoutTypeMethod; + private static boolean sGetWindowLayoutTypeMethodAttempted; + + public static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) { + if (!sSetWindowLayoutTypeMethodAttempted) { + try { + sSetWindowLayoutTypeMethod = PopupWindow.class.getDeclaredMethod( + "setWindowLayoutType", int.class); + sSetWindowLayoutTypeMethod.setAccessible(true); + } catch (Exception e) { + // Reflection method fetch failed. Oh well. + } + sSetWindowLayoutTypeMethodAttempted = true; + } + if (sSetWindowLayoutTypeMethod != null) { + try { + sSetWindowLayoutTypeMethod.invoke(popupWindow, layoutType); + } catch (Exception e) { + // Reflection call failed. Oh well. + } + } + } + + public static int getWindowLayoutType(PopupWindow popupWindow) { + if (!sGetWindowLayoutTypeMethodAttempted) { + try { + sGetWindowLayoutTypeMethod = PopupWindow.class.getDeclaredMethod( + "getWindowLayoutType"); + sGetWindowLayoutTypeMethod.setAccessible(true); + } catch (Exception e) { + // Reflection method fetch failed. Oh well. + } + sGetWindowLayoutTypeMethodAttempted = true; + } + if (sGetWindowLayoutTypeMethod != null) { + try { + return (Integer) sGetWindowLayoutTypeMethod.invoke(popupWindow); + } catch (Exception e) { + // Reflection call failed. Oh well. + } + } + return 0; + } + +} diff --git a/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionCursorController.java b/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionCursorController.java index 2f64793a..c08dca44 100644 --- a/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionCursorController.java +++ b/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionCursorController.java @@ -3,6 +3,7 @@ package com.termux.view.textselection; import android.content.ClipboardManager; import android.content.Context; import android.graphics.Rect; +import android.os.Build; import android.text.TextUtils; import android.view.ActionMode; import android.view.Menu; @@ -153,6 +154,12 @@ public class TextSelectionCursorController implements CursorController { }; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + mActionMode = terminalView.startActionMode(callback); + return; + } + + //noinspection NewApi mActionMode = terminalView.startActionMode(new ActionMode.Callback2() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { diff --git a/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionHandleView.java b/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionHandleView.java index 4f39e723..b3caca67 100644 --- a/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionHandleView.java +++ b/terminal-view/src/main/java/com/termux/view/textselection/TextSelectionHandleView.java @@ -4,6 +4,7 @@ import android.annotation.SuppressLint; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.SystemClock; import android.view.MotionEvent; import android.view.View; @@ -14,6 +15,7 @@ import android.widget.PopupWindow; import com.termux.view.R; import com.termux.view.TerminalView; +import com.termux.view.support.PopupWindowCompatGingerbread; @SuppressLint("ViewConstructor") public class TextSelectionHandleView extends View { @@ -68,13 +70,18 @@ public class TextSelectionHandleView extends View { android.R.attr.textSelectHandleWindowStyle); mHandle.setSplitTouchEnabled(true); mHandle.setClippingEnabled(false); - mHandle.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); mHandle.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT); mHandle.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); mHandle.setBackgroundDrawable(null); mHandle.setAnimationStyle(0); - mHandle.setEnterTransition(null); - mHandle.setExitTransition(null); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + mHandle.setWindowLayoutType(WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); + mHandle.setEnterTransition(null); + mHandle.setExitTransition(null); + } else { + PopupWindowCompatGingerbread.setWindowLayoutType(mHandle, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL); + } mHandle.setContentView(this); } diff --git a/termux-shared/src/main/java/com/termux/shared/android/AndroidUtils.java b/termux-shared/src/main/java/com/termux/shared/android/AndroidUtils.java index 766ea34e..4ddcc3fb 100644 --- a/termux-shared/src/main/java/com/termux/shared/android/AndroidUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/android/AndroidUtils.java @@ -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)); diff --git a/termux-shared/src/main/java/com/termux/shared/android/PackageUtils.java b/termux-shared/src/main/java/com/termux/shared/android/PackageUtils.java index dae7b42b..4447a921 100644 --- a/termux-shared/src/main/java/com/termux/shared/android/PackageUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/android/PackageUtils.java @@ -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; diff --git a/termux-shared/src/main/java/com/termux/shared/android/PermissionUtils.java b/termux-shared/src/main/java/com/termux/shared/android/PermissionUtils.java index ff19a151..60aeed07 100644 --- a/termux-shared/src/main/java/com/termux/shared/android/PermissionUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/android/PermissionUtils.java @@ -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 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())); diff --git a/termux-shared/src/main/java/com/termux/shared/file/filesystem/UnixConstants.java b/termux-shared/src/main/java/com/termux/shared/file/filesystem/UnixConstants.java index 72e7dc2a..9659be7e 100644 --- a/termux-shared/src/main/java/com/termux/shared/file/filesystem/UnixConstants.java +++ b/termux-shared/src/main/java/com/termux/shared/file/filesystem/UnixConstants.java @@ -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; diff --git a/termux-shared/src/main/java/com/termux/shared/interact/ShareUtils.java b/termux-shared/src/main/java/com/termux/shared/interact/ShareUtils.java index c7793f75..4d17af86 100644 --- a/termux-shared/src/main/java/com/termux/shared/interact/ShareUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/interact/ShareUtils.java @@ -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) diff --git a/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/SpecialButtonState.java b/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/SpecialButtonState.java index 3b689529..606dcc4f 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/SpecialButtonState.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/extrakeys/SpecialButtonState.java @@ -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}. */ diff --git a/termux-shared/src/main/java/com/termux/shared/termux/terminal/io/TerminalExtraKeys.java b/termux-shared/src/main/java/com/termux/shared/termux/terminal/io/TerminalExtraKeys.java index 05571f7a..44eb5b02 100644 --- a/termux-shared/src/main/java/com/termux/shared/termux/terminal/io/TerminalExtraKeys.java +++ b/termux-shared/src/main/java/com/termux/shared/termux/terminal/io/TerminalExtraKeys.java @@ -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); + } } } diff --git a/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java b/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java index eee44ec2..5df35d2b 100644 --- a/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/view/KeyboardUtils.java @@ -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(); diff --git a/termux-shared/src/main/java/com/termux/shared/view/ViewUtils.java b/termux-shared/src/main/java/com/termux/shared/view/ViewUtils.java index d85b8290..2f62d74d 100644 --- a/termux-shared/src/main/java/com/termux/shared/view/ViewUtils.java +++ b/termux-shared/src/main/java/com/termux/shared/view/ViewUtils.java @@ -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);