From 34ab93c9bd214c02882386db09392e02b59b0540 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Mon, 1 Nov 2021 11:48:20 +0800 Subject: [PATCH 01/10] Fix player controls not hiding if resumed from media button --- app/src/main/java/org/schabi/newpipe/player/Player.java | 3 +++ .../org/schabi/newpipe/player/playback/PlayerMediaSession.java | 1 + 2 files changed, 4 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 22e66e793..4e2a9d065 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -3754,6 +3754,9 @@ public final class Player implements case KeyEvent.KEYCODE_SPACE: if (isFullscreen) { playPause(); + if (isPlaying()) { + hideControls(0, 0); + } } break; case KeyEvent.KEYCODE_BACK: diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java b/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java index 9dcb12344..fbe12efb1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java @@ -88,6 +88,7 @@ public class PlayerMediaSession implements MediaSessionCallback { @Override public void play() { player.play(); + player.hideControls(0, 0); } @Override From 29348411520f56f07865c6deef722ae107b9a205 Mon Sep 17 00:00:00 2001 From: ktprograms Date: Wed, 3 Nov 2021 08:26:13 +0800 Subject: [PATCH 02/10] Enable play/pause with space key even when not in fullscreen player --- app/src/main/java/org/schabi/newpipe/player/Player.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 4e2a9d065..2a88445bb 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -3752,11 +3752,9 @@ public final class Player implements default: break; case KeyEvent.KEYCODE_SPACE: - if (isFullscreen) { - playPause(); - if (isPlaying()) { - hideControls(0, 0); - } + playPause(); + if (isPlaying()) { + hideControls(0, 0); } break; case KeyEvent.KEYCODE_BACK: From 5f16e4ef870e268e325749f9c87f3b68b106c4fe Mon Sep 17 00:00:00 2001 From: Stypox Date: Wed, 2 Mar 2022 12:21:25 +0100 Subject: [PATCH 03/10] Replace R.string.yes with R.string.ok Android doesn't use yes/no but ok/cancel usually, so this should be done here, too --- .../schabi/newpipe/local/playlist/LocalPlaylistFragment.java | 2 +- .../schabi/newpipe/settings/PeertubeInstanceListFragment.java | 2 +- .../org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java | 2 +- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-az/strings.xml | 1 - app/src/main/res/values-b+ast/strings.xml | 1 - app/src/main/res/values-b+uz+Latn/strings.xml | 1 - app/src/main/res/values-b+zh+HANS+CN/strings.xml | 1 - app/src/main/res/values-be/strings.xml | 1 - app/src/main/res/values-ber/strings.xml | 1 - app/src/main/res/values-bg/strings.xml | 1 - app/src/main/res/values-bn-rBD/strings.xml | 1 - app/src/main/res/values-bn-rIN/strings.xml | 1 - app/src/main/res/values-bn/strings.xml | 1 - app/src/main/res/values-ca/strings.xml | 1 - app/src/main/res/values-ckb/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-da/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-eo/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-et/strings.xml | 1 - app/src/main/res/values-eu/strings.xml | 1 - app/src/main/res/values-fa/strings.xml | 1 - app/src/main/res/values-fi/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-gl/strings.xml | 1 - app/src/main/res/values-he/strings.xml | 1 - app/src/main/res/values-hi/strings.xml | 1 - app/src/main/res/values-hr/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-hy/strings.xml | 1 - app/src/main/res/values-ia/strings.xml | 1 - app/src/main/res/values-in/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-kab/strings.xml | 1 - app/src/main/res/values-kmr/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-ku/strings.xml | 1 - app/src/main/res/values-lt/strings.xml | 1 - app/src/main/res/values-lv/strings.xml | 1 - app/src/main/res/values-mk/strings.xml | 1 - app/src/main/res/values-ml/strings.xml | 1 - app/src/main/res/values-ms/strings.xml | 1 - app/src/main/res/values-nb-rNO/strings.xml | 1 - app/src/main/res/values-ne/strings.xml | 1 - app/src/main/res/values-nl-rBE/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-pa/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ro/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sc/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sl/strings.xml | 1 - app/src/main/res/values-so/strings.xml | 1 - app/src/main/res/values-sq/strings.xml | 1 - app/src/main/res/values-sr/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-ta/strings.xml | 1 - app/src/main/res/values-te/strings.xml | 1 - app/src/main/res/values-th/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-tzm/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-ur/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values-zh-rHK/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 1 - app/src/main/res/values/strings.xml | 1 - 76 files changed, 3 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 9ea6c020d..0eb56d716 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -350,7 +350,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment removeWatchedStreams(false)) .setNeutralButton( R.string.remove_watched_popup_yes_and_partially_watched_videos, diff --git a/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java b/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java index dfc053a62..391f17383 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/PeertubeInstanceListFragment.java @@ -191,7 +191,7 @@ public class PeertubeInstanceListFragment extends Fragment { .setTitle(R.string.restore_defaults) .setMessage(R.string.restore_defaults_confirmation) .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.yes, (dialog, which) -> { + .setPositiveButton(R.string.ok, (dialog, which) -> { sharedPreferences.edit().remove(savedInstanceListKey).apply(); selectInstance(PeertubeInstance.defaultInstance); updateInstanceList(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java index 490e299bd..eb879d2f2 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java @@ -136,7 +136,7 @@ public class ChooseTabsFragment extends Fragment { .setTitle(R.string.restore_defaults) .setMessage(R.string.restore_defaults_confirmation) .setNegativeButton(R.string.cancel, null) - .setPositiveButton(R.string.yes, (dialog, which) -> { + .setPositiveButton(R.string.ok, (dialog, which) -> { tabsManager.resetTabs(); updateTabList(); selectedTabsAdapter.notifyDataSetChanged(); diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index a13589c19..d25b478ef 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -91,7 +91,6 @@ محتوى مقيد للبالغين بث مباشر تقرير عن المشكلة - نعم متوقف تنظيف أفضل دقة diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index faad933a7..3e3ac2428 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -169,7 +169,6 @@ Ən yaxşı görüntü keyfiyyəti Təmizlə Deaktiv edilib - Bəli İfaçılar Albomlar Mahnılar diff --git a/app/src/main/res/values-b+ast/strings.xml b/app/src/main/res/values-b+ast/strings.xml index aab0a83bb..29611db80 100644 --- a/app/src/main/res/values-b+ast/strings.xml +++ b/app/src/main/res/values-b+ast/strings.xml @@ -44,7 +44,6 @@ Tarrezmes Formatu de videu predetermináu Prietu - mil mill. mil mill. diff --git a/app/src/main/res/values-b+uz+Latn/strings.xml b/app/src/main/res/values-b+uz+Latn/strings.xml index f984fbea9..6f5a5e8fc 100644 --- a/app/src/main/res/values-b+uz+Latn/strings.xml +++ b/app/src/main/res/values-b+uz+Latn/strings.xml @@ -112,7 +112,6 @@ Eng yaxshi qaror Tozalash Ijrochilar o\'chirib qo\'yilgan - Ha Artistlar Albomlar Qo\'shiqlar diff --git a/app/src/main/res/values-b+zh+HANS+CN/strings.xml b/app/src/main/res/values-b+zh+HANS+CN/strings.xml index 9ae77924a..d9f874de8 100644 --- a/app/src/main/res/values-b+zh+HANS+CN/strings.xml +++ b/app/src/main/res/values-b+zh+HANS+CN/strings.xml @@ -28,7 +28,6 @@ 不支持的 URL 外观 全部 - 网络错误 %s 个视频 diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 249b8ca38..ef81078e2 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -97,7 +97,6 @@ Плэйлісты Дарожкі Карыстальнікі - Так Адключана Ачысціць Лепшае разрозненне diff --git a/app/src/main/res/values-ber/strings.xml b/app/src/main/res/values-ber/strings.xml index 6d49cad2b..0d6c89db5 100644 --- a/app/src/main/res/values-ber/strings.xml +++ b/app/src/main/res/values-ber/strings.xml @@ -56,7 +56,6 @@ ⴰⴼⴰⵢⵍⵓ ⵖⵔ ⵎⴰⵕⵕⴰ ⵉⵜⵜⵡⴰⴽⴽⵙ ⵓⴼⴰⵢⵍⵓ - ⵢⴰⵀ ⵉⴼⵉⴷⵢⵓⵜⵏ ⵎⴰⵕⵕⴰ ⵓⴳⴳⴰⵎⵏ diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 5aac01afb..73c240aae 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -75,7 +75,6 @@ Изтегляния Съобщение за грешка Всички - Да Забранено Изчисти Най-добра резолюция diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 8a014cdf8..807de8735 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -55,7 +55,6 @@ ডাউনলোডগুলি ত্রুটি প্রতিবেদন সবগুলি - হ্যাঁ নিস্ক্রীয় পরিষ্কার diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index d087905a4..ff864b337 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -53,7 +53,6 @@ সবসময় পরিষ্কার নিস্ক্রীয় - হ্যাঁ সবগুলি ত্রুটি প্রতিবেদন ডাউনলোডগুলি diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 89a95c6fb..c17f34ae0 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -176,7 +176,6 @@ সেরা রেজুলিউসন পরিষ্কার নিস্ক্রীয় - হ্যাঁ শিল্পীরা অ্যালবাম গুলি গান গুলি diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 13b8c5ac3..15e43a307 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -37,7 +37,6 @@ Baixades Baixades Tot - Desactivat Neteja Millor resolució diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index 036aa19f5..2eacf992f 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -101,7 +101,6 @@ مۆڵەتنامەی لایەنی-سێیەم مۆڵەتنامەی نیوپایپ پیشاندانی ڕێنمایی ”داگرتن تا پاشکۆ” - بەڵێ دابەشکراوەکان زۆرترین لێدراو لادانی نیشانه‌كراو diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index f65a350fe..2b9df57f7 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -84,7 +84,6 @@ Určete prosím složku pro stahování později v nastavení Co:\\nŽádost:\\nJazyk obsahu\\nZemě obsahu:\\nJazyk aplikace:\\nSlužba:\\nČas GMT:\\nBalíček:\\nVerze:\\nVerze OS: Vše - Ano tis. Otevřít ve vyskakovacím okně mil. diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index d348dc4a2..8fadebacd 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -108,7 +108,6 @@ Numre Brugere - Ja Slået fra Slet Bedste opløsning diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index ba15174a9..0721ebfad 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -88,7 +88,6 @@ Schwarz reCAPTCHA-Aufgabe reCAPTCHA-Aufgabe angefordert - Ja Alle Deaktiviert Im Pop-up-Modus öffnen diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index a57011bc3..5e7fd4940 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -52,7 +52,6 @@ Λήψεις Λήψεις Όλα - Ναι Σφάλμα Αναφορά Πληροφορίες: diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 43798f344..062bda7e8 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -95,7 +95,6 @@ %s filmeto %s filmetoj - Jes Tiu permeso estas necesa por \nmalfermi en ŝprucfenestra modo Ludante en ŝprucfenestra modo diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index bd40f0c61..295fa22f8 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -82,7 +82,6 @@ Lo sucedido:\\nPetición:\\nIdioma del contenido:\\nPaís del contenido:\\nIdioma de la aplicación:\\nServicio:\\nHora GMT:\\nPaquete:\\nVersión:\\nVersión del SO: Negro Todo - k M MM diff --git a/app/src/main/res/values-et/strings.xml b/app/src/main/res/values-et/strings.xml index b22d1e782..c2fd8ef9e 100644 --- a/app/src/main/res/values-et/strings.xml +++ b/app/src/main/res/values-et/strings.xml @@ -93,7 +93,6 @@ Allalaadimised Vea teatamine Kõik - Jah Keelatud Kustuta Parim lahutus diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 88b8d90f9..7a5e274b1 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -62,7 +62,6 @@ Deskargak Errore-txostena Dena - Bai Desgaituta Garbitu Bereizmen onena diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index db8e85f17..34fda3cae 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -109,7 +109,6 @@ کانال‌ها سیاهه‌های پخش کاربران - بله غیرفعال پاک‌کردن پخش همه diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 2c871c051..2bd6ccba8 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -73,7 +73,6 @@ Lataukset Virheraportti Kaikki - Kyllä Poistettu käytöstä Pyyhi Paras resoluutio diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2e4257695..50fe7b687 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -86,7 +86,6 @@ Défi reCAPTCHA demandé Ouvrir en mode pop-up Lecture en mode flottant - Oui Désactivés Quoi :\\nRequest :\\nContent Language :\\nContent Country :\\nApp Language :\\nService :\\nGMT Time :\\nPackage :\\nVersion :\\nOS version : k diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index a9357a5cd..bfe9710f4 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -96,7 +96,6 @@ Listas de reprodución Pistas Usuarios - Si Desactivado Limpar Mellor resolución diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 3ec3ee00b..f3777c909 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -58,7 +58,6 @@ הורדות דוח שגיאה הכול - כן מושבת ניקוי שגיאה diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index d9e9c83d2..46990aad4 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -90,7 +90,6 @@ डाउनलोड त्रुटी की रिपोर्ट सारे - सहमत हूँ बंद करे साफ़ बेहतर विडियो की क्वालिटी diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 09c85052c..92e81f3c0 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -71,7 +71,6 @@ Preuzimanja Prijavi grešku Sve - Da Isključeno Očisti Najbolja rezolucija diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 04fe0cd01..cbe83c4ea 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -111,7 +111,6 @@ Hibaelhárítás Lejátszás felugró ablakban Összes - Igen Letiltva Törlés Legjobb felbontás diff --git a/app/src/main/res/values-hy/strings.xml b/app/src/main/res/values-hy/strings.xml index ea2750a93..e914ff303 100644 --- a/app/src/main/res/values-hy/strings.xml +++ b/app/src/main/res/values-hy/strings.xml @@ -65,7 +65,6 @@ Ֆայլը ջնջվեց Ֆայլ Երգեր - Այո Որոնման պատմություն Փակել diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index 656a37d25..e9d400be2 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -85,7 +85,6 @@ Pistas Usatores Eventos - Si Disactivate Vacuar Melior resolution diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index fb02fd4ff..8c01bbbcb 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -86,7 +86,6 @@ r J T - Ya Buka dalam mode popup Izin ini dibutuhkan untuk \nmembuka di mode sembul diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 524e83a89..90a9cc9c3 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -87,7 +87,6 @@ M Mrd È richiesta la risoluzione del reCAPTCHA - Apri in modalità popup Riproduzione in modalità popup Disattivato diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index f659a9149..74a90752c 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -87,7 +87,6 @@ k M B - はい ポップアップモードで開く ポップアップモードで開くには \n権限の許可が必要です diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index b3679ce82..d84f7f698 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -30,7 +30,6 @@ Sifeḍ ɣer Rnu ɣer Amecwaṛ - Ih Azdam n NewPipe Err-d imezwar Yerna-t %s diff --git a/app/src/main/res/values-kmr/strings.xml b/app/src/main/res/values-kmr/strings.xml index f4af24f36..241192866 100644 --- a/app/src/main/res/values-kmr/strings.xml +++ b/app/src/main/res/values-kmr/strings.xml @@ -169,7 +169,6 @@ NewPipe nermalava kopîleft libre ye: Hûn dikarin li gorî kêfa xwe bikar bînin, parve bikin û baştir bikin. Bi taybetî hûn dikarin wê di bin mercên Lîsansa Giştî ya GNU ya Giştî ya ku ji hêla Weqfa Nermalava Azad ve hatî weşandin de, an guhertoya 3 ya Lîsansê, an jî (li gorî vebijarka we) guhertoyek paşîn ji nû ve belav bikin û / an biguherînin. Zelal Bêmecel - Erê Hunermend Album Stran diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 3c9158753..16dc06956 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -102,7 +102,6 @@ 팝업 모드에서 재생 중 오류 보고 전부 - 해제됨 지우기 최대 해상도 diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index 59c2df022..f4d7056a3 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -86,7 +86,6 @@ دابەزاندنەکان ناتوانرێ سکاڵابکرێ گشتی - بەڵێ ناکارایە پاککردنەوە باشترین قەبارە diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 7608e6821..658b30129 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -58,7 +58,6 @@ Atsisiuntimai Klaidų ataskaita Visi - Taip Išjungta Išvalyti Geriausia raiška diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 6a311be05..6f83ce867 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -236,7 +236,6 @@ Labākā izšķirtspēja Notīrīt Atspējots - Mākslinieki Albūmi Dziesmas diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 392bc39d2..0aaa8d546 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -93,7 +93,6 @@ Превземања Извештај за грешки Сите - Да Оневозможено Избриши Најдобра резолуција diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index 26b4158c4..959e4c5af 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -270,7 +270,6 @@ മികച്ച റിസല്യൂഷൻ തെളിക്കുക അസാധുവാക്കപ്പെട്ടു - അതെ കലാകാരന്മാർ ആൽബങ്ങൾ പാട്ടുകൾ diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index d102b529d..b38105b5a 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -105,7 +105,6 @@ Trek Pengguna Peristiwa - Ya Dinyahdayakan Bersihkan Resolusi terbaik diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 251083236..1735bd0c1 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -89,7 +89,6 @@ Svart Spiller av i oppsprettsmodus Alle - Ja Avskrudd k M diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index d9abdfefd..9cbad12ab 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -111,7 +111,6 @@ ट्रयाकहरु प्रयोगकर्ताहरु घटनाहरू - हो अक्षम स्पष्ट सर्वश्रेष्ठ रेसोलुशन diff --git a/app/src/main/res/values-nl-rBE/strings.xml b/app/src/main/res/values-nl-rBE/strings.xml index 336c654de..542e4a001 100644 --- a/app/src/main/res/values-nl-rBE/strings.xml +++ b/app/src/main/res/values-nl-rBE/strings.xml @@ -93,7 +93,6 @@ Downloads Foutrapport Alles - Ja Uitgeschakeld Wissen Beste resolutie diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 92eabcab1..e9f20e620 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -85,7 +85,6 @@ reCAPTCHA-uitdaging gevraagd Openen in pop-upmodus Alles - Ja k M B diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 005b30a89..68178f37c 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -92,7 +92,6 @@ ਡਾਊਨਲੋਡਸ Error ਰਿਪੋਰਟ ਸਾਰੇ - ਹਾਂ ਬੰਦ ਕੀਤਾ ਮਿਟਾਓ ਵਧੀਆ Resolution diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 93a497d7b..f0e74e4b8 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -95,7 +95,6 @@ Wybierz podpowiedzi, które będą wyświetlane podczas wyszukiwania Odtwarzanie w trybie okienkowym Wszystkie - Tak Wyłączone Wyczyść tys. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 9c1b47d32..a445bf9c1 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -90,7 +90,6 @@ Formato de vídeo padrão Reproduzindo em modo popup Tudo - Sim Desativado k M diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index ef920fb9c..72f05896a 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -395,7 +395,6 @@ Tentativas máximas Histórico Velocidade - Sim Não é possível recuperar esta descarga Mudar nome Nenhuma subscrição selecionada diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 70c50a89e..7d9f6f959 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -83,7 +83,6 @@ Abrir no modo popup Preto Tudo - Sim k M MM diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 802b2ab69..774512671 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -90,7 +90,6 @@ Negru Redare în mod pop-up Toate - Da Dezactivat Aplicația/UI s-a oprit Ce:\\nSolicitare:\\nLimba conținutului:\\nȚara conținutului:\\nLimba aplicației:\\nServiciu:\\nOra GMT:\\nPachet:\\nVersiune: \\nVersiune SO: diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index e5a8e53b8..dd72474e7 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -86,7 +86,6 @@ Чёрная Помнить параметры окна Воспроизведение во всплывающем окне - Да Очистить Всё Что:\\nЗапрос:\\nЯзык контента:\\nСтрана контента:\\nЯзык приложения:\\nСервис:\\nВремя по Гринвичу:\\nПакет:\\nВерсия пакета:\\nВерсия ОС: diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index 1b4e4c37c..599c4a97b 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -415,7 +415,6 @@ Risolutzione mègius Isbòida Disabilitadu - Eja Artista Albums Cantzones diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 1253ef053..13ecd5190 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -87,7 +87,6 @@ M B Požiadavka reCAPTCHA - Áno Spustiť v okne Tieto práva sú potrebné pre \nprehrávanie v mini okne diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 8d13d5f62..4702e7452 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -87,7 +87,6 @@ k mio mrd - Da Odpri v pojavnem načinu To dovoljenje je potrebno za odpiranje \nv pojavnem načinu diff --git a/app/src/main/res/values-so/strings.xml b/app/src/main/res/values-so/strings.xml index 3de28220a..5a9d19448 100644 --- a/app/src/main/res/values-so/strings.xml +++ b/app/src/main/res/values-so/strings.xml @@ -319,7 +319,6 @@ Toos Soo celi Xidhan - Haa Isticmaale Muuqaalo Dhammaan diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index 26ab1997f..d8ca670bd 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -34,7 +34,6 @@ Shkarkimet Raporti i gabimit Të gjitha - Po Në pritje %d i zgjedhur diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 82e8eb953..639eb3171 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -87,7 +87,6 @@ хиљ мил млрд - Да Отвори у искачућем режиму Ова дозвола је потребна за \nотварање у искачућем режиму diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index c632b264c..641722771 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -58,7 +58,6 @@ Hämtningar Felrapport Alla - Ja Inaktiverad Rensa Bästa upplösningen diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index c762d21d4..62368b84b 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -73,7 +73,6 @@ அனைத்தும் ஒளிச்சரங்கள் பயனர்கள் - ஆம் அழி எப்பொழுதும் ஒரு முறை diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 157ad1729..b5d5ef0b7 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -52,7 +52,6 @@ డౌన్ లోడ్ లోపం నివేదిక అన్ని - అవును అన్నింటినీ ప్లే చేయండి న్యూప్యాప్ నోటిఫికేషన్ లోపం diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index bf8e56d75..3c0848af1 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -104,7 +104,6 @@ แทร็ค ผู้ใช้ เหตุการณ์ - ใช่ ปิดการใช้งาน ล้าง ความละเอียดที่ดีที่สุด diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index fa87a4a18..0263336c7 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -86,7 +86,6 @@ Siyah Açılır pencere kipinde oynatılıyor Tümü - Evet Devre dışı Yorumunuz (İngilizce): Ayrıntılar: diff --git a/app/src/main/res/values-tzm/strings.xml b/app/src/main/res/values-tzm/strings.xml index d53dcec8b..5bae4ff2f 100644 --- a/app/src/main/res/values-tzm/strings.xml +++ b/app/src/main/res/values-tzm/strings.xml @@ -123,7 +123,6 @@ Afaylu Ku dwal Sfeḍ - Yah Inaẓuṛen Tiɣennijin Imezza diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 6af7304d8..4a47fe100 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -58,7 +58,6 @@ Завантаження Звіт про помилку Усе - Так Вимкнено Збій застосунку/інтерфейсу Ваш коментар (англійською): diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index f2c5afc33..56e8b7ed7 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -92,7 +92,6 @@ ڈاؤن لوڈز خرابی کی اطلاع تمام - ہاں غیر فعال صاف بہترین ریزولوشن diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index fc923dc3d..0d528a3b9 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -56,7 +56,6 @@ Tải xuống Báo lỗi Tất cả - Vô hiệu Xóa Độ phân giải tốt nhất diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9fec7c065..27b06de45 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -28,7 +28,6 @@ 不支持的 URL 外观 全部 - 网络错误 %s 个视频 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 83085d9e4..233174f06 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -86,7 +86,6 @@ 純黑 以畫中畫模式播放 所有 - App/界面閃退 經過:\\n請求:\\n內容語言:\\n內容國家:\\nApp 語言:\\n服務:\\nGMT 時間:\\n封裝:\\n版本:\\nOS 版本: diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index bc1f40873..53dc34025 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -61,7 +61,6 @@ 下載 錯誤回報 全部 - 是的 已停用 清除 最佳解析度 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8b8945b40..a249f1731 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -168,7 +168,6 @@ Songs Albums Artists - Yes Disabled Clear Best resolution From e588abd4e7414faa8ee0a02e895f404ff5f32e41 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 3 Mar 2022 10:14:58 +0100 Subject: [PATCH 04/10] Restore handling SPACE as play-pause only in fullscreen When not in fullscreen SPACE should be not handled by the player, and hence result in a scroll down --- app/src/main/java/org/schabi/newpipe/player/Player.java | 9 ++++++--- .../newpipe/player/playback/PlayerMediaSession.java | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index 2a88445bb..759c817d5 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -3752,9 +3752,12 @@ public final class Player implements default: break; case KeyEvent.KEYCODE_SPACE: - playPause(); - if (isPlaying()) { - hideControls(0, 0); + if (isFullscreen) { + playPause(); + if (isPlaying()) { + hideControls(0, 0); + } + return true; } break; case KeyEvent.KEYCODE_BACK: diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java b/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java index fbe12efb1..ee0a6f118 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/PlayerMediaSession.java @@ -88,6 +88,7 @@ public class PlayerMediaSession implements MediaSessionCallback { @Override public void play() { player.play(); + // hide the player controls even if the play command came from the media session player.hideControls(0, 0); } From 1602befc513fb20ebe63481e4380ebd0ec34af6e Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Thu, 3 Mar 2022 13:19:06 -0500 Subject: [PATCH 05/10] Move utility methods out of CheckForNewAppVersion --- .../schabi/newpipe/CheckForNewAppVersion.java | 135 +++--------------- .../java/org/schabi/newpipe/MainActivity.java | 3 +- .../settings/MainSettingsFragment.java | 5 +- .../newpipe/settings/SettingsActivity.java | 5 +- .../newpipe/util/ReleaseVersionUtil.java | 96 +++++++++++++ 5 files changed, 121 insertions(+), 123 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 122660d64..ca5862333 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -1,12 +1,9 @@ package org.schabi.newpipe; -import android.app.Application; import android.app.IntentService; import android.app.PendingIntent; import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.Signature; import android.net.Uri; import android.util.Log; @@ -14,29 +11,17 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; -import androidx.core.content.pm.PackageInfoCompat; import androidx.preference.PreferenceManager; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; import com.grack.nanojson.JsonParserException; -import org.schabi.newpipe.error.ErrorInfo; -import org.schabi.newpipe.error.ErrorUtil; -import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.downloader.Response; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; +import org.schabi.newpipe.util.ReleaseVersionUtil; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.List; public final class CheckForNewAppVersion extends IntentService { public CheckForNewAppVersion() { @@ -45,122 +30,45 @@ public final class CheckForNewAppVersion extends IntentService { private static final boolean DEBUG = MainActivity.DEBUG; private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); - - // Public key of the certificate that is used in NewPipe release versions - private static final String RELEASE_CERT_PUBLIC_KEY_SHA1 - = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json"; - /** - * Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133. - * - * @param application The application - * @return String with the APK's SHA1 fingerprint in hexadecimal - */ - @NonNull - private static String getCertificateSHA1Fingerprint(@NonNull final Application application) { - final List signatures; - try { - signatures = PackageInfoCompat.getSignatures(application.getPackageManager(), - application.getPackageName()); - } catch (final PackageManager.NameNotFoundException e) { - ErrorUtil.createNotification(application, new ErrorInfo(e, - UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info")); - return ""; - } - if (signatures.isEmpty()) { - return ""; - } - - final X509Certificate c; - try { - final byte[] cert = signatures.get(0).toByteArray(); - final InputStream input = new ByteArrayInputStream(cert); - final CertificateFactory cf = CertificateFactory.getInstance("X509"); - c = (X509Certificate) cf.generateCertificate(input); - } catch (final CertificateException e) { - ErrorUtil.createNotification(application, new ErrorInfo(e, - UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error")); - return ""; - } - - try { - final MessageDigest md = MessageDigest.getInstance("SHA1"); - final byte[] publicKey = md.digest(c.getEncoded()); - return byte2HexFormatted(publicKey); - } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - ErrorUtil.createNotification(application, new ErrorInfo(e, - UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key")); - return ""; - } - } - - private static String byte2HexFormatted(final byte[] arr) { - final StringBuilder str = new StringBuilder(arr.length * 2); - - for (int i = 0; i < arr.length; i++) { - String h = Integer.toHexString(arr[i]); - final int l = h.length(); - if (l == 1) { - h = "0" + h; - } - if (l > 2) { - h = h.substring(l - 2, l); - } - str.append(h.toUpperCase()); - if (i < (arr.length - 1)) { - str.append(':'); - } - } - return str.toString(); - } - /** * Method to compare the current and latest available app version. * If a newer version is available, we show the update notification. * - * @param application The application * @param versionName Name of new version * @param apkLocationUrl Url with the new apk * @param versionCode Code of new version */ - private static void compareAppVersionAndShowNotification(@NonNull final Application application, - final String versionName, - final String apkLocationUrl, - final int versionCode) { + private static void compareAppVersionAndShowNotification(final String versionName, + final String apkLocationUrl, + final int versionCode) { if (BuildConfig.VERSION_CODE >= versionCode) { return; } + final App app = App.getApp(); // A pending intent to open the apk location url in the browser. final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - final PendingIntent pendingIntent - = PendingIntent.getActivity(application, 0, intent, 0); + final PendingIntent pendingIntent = PendingIntent.getActivity(app, 0, intent, 0); - final String channelId = application - .getString(R.string.app_update_notification_channel_id); + final String channelId = app.getString(R.string.app_update_notification_channel_id); final NotificationCompat.Builder notificationBuilder - = new NotificationCompat.Builder(application, channelId) + = new NotificationCompat.Builder(app, channelId) .setSmallIcon(R.drawable.ic_newpipe_update) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setContentIntent(pendingIntent) .setAutoCancel(true) - .setContentTitle(application - .getString(R.string.app_update_notification_content_title)) - .setContentText(application - .getString(R.string.app_update_notification_content_text) + .setContentTitle(app.getString(R.string.app_update_notification_content_title)) + .setContentText(app.getString(R.string.app_update_notification_content_text) + " " + versionName); final NotificationManagerCompat notificationManager - = NotificationManagerCompat.from(application); + = NotificationManagerCompat.from(app); notificationManager.notify(2000, notificationBuilder.build()); } - public static boolean isReleaseApk(@NonNull final App app) { - return getCertificateSHA1Fingerprint(app).equals(RELEASE_CERT_PUBLIC_KEY_SHA1); - } - private void checkNewVersion() throws IOException, ReCaptchaException { final App app = App.getApp(); @@ -168,7 +76,7 @@ public final class CheckForNewAppVersion extends IntentService { final NewVersionManager manager = new NewVersionManager(); // Check if the current apk is a github one or not. - if (!isReleaseApk(app)) { + if (!ReleaseVersionUtil.isReleaseApk()) { return; } @@ -181,13 +89,13 @@ public final class CheckForNewAppVersion extends IntentService { // Make a network request to get latest NewPipe data. final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL); - handleResponse(response, manager, prefs, app); + handleResponse(response, manager); } private void handleResponse(@NonNull final Response response, - @NonNull final NewVersionManager manager, - @NonNull final SharedPreferences prefs, - @NonNull final App app) { + @NonNull final NewVersionManager manager) { + final App app = App.getApp(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); try { // Store a timestamp which needs to be exceeded, // before a new request to the API is made. @@ -209,14 +117,11 @@ public final class CheckForNewAppVersion extends IntentService { .from(response.responseBody()).getObject("flavors") .getObject("github").getObject("stable"); - final String versionName = githubStableObject - .getString("version"); - final int versionCode = githubStableObject - .getInt("version_code"); - final String apkLocationUrl = githubStableObject - .getString("apk"); + final String versionName = githubStableObject.getString("version"); + final int versionCode = githubStableObject.getInt("version_code"); + final String apkLocationUrl = githubStableObject.getString("apk"); - compareAppVersionAndShowNotification(app, versionName, + compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode); } catch (final JsonParserException e) { // Most likely something is wrong in data received from NEWPIPE_API_URL. diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 95663ea0a..3f0305b5f 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -20,7 +20,6 @@ package org.schabi.newpipe; -import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; import android.content.BroadcastReceiver; @@ -177,7 +176,7 @@ public class MainActivity extends AppCompatActivity { // Start the service which is checking all conditions // and eventually searching for a new version. // The service searching for a new NewPipe version must not be started in background. - startNewVersionCheckService(); + CheckForNewAppVersion.startNewVersionCheckService(); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index d7fb559d6..3776d78f6 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -7,10 +7,9 @@ import android.view.MenuItem; import androidx.annotation.NonNull; -import org.schabi.newpipe.App; -import org.schabi.newpipe.CheckForNewAppVersion; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; +import org.schabi.newpipe.util.ReleaseVersionUtil; public class MainSettingsFragment extends BasePreferenceFragment { public static final boolean DEBUG = MainActivity.DEBUG; @@ -24,7 +23,7 @@ public class MainSettingsFragment extends BasePreferenceFragment { setHasOptionsMenu(true); // Otherwise onCreateOptionsMenu is not called // Check if the app is updatable - if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { + if (!ReleaseVersionUtil.isReleaseApk()) { getPreferenceScreen().removePreference( findPreference(getString(R.string.update_pref_screen_key))); 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 7510bb3bc..7078514dd 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -23,8 +23,6 @@ import androidx.preference.PreferenceFragmentCompat; import com.jakewharton.rxbinding4.widget.RxTextView; -import org.schabi.newpipe.App; -import org.schabi.newpipe.CheckForNewAppVersion; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.SettingsLayoutBinding; @@ -37,6 +35,7 @@ import org.schabi.newpipe.settings.preferencesearch.PreferenceSearchResultListen import org.schabi.newpipe.settings.preferencesearch.PreferenceSearcher; import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.KeyboardUtil; +import org.schabi.newpipe.util.ReleaseVersionUtil; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.views.FocusOverlayView; @@ -267,7 +266,7 @@ public class SettingsActivity extends AppCompatActivity implements */ private void ensureSearchRepresentsApplicationState() { // Check if the update settings are available - if (!CheckForNewAppVersion.isReleaseApk(App.getApp())) { + if (!ReleaseVersionUtil.isReleaseApk()) { SettingsResourceRegistry.getInstance() .getEntryByPreferencesResId(R.xml.update_settings) .setSearchable(false); diff --git a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java new file mode 100644 index 000000000..5b3cfea92 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java @@ -0,0 +1,96 @@ +package org.schabi.newpipe.util; + +import android.content.pm.PackageManager; +import android.content.pm.Signature; + +import androidx.annotation.NonNull; +import androidx.core.content.pm.PackageInfoCompat; + +import org.schabi.newpipe.App; +import org.schabi.newpipe.error.ErrorInfo; +import org.schabi.newpipe.error.ErrorUtil; +import org.schabi.newpipe.error.UserAction; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.List; + +public class ReleaseVersionUtil { + // Public key of the certificate that is used in NewPipe release versions + private static final String RELEASE_CERT_PUBLIC_KEY_SHA1 + = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; + + public static boolean isReleaseApk() { + return getCertificateSHA1Fingerprint().equals(RELEASE_CERT_PUBLIC_KEY_SHA1); + } + + /** + * Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133. + * + * @return String with the APK's SHA1 fingerprint in hexadecimal + */ + @NonNull + private static String getCertificateSHA1Fingerprint() { + final App app = App.getApp(); + final List signatures; + try { + signatures = PackageInfoCompat.getSignatures(app.getPackageManager(), + app.getPackageName()); + } catch (final PackageManager.NameNotFoundException e) { + ErrorUtil.createNotification(app, new ErrorInfo(e, + UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info")); + return ""; + } + if (signatures.isEmpty()) { + return ""; + } + + final X509Certificate c; + try { + final byte[] cert = signatures.get(0).toByteArray(); + final InputStream input = new ByteArrayInputStream(cert); + final CertificateFactory cf = CertificateFactory.getInstance("X509"); + c = (X509Certificate) cf.generateCertificate(input); + } catch (final CertificateException e) { + ErrorUtil.createNotification(app, new ErrorInfo(e, + UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error")); + return ""; + } + + try { + final MessageDigest md = MessageDigest.getInstance("SHA1"); + final byte[] publicKey = md.digest(c.getEncoded()); + return byte2HexFormatted(publicKey); + } catch (NoSuchAlgorithmException | CertificateEncodingException e) { + ErrorUtil.createNotification(app, new ErrorInfo(e, + UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key")); + return ""; + } + } + + private static String byte2HexFormatted(final byte[] arr) { + final StringBuilder str = new StringBuilder(arr.length * 2); + + for (int i = 0; i < arr.length; i++) { + String h = Integer.toHexString(arr[i]); + final int l = h.length(); + if (l == 1) { + h = "0" + h; + } + if (l > 2) { + h = h.substring(l - 2, l); + } + str.append(h.toUpperCase()); + if (i < (arr.length - 1)) { + str.append(':'); + } + } + return str.toString(); + } +} From 0f175de5996abfacf64b8d8cb08d267b75175822 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Thu, 3 Mar 2022 13:21:50 -0500 Subject: [PATCH 06/10] Kotlin-ize ReleaseVersionUtil, merge with NewVersionManager --- .../schabi/newpipe/CheckForNewAppVersion.java | 12 +- .../org/schabi/newpipe/NewVersionManager.kt | 28 ----- .../newpipe/util/ReleaseVersionUtil.java | 96 -------------- .../schabi/newpipe/util/ReleaseVersionUtil.kt | 118 ++++++++++++++++++ .../schabi/newpipe/NewVersionManagerTest.kt | 20 ++- 5 files changed, 130 insertions(+), 144 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/NewVersionManager.kt delete mode 100644 app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java create mode 100644 app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index ca5862333..21673942b 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -73,7 +73,6 @@ public final class CheckForNewAppVersion extends IntentService { final App app = App.getApp(); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); - final NewVersionManager manager = new NewVersionManager(); // Check if the current apk is a github one or not. if (!ReleaseVersionUtil.isReleaseApk()) { @@ -83,24 +82,23 @@ public final class CheckForNewAppVersion extends IntentService { // Check if the last request has happened a certain time ago // to reduce the number of API requests. final long expiry = prefs.getLong(app.getString(R.string.update_expiry_key), 0); - if (!manager.isExpired(expiry)) { + if (!ReleaseVersionUtil.isLastUpdateCheckExpired(expiry)) { return; } // Make a network request to get latest NewPipe data. final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL); - handleResponse(response, manager); + handleResponse(response); } - private void handleResponse(@NonNull final Response response, - @NonNull final NewVersionManager manager) { + private void handleResponse(@NonNull final Response response) { final App app = App.getApp(); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); try { // Store a timestamp which needs to be exceeded, // before a new request to the API is made. - final long newExpiry = manager - .coerceExpiry(response.getHeader("expires")); + final long newExpiry = ReleaseVersionUtil + .coerceUpdateCheckExpiry(response.getHeader("expires")); prefs.edit() .putLong(app.getString(R.string.update_expiry_key), newExpiry) .apply(); diff --git a/app/src/main/java/org/schabi/newpipe/NewVersionManager.kt b/app/src/main/java/org/schabi/newpipe/NewVersionManager.kt deleted file mode 100644 index 36de1ecfc..000000000 --- a/app/src/main/java/org/schabi/newpipe/NewVersionManager.kt +++ /dev/null @@ -1,28 +0,0 @@ -package org.schabi.newpipe - -import java.time.Instant -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter - -class NewVersionManager { - - fun isExpired(expiry: Long): Boolean { - return Instant.ofEpochSecond(expiry).isBefore(Instant.now()) - } - - /** - * Coerce expiry date time in between 6 hours and 72 hours from now - * - * @return Epoch second of expiry date time - */ - fun coerceExpiry(expiryString: String?): Long { - val now = ZonedDateTime.now() - return expiryString?.let { - - var expiry = ZonedDateTime.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(expiryString)) - expiry = maxOf(expiry, now.plusHours(6)) - expiry = minOf(expiry, now.plusHours(72)) - expiry.toEpochSecond() - } ?: now.plusHours(6).toEpochSecond() - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java deleted file mode 100644 index 5b3cfea92..000000000 --- a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.schabi.newpipe.util; - -import android.content.pm.PackageManager; -import android.content.pm.Signature; - -import androidx.annotation.NonNull; -import androidx.core.content.pm.PackageInfoCompat; - -import org.schabi.newpipe.App; -import org.schabi.newpipe.error.ErrorInfo; -import org.schabi.newpipe.error.ErrorUtil; -import org.schabi.newpipe.error.UserAction; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.List; - -public class ReleaseVersionUtil { - // Public key of the certificate that is used in NewPipe release versions - private static final String RELEASE_CERT_PUBLIC_KEY_SHA1 - = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; - - public static boolean isReleaseApk() { - return getCertificateSHA1Fingerprint().equals(RELEASE_CERT_PUBLIC_KEY_SHA1); - } - - /** - * Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133. - * - * @return String with the APK's SHA1 fingerprint in hexadecimal - */ - @NonNull - private static String getCertificateSHA1Fingerprint() { - final App app = App.getApp(); - final List signatures; - try { - signatures = PackageInfoCompat.getSignatures(app.getPackageManager(), - app.getPackageName()); - } catch (final PackageManager.NameNotFoundException e) { - ErrorUtil.createNotification(app, new ErrorInfo(e, - UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not find package info")); - return ""; - } - if (signatures.isEmpty()) { - return ""; - } - - final X509Certificate c; - try { - final byte[] cert = signatures.get(0).toByteArray(); - final InputStream input = new ByteArrayInputStream(cert); - final CertificateFactory cf = CertificateFactory.getInstance("X509"); - c = (X509Certificate) cf.generateCertificate(input); - } catch (final CertificateException e) { - ErrorUtil.createNotification(app, new ErrorInfo(e, - UserAction.CHECK_FOR_NEW_APP_VERSION, "Certificate error")); - return ""; - } - - try { - final MessageDigest md = MessageDigest.getInstance("SHA1"); - final byte[] publicKey = md.digest(c.getEncoded()); - return byte2HexFormatted(publicKey); - } catch (NoSuchAlgorithmException | CertificateEncodingException e) { - ErrorUtil.createNotification(app, new ErrorInfo(e, - UserAction.CHECK_FOR_NEW_APP_VERSION, "Could not retrieve SHA1 key")); - return ""; - } - } - - private static String byte2HexFormatted(final byte[] arr) { - final StringBuilder str = new StringBuilder(arr.length * 2); - - for (int i = 0; i < arr.length; i++) { - String h = Integer.toHexString(arr[i]); - final int l = h.length(); - if (l == 1) { - h = "0" + h; - } - if (l > 2) { - h = h.substring(l - 2, l); - } - str.append(h.toUpperCase()); - if (i < (arr.length - 1)) { - str.append(':'); - } - } - return str.toString(); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt new file mode 100644 index 000000000..4ec2a9614 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt @@ -0,0 +1,118 @@ +package org.schabi.newpipe.util + +import android.content.pm.PackageManager +import android.content.pm.Signature +import androidx.core.content.pm.PackageInfoCompat +import org.schabi.newpipe.App +import org.schabi.newpipe.error.ErrorInfo +import org.schabi.newpipe.error.ErrorUtil.Companion.createNotification +import org.schabi.newpipe.error.UserAction +import java.io.ByteArrayInputStream +import java.io.InputStream +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException +import java.security.cert.CertificateEncodingException +import java.security.cert.CertificateException +import java.security.cert.CertificateFactory +import java.security.cert.X509Certificate +import java.time.Instant +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + +object ReleaseVersionUtil { + // Public key of the certificate that is used in NewPipe release versions + private const val RELEASE_CERT_PUBLIC_KEY_SHA1 = + "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15" + + @JvmStatic + fun isReleaseApk(): Boolean { + return certificateSHA1Fingerprint == RELEASE_CERT_PUBLIC_KEY_SHA1 + } + + /** + * Method to get the APK's SHA1 key. See https://stackoverflow.com/questions/9293019/#22506133. + * + * @return String with the APK's SHA1 fingerprint in hexadecimal + */ + private val certificateSHA1Fingerprint: String + get() { + val app = App.getApp() + val signatures: List = try { + PackageInfoCompat.getSignatures(app.packageManager, app.packageName) + } catch (e: PackageManager.NameNotFoundException) { + showRequestError(app, e, "Could not find package info") + return "" + } + if (signatures.isEmpty()) { + return "" + } + val x509cert = try { + val cert = signatures[0].toByteArray() + val input: InputStream = ByteArrayInputStream(cert) + val cf = CertificateFactory.getInstance("X509") + cf.generateCertificate(input) as X509Certificate + } catch (e: CertificateException) { + showRequestError(app, e, "Certificate error") + return "" + } + + return try { + val md = MessageDigest.getInstance("SHA1") + val publicKey = md.digest(x509cert.encoded) + byte2HexFormatted(publicKey) + } catch (e: NoSuchAlgorithmException) { + showRequestError(app, e, "Could not retrieve SHA1 key") + "" + } catch (e: CertificateEncodingException) { + showRequestError(app, e, "Could not retrieve SHA1 key") + "" + } + } + + private fun byte2HexFormatted(arr: ByteArray): String { + val str = StringBuilder(arr.size * 2) + for (i in arr.indices) { + var h = Integer.toHexString(arr[i].toInt()) + val l = h.length + if (l == 1) { + h = "0$h" + } + if (l > 2) { + h = h.substring(l - 2, l) + } + str.append(h.uppercase()) + if (i < arr.size - 1) { + str.append(':') + } + } + return str.toString() + } + + private fun showRequestError(app: App, e: Exception, request: String) { + createNotification( + app, ErrorInfo(e, UserAction.CHECK_FOR_NEW_APP_VERSION, request) + ) + } + + @JvmStatic + fun isLastUpdateCheckExpired(expiry: Long): Boolean { + return Instant.ofEpochSecond(expiry).isBefore(Instant.now()) + } + + /** + * Coerce expiry date time in between 6 hours and 72 hours from now + * + * @return Epoch second of expiry date time + */ + @JvmStatic + fun coerceUpdateCheckExpiry(expiryString: String?): Long { + val now = ZonedDateTime.now() + return expiryString?.let { + var expiry = + ZonedDateTime.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(expiryString)) + expiry = maxOf(expiry, now.plusHours(6)) + expiry = minOf(expiry, now.plusHours(72)) + expiry.toEpochSecond() + } ?: now.plusHours(6).toEpochSecond() + } +} diff --git a/app/src/test/java/org/schabi/newpipe/NewVersionManagerTest.kt b/app/src/test/java/org/schabi/newpipe/NewVersionManagerTest.kt index d2dacc783..7a2d965f7 100644 --- a/app/src/test/java/org/schabi/newpipe/NewVersionManagerTest.kt +++ b/app/src/test/java/org/schabi/newpipe/NewVersionManagerTest.kt @@ -2,8 +2,9 @@ package org.schabi.newpipe import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue -import org.junit.Before import org.junit.Test +import org.schabi.newpipe.util.ReleaseVersionUtil.coerceUpdateCheckExpiry +import org.schabi.newpipe.util.ReleaseVersionUtil.isLastUpdateCheckExpired import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter @@ -11,18 +12,11 @@ import kotlin.math.abs class NewVersionManagerTest { - private lateinit var manager: NewVersionManager - - @Before - fun setup() { - manager = NewVersionManager() - } - @Test fun `Expiry is reached`() { val oneHourEarlier = Instant.now().atZone(ZoneId.of("GMT")).minusHours(1) - val expired = manager.isExpired(oneHourEarlier.toEpochSecond()) + val expired = isLastUpdateCheckExpired(oneHourEarlier.toEpochSecond()) assertTrue(expired) } @@ -31,7 +25,7 @@ class NewVersionManagerTest { fun `Expiry is not reached`() { val oneHourLater = Instant.now().atZone(ZoneId.of("GMT")).plusHours(1) - val expired = manager.isExpired(oneHourLater.toEpochSecond()) + val expired = isLastUpdateCheckExpired(oneHourLater.toEpochSecond()) assertFalse(expired) } @@ -47,7 +41,7 @@ class NewVersionManagerTest { fun `Expiry must be returned as is because it is inside the acceptable range of 6-72 hours`() { val sixHoursLater = Instant.now().atZone(ZoneId.of("GMT")).plusHours(6) - val coerced = manager.coerceExpiry(DateTimeFormatter.RFC_1123_DATE_TIME.format(sixHoursLater)) + val coerced = coerceUpdateCheckExpiry(DateTimeFormatter.RFC_1123_DATE_TIME.format(sixHoursLater)) assertNearlyEqual(sixHoursLater.toEpochSecond(), coerced) } @@ -56,7 +50,7 @@ class NewVersionManagerTest { fun `Expiry must be increased to 6 hours if below`() { val tooLow = Instant.now().atZone(ZoneId.of("GMT")).plusHours(5) - val coerced = manager.coerceExpiry(DateTimeFormatter.RFC_1123_DATE_TIME.format(tooLow)) + val coerced = coerceUpdateCheckExpiry(DateTimeFormatter.RFC_1123_DATE_TIME.format(tooLow)) assertNearlyEqual(tooLow.plusHours(1).toEpochSecond(), coerced) } @@ -65,7 +59,7 @@ class NewVersionManagerTest { fun `Expiry must be decreased to 72 hours if above`() { val tooHigh = Instant.now().atZone(ZoneId.of("GMT")).plusHours(73) - val coerced = manager.coerceExpiry(DateTimeFormatter.RFC_1123_DATE_TIME.format(tooHigh)) + val coerced = coerceUpdateCheckExpiry(DateTimeFormatter.RFC_1123_DATE_TIME.format(tooHigh)) assertNearlyEqual(tooHigh.minusHours(1).toEpochSecond(), coerced) } From 81fef1be19cac1e4f32aa685180ee7d1448e323c Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Thu, 3 Mar 2022 13:24:12 -0500 Subject: [PATCH 07/10] Migrate CheckForNewAppVersion to JobIntentService --- app/src/main/AndroidManifest.xml | 3 ++- .../schabi/newpipe/CheckForNewAppVersion.java | 18 ++++++++---------- .../java/org/schabi/newpipe/MainActivity.java | 2 +- .../settings/UpdateSettingsFragment.java | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 28cdbf020..2f215a768 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -383,7 +383,8 @@ android:exported="false" /> + android:exported="false" + android:permission="android.permission.BIND_JOB_SERVICE" /> diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java index 21673942b..4ed4d1b1b 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java @@ -1,7 +1,7 @@ package org.schabi.newpipe; -import android.app.IntentService; import android.app.PendingIntent; +import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -9,6 +9,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.app.JobIntentService; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.preference.PreferenceManager; @@ -23,14 +24,12 @@ import org.schabi.newpipe.util.ReleaseVersionUtil; import java.io.IOException; -public final class CheckForNewAppVersion extends IntentService { - public CheckForNewAppVersion() { - super("CheckForNewAppVersion"); - } +public final class CheckForNewAppVersion extends JobIntentService { private static final boolean DEBUG = MainActivity.DEBUG; private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json"; + private static final int JOB_ID = -17000; /** * Method to compare the current and latest available app version. @@ -147,14 +146,13 @@ public final class CheckForNewAppVersion extends IntentService { * * Must not be executed when the app is in background. */ - public static void startNewVersionCheckService() { - final Intent intent = new Intent(App.getApp().getApplicationContext(), - CheckForNewAppVersion.class); - App.getApp().startService(intent); + public static void startNewVersionCheckService(final Context context) { + enqueueWork(context, CheckForNewAppVersion.class, JOB_ID, + new Intent(context, CheckForNewAppVersion.class)); } @Override - protected void onHandleIntent(@Nullable final Intent intent) { + protected void onHandleWork(@Nullable final Intent intent) { try { checkNewVersion(); } catch (final IOException e) { diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 3f0305b5f..6f1bea376 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -176,7 +176,7 @@ public class MainActivity extends AppCompatActivity { // Start the service which is checking all conditions // and eventually searching for a new version. // The service searching for a new NewPipe version must not be started in background. - CheckForNewAppVersion.startNewVersionCheckService(); + CheckForNewAppVersion.startNewVersionCheckService(app); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index 04bad3815..46582cb24 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -33,7 +33,7 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { // Reset the expire time. This is necessary to check for an update immediately. defaultPreferences.edit() .putLong(getString(R.string.update_expiry_key), 0).apply(); - startNewVersionCheckService(); + startNewVersionCheckService(getContext()); } @Override From 71f141f3f8236f2f19e558685f4391c982051cb4 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Thu, 3 Mar 2022 13:26:57 -0500 Subject: [PATCH 08/10] Migrate CheckForNewAppVersion to Worker (and rename it) --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 4 --- .../java/org/schabi/newpipe/MainActivity.java | 5 ++- ...wAppVersion.java => NewVersionWorker.java} | 34 ++++++++++++------- .../settings/UpdateSettingsFragment.java | 5 ++- 5 files changed, 27 insertions(+), 22 deletions(-) rename app/src/main/java/org/schabi/newpipe/{CheckForNewAppVersion.java => NewVersionWorker.java} (87%) diff --git a/app/build.gradle b/app/build.gradle index d78b7e730..35cdde5f4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -220,6 +220,7 @@ dependencies { // https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01 implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01' implementation 'androidx.webkit:webkit:1.4.0' + implementation 'androidx.work:work-runtime:2.7.1' implementation 'com.google.android.material:material:1.4.0' /** Third-party libraries **/ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2f215a768..f9c99819c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -381,10 +381,6 @@ - diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 6f1bea376..b208d8443 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -173,10 +173,9 @@ public class MainActivity extends AppCompatActivity { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); if (prefs.getBoolean(app.getString(R.string.update_app_key), true)) { - // Start the service which is checking all conditions + // Start the worker which is checking all conditions // and eventually searching for a new version. - // The service searching for a new NewPipe version must not be started in background. - CheckForNewAppVersion.startNewVersionCheckService(app); + NewVersionWorker.enqueueNewVersionCheckingWork(app); } } diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.java similarity index 87% rename from app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java rename to app/src/main/java/org/schabi/newpipe/NewVersionWorker.java index 4ed4d1b1b..00405a899 100644 --- a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersion.java +++ b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.java @@ -8,11 +8,14 @@ import android.net.Uri; import android.util.Log; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.app.JobIntentService; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.preference.PreferenceManager; +import androidx.work.OneTimeWorkRequest; +import androidx.work.WorkManager; +import androidx.work.WorkRequest; +import androidx.work.Worker; +import androidx.work.WorkerParameters; import com.grack.nanojson.JsonObject; import com.grack.nanojson.JsonParser; @@ -24,12 +27,16 @@ import org.schabi.newpipe.util.ReleaseVersionUtil; import java.io.IOException; -public final class CheckForNewAppVersion extends JobIntentService { +public final class NewVersionWorker extends Worker { private static final boolean DEBUG = MainActivity.DEBUG; - private static final String TAG = CheckForNewAppVersion.class.getSimpleName(); + private static final String TAG = NewVersionWorker.class.getSimpleName(); private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json"; - private static final int JOB_ID = -17000; + + public NewVersionWorker(@NonNull final Context context, + @NonNull final WorkerParameters workerParams) { + super(context, workerParams); + } /** * Method to compare the current and latest available app version. @@ -130,7 +137,7 @@ public final class CheckForNewAppVersion extends JobIntentService { } /** - * Start a new service which + * Start a new worker which * checks if all conditions for performing a version check are met, * fetches the API endpoint {@link #NEWPIPE_API_URL} containing info * about the latest NewPipe version @@ -144,22 +151,25 @@ public final class CheckForNewAppVersion extends JobIntentService { *
  • The app did not recently check for updates. * We do not want to make unnecessary connections and DOS our servers.
  • * - * Must not be executed when the app is in background. */ - public static void startNewVersionCheckService(final Context context) { - enqueueWork(context, CheckForNewAppVersion.class, JOB_ID, - new Intent(context, CheckForNewAppVersion.class)); + public static void enqueueNewVersionCheckingWork(final Context context) { + final WorkRequest workRequest = + new OneTimeWorkRequest.Builder(NewVersionWorker.class).build(); + WorkManager.getInstance(context).enqueue(workRequest); } + @NonNull @Override - protected void onHandleWork(@Nullable final Intent intent) { + public Result doWork() { try { checkNewVersion(); } catch (final IOException e) { Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e); + return Result.failure(); } catch (final ReCaptchaException e) { Log.e(TAG, "ReCaptchaException should never happen here.", e); + return Result.failure(); } - + return Result.success(); } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java index 46582cb24..1043e88c2 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -1,12 +1,11 @@ package org.schabi.newpipe.settings; -import static org.schabi.newpipe.CheckForNewAppVersion.startNewVersionCheckService; - import android.os.Bundle; import android.widget.Toast; import androidx.preference.Preference; +import org.schabi.newpipe.NewVersionWorker; import org.schabi.newpipe.R; public class UpdateSettingsFragment extends BasePreferenceFragment { @@ -33,7 +32,7 @@ public class UpdateSettingsFragment extends BasePreferenceFragment { // Reset the expire time. This is necessary to check for an update immediately. defaultPreferences.edit() .putLong(getString(R.string.update_expiry_key), 0).apply(); - startNewVersionCheckService(getContext()); + NewVersionWorker.enqueueNewVersionCheckingWork(getContext()); } @Override From b8b97fa6d42e644b7294af4e5b9bf2e1dc96b341 Mon Sep 17 00:00:00 2001 From: TacoTheDank Date: Thu, 3 Mar 2022 13:34:35 -0500 Subject: [PATCH 09/10] Convert NewVersionWorker to Kotlin --- .../org/schabi/newpipe/NewVersionWorker.java | 175 ------------------ .../org/schabi/newpipe/NewVersionWorker.kt | 163 ++++++++++++++++ .../schabi/newpipe/util/ReleaseVersionUtil.kt | 2 - 3 files changed, 163 insertions(+), 177 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/NewVersionWorker.java create mode 100644 app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt diff --git a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.java b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.java deleted file mode 100644 index 00405a899..000000000 --- a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.java +++ /dev/null @@ -1,175 +0,0 @@ -package org.schabi.newpipe; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; -import android.util.Log; - -import androidx.annotation.NonNull; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; -import androidx.preference.PreferenceManager; -import androidx.work.OneTimeWorkRequest; -import androidx.work.WorkManager; -import androidx.work.WorkRequest; -import androidx.work.Worker; -import androidx.work.WorkerParameters; - -import com.grack.nanojson.JsonObject; -import com.grack.nanojson.JsonParser; -import com.grack.nanojson.JsonParserException; - -import org.schabi.newpipe.extractor.downloader.Response; -import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; -import org.schabi.newpipe.util.ReleaseVersionUtil; - -import java.io.IOException; - -public final class NewVersionWorker extends Worker { - - private static final boolean DEBUG = MainActivity.DEBUG; - private static final String TAG = NewVersionWorker.class.getSimpleName(); - private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json"; - - public NewVersionWorker(@NonNull final Context context, - @NonNull final WorkerParameters workerParams) { - super(context, workerParams); - } - - /** - * Method to compare the current and latest available app version. - * If a newer version is available, we show the update notification. - * - * @param versionName Name of new version - * @param apkLocationUrl Url with the new apk - * @param versionCode Code of new version - */ - private static void compareAppVersionAndShowNotification(final String versionName, - final String apkLocationUrl, - final int versionCode) { - if (BuildConfig.VERSION_CODE >= versionCode) { - return; - } - - final App app = App.getApp(); - // A pending intent to open the apk location url in the browser. - final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - final PendingIntent pendingIntent = PendingIntent.getActivity(app, 0, intent, 0); - - final String channelId = app.getString(R.string.app_update_notification_channel_id); - final NotificationCompat.Builder notificationBuilder - = new NotificationCompat.Builder(app, channelId) - .setSmallIcon(R.drawable.ic_newpipe_update) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setContentIntent(pendingIntent) - .setAutoCancel(true) - .setContentTitle(app.getString(R.string.app_update_notification_content_title)) - .setContentText(app.getString(R.string.app_update_notification_content_text) - + " " + versionName); - - final NotificationManagerCompat notificationManager - = NotificationManagerCompat.from(app); - notificationManager.notify(2000, notificationBuilder.build()); - } - - private void checkNewVersion() throws IOException, ReCaptchaException { - final App app = App.getApp(); - - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); - - // Check if the current apk is a github one or not. - if (!ReleaseVersionUtil.isReleaseApk()) { - return; - } - - // Check if the last request has happened a certain time ago - // to reduce the number of API requests. - final long expiry = prefs.getLong(app.getString(R.string.update_expiry_key), 0); - if (!ReleaseVersionUtil.isLastUpdateCheckExpired(expiry)) { - return; - } - - // Make a network request to get latest NewPipe data. - final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL); - handleResponse(response); - } - - private void handleResponse(@NonNull final Response response) { - final App app = App.getApp(); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app); - try { - // Store a timestamp which needs to be exceeded, - // before a new request to the API is made. - final long newExpiry = ReleaseVersionUtil - .coerceUpdateCheckExpiry(response.getHeader("expires")); - prefs.edit() - .putLong(app.getString(R.string.update_expiry_key), newExpiry) - .apply(); - } catch (final Exception e) { - if (DEBUG) { - Log.w(TAG, "Could not extract and save new expiry date", e); - } - } - - // Parse the json from the response. - try { - - final JsonObject githubStableObject = JsonParser.object() - .from(response.responseBody()).getObject("flavors") - .getObject("github").getObject("stable"); - - final String versionName = githubStableObject.getString("version"); - final int versionCode = githubStableObject.getInt("version_code"); - final String apkLocationUrl = githubStableObject.getString("apk"); - - compareAppVersionAndShowNotification(versionName, - apkLocationUrl, versionCode); - } catch (final JsonParserException e) { - // Most likely something is wrong in data received from NEWPIPE_API_URL. - // Do not alarm user and fail silently. - if (DEBUG) { - Log.w(TAG, "Could not get NewPipe API: invalid json", e); - } - } - } - - /** - * Start a new worker which - * checks if all conditions for performing a version check are met, - * fetches the API endpoint {@link #NEWPIPE_API_URL} containing info - * about the latest NewPipe version - * and displays a notification about ana available update. - *
    - * Following conditions need to be met, before data is request from the server: - *
      - *
    • The app is signed with the correct signing key (by TeamNewPipe / schabi). - * If the signing key differs from the one used upstream, the update cannot be installed.
    • - *
    • The user enabled searching for and notifying about updates in the settings.
    • - *
    • The app did not recently check for updates. - * We do not want to make unnecessary connections and DOS our servers.
    • - *
    - */ - public static void enqueueNewVersionCheckingWork(final Context context) { - final WorkRequest workRequest = - new OneTimeWorkRequest.Builder(NewVersionWorker.class).build(); - WorkManager.getInstance(context).enqueue(workRequest); - } - - @NonNull - @Override - public Result doWork() { - try { - checkNewVersion(); - } catch (final IOException e) { - Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e); - return Result.failure(); - } catch (final ReCaptchaException e) { - Log.e(TAG, "ReCaptchaException should never happen here.", e); - return Result.failure(); - } - return Result.success(); - } -} diff --git a/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt new file mode 100644 index 000000000..060114974 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt @@ -0,0 +1,163 @@ +package org.schabi.newpipe + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.util.Log +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat +import androidx.core.content.edit +import androidx.core.net.toUri +import androidx.preference.PreferenceManager +import androidx.work.OneTimeWorkRequest +import androidx.work.WorkManager +import androidx.work.WorkRequest +import androidx.work.Worker +import androidx.work.WorkerParameters +import com.grack.nanojson.JsonParser +import com.grack.nanojson.JsonParserException +import org.schabi.newpipe.extractor.downloader.Response +import org.schabi.newpipe.extractor.exceptions.ReCaptchaException +import org.schabi.newpipe.util.ReleaseVersionUtil.coerceUpdateCheckExpiry +import org.schabi.newpipe.util.ReleaseVersionUtil.isLastUpdateCheckExpired +import org.schabi.newpipe.util.ReleaseVersionUtil.isReleaseApk +import java.io.IOException + +class NewVersionWorker( + context: Context, + workerParams: WorkerParameters +) : Worker(context, workerParams) { + + /** + * Method to compare the current and latest available app version. + * If a newer version is available, we show the update notification. + * + * @param versionName Name of new version + * @param apkLocationUrl Url with the new apk + * @param versionCode Code of new version + */ + private fun compareAppVersionAndShowNotification( + versionName: String, + apkLocationUrl: String?, + versionCode: Int + ) { + if (BuildConfig.VERSION_CODE >= versionCode) { + return + } + val app = App.getApp() + + // A pending intent to open the apk location url in the browser. + val intent = Intent(Intent.ACTION_VIEW, apkLocationUrl?.toUri()) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + val pendingIntent = PendingIntent.getActivity(app, 0, intent, 0) + val channelId = app.getString(R.string.app_update_notification_channel_id) + val notificationBuilder = NotificationCompat.Builder(app, channelId) + .setSmallIcon(R.drawable.ic_newpipe_update) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + .setContentTitle(app.getString(R.string.app_update_notification_content_title)) + .setContentText( + app.getString(R.string.app_update_notification_content_text) + + " " + versionName + ) + val notificationManager = NotificationManagerCompat.from(app) + notificationManager.notify(2000, notificationBuilder.build()) + } + + @Throws(IOException::class, ReCaptchaException::class) + private fun checkNewVersion() { + // Check if the current apk is a github one or not. + if (!isReleaseApk()) { + return + } + + val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) + // Check if the last request has happened a certain time ago + // to reduce the number of API requests. + val expiry = prefs.getLong(applicationContext.getString(R.string.update_expiry_key), 0) + if (!isLastUpdateCheckExpired(expiry)) { + return + } + + // Make a network request to get latest NewPipe data. + val response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL) + handleResponse(response) + } + + private fun handleResponse(response: Response) { + val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext) + try { + // Store a timestamp which needs to be exceeded, + // before a new request to the API is made. + val newExpiry = coerceUpdateCheckExpiry(response.getHeader("expires")) + prefs.edit { + putLong(applicationContext.getString(R.string.update_expiry_key), newExpiry) + } + } catch (e: Exception) { + if (DEBUG) { + Log.w(TAG, "Could not extract and save new expiry date", e) + } + } + + // Parse the json from the response. + try { + val githubStableObject = JsonParser.`object`() + .from(response.responseBody()).getObject("flavors") + .getObject("github").getObject("stable") + + val versionName = githubStableObject.getString("version") + val versionCode = githubStableObject.getInt("version_code") + val apkLocationUrl = githubStableObject.getString("apk") + compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode) + } catch (e: JsonParserException) { + // Most likely something is wrong in data received from NEWPIPE_API_URL. + // Do not alarm user and fail silently. + if (DEBUG) { + Log.w(TAG, "Could not get NewPipe API: invalid json", e) + } + } + } + + override fun doWork(): Result { + try { + checkNewVersion() + } catch (e: IOException) { + Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e) + return Result.failure() + } catch (e: ReCaptchaException) { + Log.e(TAG, "ReCaptchaException should never happen here.", e) + return Result.failure() + } + return Result.success() + } + + companion object { + private val DEBUG = MainActivity.DEBUG + private val TAG = NewVersionWorker::class.java.simpleName + private const val NEWPIPE_API_URL = "https://newpipe.net/api/data.json" + + /** + * Start a new worker which + * checks if all conditions for performing a version check are met, + * fetches the API endpoint [.NEWPIPE_API_URL] containing info + * about the latest NewPipe version + * and displays a notification about ana available update. + *

    + * Following conditions need to be met, before data is request from the server: + * + * * The app is signed with the correct signing key (by TeamNewPipe / schabi). + * If the signing key differs from the one used upstream, the update cannot be installed. + * * The user enabled searching for and notifying about updates in the settings. + * * The app did not recently check for updates. + * We do not want to make unnecessary connections and DOS our servers. + * + */ + @JvmStatic + fun enqueueNewVersionCheckingWork(context: Context) { + val workRequest: WorkRequest = + OneTimeWorkRequest.Builder(NewVersionWorker::class.java).build() + WorkManager.getInstance(context).enqueue(workRequest) + } + } +} diff --git a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt index 4ec2a9614..21a9059e2 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt +++ b/app/src/main/java/org/schabi/newpipe/util/ReleaseVersionUtil.kt @@ -94,7 +94,6 @@ object ReleaseVersionUtil { ) } - @JvmStatic fun isLastUpdateCheckExpired(expiry: Long): Boolean { return Instant.ofEpochSecond(expiry).isBefore(Instant.now()) } @@ -104,7 +103,6 @@ object ReleaseVersionUtil { * * @return Epoch second of expiry date time */ - @JvmStatic fun coerceUpdateCheckExpiry(expiryString: String?): Long { val now = ZonedDateTime.now() return expiryString?.let { From 02fa5aa0fab66760d31e556428099c9de9df35e4 Mon Sep 17 00:00:00 2001 From: ktprograms <71804605+ktprograms@users.noreply.github.com> Date: Wed, 16 Mar 2022 01:32:39 +0800 Subject: [PATCH 10/10] Implement appending queue to playlist in main player (#8008) This also allows saving a remote playlist locally. - Add an "Add to playlist" button to the queue menu in the Player. - Move the appendAllToPlaylist functionality from PlayQueueActivity to Player. Fixes: #8004 --- .../newpipe/player/PlayQueueActivity.java | 33 +++------------- .../org/schabi/newpipe/player/Player.java | 39 +++++++++++++++++++ app/src/main/res/layout/player.xml | 17 +++++++- 3 files changed, 60 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java index e0c5ab083..4bee4ec36 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java +++ b/app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java @@ -1,5 +1,9 @@ package org.schabi.newpipe.player; +import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; +import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; +import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; + import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -23,11 +27,9 @@ import androidx.recyclerview.widget.RecyclerView; import com.google.android.exoplayer2.PlaybackParameters; import org.schabi.newpipe.R; -import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.ActivityPlayerQueueControlBinding; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; -import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.player.event.PlayerEventListener; import org.schabi.newpipe.player.helper.PlaybackParameterDialog; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -42,13 +44,6 @@ import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ThemeHelper; -import java.util.List; -import java.util.stream.Collectors; - -import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu; -import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed; -import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; - public final class PlayQueueActivity extends AppCompatActivity implements PlayerEventListener, SeekBar.OnSeekBarChangeListener, View.OnClickListener, PlaybackParameterDialog.Callback { @@ -129,7 +124,7 @@ public final class PlayQueueActivity extends AppCompatActivity NavigationHelper.openSettings(this); return true; case R.id.action_append_playlist: - appendAllToPlaylist(); + player.onAddToPlaylistClicked(getSupportFragmentManager()); return true; case R.id.action_playback_speed: openPlaybackParameterDialog(); @@ -443,24 +438,6 @@ public final class PlayQueueActivity extends AppCompatActivity seeking = false; } - //////////////////////////////////////////////////////////////////////////// - // Playlist append - //////////////////////////////////////////////////////////////////////////// - - private void appendAllToPlaylist() { - if (player != null && player.getPlayQueue() != null) { - openPlaylistAppendDialog(player.getPlayQueue().getStreams()); - } - } - - private void openPlaylistAppendDialog(final List playQueueItems) { - PlaylistDialog.createCorrespondingDialog( - getApplicationContext(), - playQueueItems.stream().map(StreamEntity::new).collect(Collectors.toList()), - dialog -> dialog.show(getSupportFragmentManager(), TAG) - ); - } - //////////////////////////////////////////////////////////////////////////// // Binding Service Listener //////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/player/Player.java b/app/src/main/java/org/schabi/newpipe/player/Player.java index eb023babd..2bdb14901 100644 --- a/app/src/main/java/org/schabi/newpipe/player/Player.java +++ b/app/src/main/java/org/schabi/newpipe/player/Player.java @@ -105,6 +105,7 @@ import androidx.core.graphics.Insets; import androidx.core.view.GestureDetectorCompat; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import androidx.fragment.app.FragmentManager; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; @@ -138,6 +139,7 @@ import com.squareup.picasso.Target; import org.schabi.newpipe.DownloaderImpl; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; +import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.PlayerBinding; import org.schabi.newpipe.databinding.PlayerPopupCloseOverlayBinding; import org.schabi.newpipe.error.ErrorInfo; @@ -152,6 +154,7 @@ import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; import org.schabi.newpipe.fragments.detail.VideoDetailFragment; import org.schabi.newpipe.info_list.StreamSegmentAdapter; import org.schabi.newpipe.ktx.AnimationType; +import org.schabi.newpipe.local.dialog.PlaylistDialog; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.event.DisplayPortion; @@ -197,6 +200,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.IntStream; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; @@ -541,6 +545,7 @@ public final class Player implements binding.segmentsButton.setOnClickListener(this); binding.repeatButton.setOnClickListener(this); binding.shuffleButton.setOnClickListener(this); + binding.addToPlaylistButton.setOnClickListener(this); binding.playPauseButton.setOnClickListener(this); binding.playPreviousButton.setOnClickListener(this); @@ -2389,6 +2394,32 @@ public final class Player implements + /*////////////////////////////////////////////////////////////////////////// + // Playlist append + //////////////////////////////////////////////////////////////////////////*/ + //region Playlist append + + public void onAddToPlaylistClicked(@NonNull final FragmentManager fragmentManager) { + if (DEBUG) { + Log.d(TAG, "onAddToPlaylistClicked() called"); + } + + if (getPlayQueue() != null) { + PlaylistDialog.createCorrespondingDialog( + getContext(), + getPlayQueue() + .getStreams() + .stream() + .map(StreamEntity::new) + .collect(Collectors.toList()), + dialog -> dialog.show(fragmentManager, TAG) + ); + } + } + //endregion + + + /*////////////////////////////////////////////////////////////////////////// // Mute / Unmute //////////////////////////////////////////////////////////////////////////*/ @@ -3131,6 +3162,7 @@ public final class Player implements binding.itemsListHeaderDuration.setVisibility(View.VISIBLE); binding.shuffleButton.setVisibility(View.VISIBLE); binding.repeatButton.setVisibility(View.VISIBLE); + binding.addToPlaylistButton.setVisibility(View.VISIBLE); hideControls(0, 0); binding.itemsListPanel.requestFocus(); @@ -3168,6 +3200,7 @@ public final class Player implements binding.itemsListHeaderDuration.setVisibility(View.GONE); binding.shuffleButton.setVisibility(View.GONE); binding.repeatButton.setVisibility(View.GONE); + binding.addToPlaylistButton.setVisibility(View.GONE); hideControls(0, 0); binding.itemsListPanel.requestFocus(); @@ -3196,6 +3229,7 @@ public final class Player implements binding.shuffleButton.setVisibility(View.GONE); binding.repeatButton.setVisibility(View.GONE); + binding.addToPlaylistButton.setVisibility(View.GONE); binding.itemsListClose.setOnClickListener(view -> closeItemsList()); } @@ -3733,6 +3767,11 @@ public final class Player implements } else if (v.getId() == binding.shuffleButton.getId()) { onShuffleClicked(); return; + } else if (v.getId() == binding.addToPlaylistButton.getId()) { + if (getParentActivity() != null) { + onAddToPlaylistClicked(getParentActivity().getSupportFragmentManager()); + } + return; } else if (v.getId() == binding.moreOptionsButton.getId()) { onMoreOptionsClicked(); } else if (v.getId() == binding.share.getId()) { diff --git a/app/src/main/res/layout/player.xml b/app/src/main/res/layout/player.xml index 1fc769c18..a6043c65a 100644 --- a/app/src/main/res/layout/player.xml +++ b/app/src/main/res/layout/player.xml @@ -581,6 +581,21 @@ app:srcCompat="@drawable/ic_close" app:tint="@color/white" /> + +