From 00262b4a493b9cefc7477b3edcd43d6311caf9a1 Mon Sep 17 00:00:00 2001 From: bopol Date: Sat, 25 Apr 2020 11:35:15 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Better=20detection=20of=20TV=C2=A0devices?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices were not detected as TV even though they are --- .../java/org/schabi/newpipe/MainActivity.java | 6 ++-- .../org/schabi/newpipe/RouterActivity.java | 2 +- .../newpipe/download/DownloadActivity.java | 2 +- .../fragments/detail/VideoDetailFragment.java | 2 +- .../fragments/list/search/SearchFragment.java | 2 +- .../holder/CommentsMiniInfoItemHolder.java | 2 +- .../newpipe/player/MainVideoPlayer.java | 9 ++--- .../newpipe/settings/SettingsActivity.java | 2 +- .../schabi/newpipe/util/AndroidTvUtils.java | 35 +++++++++++++++---- 9 files changed, 43 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 164a2839a..6f1862f31 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -64,8 +64,8 @@ import org.schabi.newpipe.fragments.MainFragment; import org.schabi.newpipe.fragments.detail.VideoDetailFragment; import org.schabi.newpipe.fragments.list.search.SearchFragment; import org.schabi.newpipe.report.ErrorActivity; -import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.AndroidTvUtils; +import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; @@ -145,7 +145,7 @@ public class MainActivity extends AppCompatActivity { ErrorActivity.reportUiError(this, e); } - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(this)) { FocusOverlayView.setupFocusObserver(this); } } @@ -532,7 +532,7 @@ public class MainActivity extends AppCompatActivity { Log.d(TAG, "onBackPressed() called"); } - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(this)) { View drawerPanel = findViewById(R.id.navigation); if (drawer.isDrawerOpen(drawerPanel)) { drawer.closeDrawers(); diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 264644c74..c927a910f 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -344,7 +344,7 @@ public class RouterActivity extends AppCompatActivity { alertDialog.show(); - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(this)) { FocusOverlayView.setupFocusObserver(alertDialog); } } diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java index c5a0c3a22..e46ded40d 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java @@ -57,7 +57,7 @@ public class DownloadActivity extends AppCompatActivity { } }); - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(this)) { FocusOverlayView.setupFocusObserver(this); } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index eba77847b..35352c013 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -539,7 +539,7 @@ public class VideoDetailFragment extends BaseStateFragment thumbnailBackgroundButton.requestFocus(); - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(getContext())) { // remove ripple effects from detail controls final int transparent = getResources().getColor(R.color.transparent_background_color); detailControlsAddToPlaylist.setBackgroundColor(transparent); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index 71a530b39..ffce053b0 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -511,7 +511,7 @@ public class SearchFragment extends BaseListFragment { - if (!AndroidTvUtils.isTv()) { + if (!AndroidTvUtils.isTv(itemBuilder.getContext())) { ClipboardManager clipboardManager = (ClipboardManager) itemBuilder.getContext() .getSystemService(Context.CLIPBOARD_SERVICE); clipboardManager.setPrimaryClip(ClipData.newPlainText(null, commentText)); diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index d2b1dbd59..570819433 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -179,7 +179,7 @@ public final class MainVideoPlayer extends AppCompatActivity final String orientKey = getString(R.string.last_orientation_landscape_key); final boolean lastOrientationWasLandscape = defaultPreferences - .getBoolean(orientKey, AndroidTvUtils.isTv()); + .getBoolean(orientKey, AndroidTvUtils.isTv(getApplicationContext())); setLandscape(lastOrientationWasLandscape); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); @@ -191,7 +191,7 @@ public final class MainVideoPlayer extends AppCompatActivity Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), false, rotationObserver); - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(this)) { FocusOverlayView.setupFocusObserver(this); } } @@ -223,7 +223,8 @@ public final class MainVideoPlayer extends AppCompatActivity default: break; case KeyEvent.KEYCODE_BACK: - if (AndroidTvUtils.isTv() && playerImpl.isControlsVisible()) { + if (AndroidTvUtils.isTv(getApplicationContext()) + && playerImpl.isControlsVisible()) { playerImpl.hideControls(0, 0); hideSystemUi(); return true; @@ -271,7 +272,7 @@ public final class MainVideoPlayer extends AppCompatActivity final String orientKey = getString(R.string.last_orientation_landscape_key); boolean lastOrientationWasLandscape = defaultPreferences - .getBoolean(orientKey, AndroidTvUtils.isTv()); + .getBoolean(orientKey, AndroidTvUtils.isTv(getApplicationContext())); setLandscape(lastOrientationWasLandscape); } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 46691aa4a..18cbece6f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -62,7 +62,7 @@ public class SettingsActivity extends AppCompatActivity .commit(); } - if (AndroidTvUtils.isTv()) { + if (AndroidTvUtils.isTv(this)) { FocusOverlayView.setupFocusObserver(this); } } diff --git a/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java b/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java index f47eb7107..29c17a9c3 100644 --- a/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java @@ -1,22 +1,45 @@ package org.schabi.newpipe.util; import android.annotation.SuppressLint; +import android.app.UiModeManager; +import android.content.Context; import android.content.pm.PackageManager; - +import android.content.res.Configuration; +import android.os.BatteryManager; import android.view.KeyEvent; + import org.schabi.newpipe.App; +import static android.content.Context.BATTERY_SERVICE; +import static android.content.Context.UI_MODE_SERVICE; + public final class AndroidTvUtils { private static final String AMAZON_FEATURE_FIRE_TV = "amazon.hardware.fire_tv"; - private AndroidTvUtils() { } + private AndroidTvUtils() { + } @SuppressLint("InlinedApi") - public static boolean isTv() { - PackageManager pm = App.getApp().getPackageManager(); + public static boolean isTv(final Context context) { + PackageManager pm = App.getApp().getPackageManager(); - return pm.hasSystemFeature(AMAZON_FEATURE_FIRE_TV) - || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); + + // from doc: https://developer.android.com/training/tv/start/hardware.html#runtime-check + boolean isAndroidTv = ((UiModeManager) context.getSystemService(UI_MODE_SERVICE)) + .getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION; + + boolean isBatteryAbsent = ((BatteryManager) context.getSystemService(BATTERY_SERVICE)) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) == 0; + + return isAndroidTv + || pm.hasSystemFeature(AMAZON_FEATURE_FIRE_TV) + || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK) + || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION) + + //from https://stackoverflow.com/a/58932366 + || (isBatteryAbsent && !pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN) + && pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST) + && pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET)); } public static boolean isConfirmKey(final int keyCode) { From f62f00b4ad227472de6eeb1f442a08eb43f9fb1e Mon Sep 17 00:00:00 2001 From: bopol Date: Sat, 25 Apr 2020 23:38:34 +0200 Subject: [PATCH 2/3] Fix crash on Android 4.4 and surely other sdk versions --- .../schabi/newpipe/util/AndroidTvUtils.java | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java b/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java index 29c17a9c3..8b90a2424 100644 --- a/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java @@ -1,11 +1,11 @@ package org.schabi.newpipe.util; -import android.annotation.SuppressLint; import android.app.UiModeManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.BatteryManager; +import android.os.Build; import android.view.KeyEvent; import org.schabi.newpipe.App; @@ -19,27 +19,30 @@ public final class AndroidTvUtils { private AndroidTvUtils() { } - @SuppressLint("InlinedApi") public static boolean isTv(final Context context) { PackageManager pm = App.getApp().getPackageManager(); - // from doc: https://developer.android.com/training/tv/start/hardware.html#runtime-check - boolean isAndroidTv = ((UiModeManager) context.getSystemService(UI_MODE_SERVICE)) + boolean isTv = ((UiModeManager) context.getSystemService(UI_MODE_SERVICE)) .getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION; - boolean isBatteryAbsent = ((BatteryManager) context.getSystemService(BATTERY_SERVICE)) - .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) == 0; - - return isAndroidTv - || pm.hasSystemFeature(AMAZON_FEATURE_FIRE_TV) - || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK) - || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION) - - //from https://stackoverflow.com/a/58932366 - || (isBatteryAbsent && !pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN) + // from https://stackoverflow.com/a/58932366 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + boolean isBatteryAbsent = ((BatteryManager) context.getSystemService(BATTERY_SERVICE)) + .getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) == 0; + isTv = isTv || (isBatteryAbsent + && !pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN) && pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST) && pm.hasSystemFeature(PackageManager.FEATURE_ETHERNET)); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + isTv = isTv || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); + } + + return isTv + || pm.hasSystemFeature(AMAZON_FEATURE_FIRE_TV) + || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION); } public static boolean isConfirmKey(final int keyCode) { From 77597b329e200fdceff3ac7fc5398f60d3d1e77b Mon Sep 17 00:00:00 2001 From: bopol Date: Sun, 26 Apr 2020 00:36:45 +0200 Subject: [PATCH 3/3] store isTv value to prevent calculating it again and again --- .../org/schabi/newpipe/util/AndroidTvUtils.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java b/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java index 8b90a2424..db2ab4aa7 100644 --- a/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/AndroidTvUtils.java @@ -14,17 +14,25 @@ import static android.content.Context.BATTERY_SERVICE; import static android.content.Context.UI_MODE_SERVICE; public final class AndroidTvUtils { + private static final String AMAZON_FEATURE_FIRE_TV = "amazon.hardware.fire_tv"; + private static Boolean isTV = null; private AndroidTvUtils() { } public static boolean isTv(final Context context) { + if (AndroidTvUtils.isTV != null) { + return AndroidTvUtils.isTV; + } + PackageManager pm = App.getApp().getPackageManager(); // from doc: https://developer.android.com/training/tv/start/hardware.html#runtime-check boolean isTv = ((UiModeManager) context.getSystemService(UI_MODE_SERVICE)) - .getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION; + .getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION + || pm.hasSystemFeature(AMAZON_FEATURE_FIRE_TV) + || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION); // from https://stackoverflow.com/a/58932366 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { @@ -40,9 +48,8 @@ public final class AndroidTvUtils { isTv = isTv || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); } - return isTv - || pm.hasSystemFeature(AMAZON_FEATURE_FIRE_TV) - || pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION); + AndroidTvUtils.isTV = isTv; + return AndroidTvUtils.isTV; } public static boolean isConfirmKey(final int keyCode) {