From 8be769b67c176dd07f8809deb03c8f74a79742bf Mon Sep 17 00:00:00 2001 From: justinzeus Date: Sat, 7 Nov 2026 19:48:04 +0100 Subject: [PATCH] Launch trailers with the vnd.youtube authority form SmartTube can parse --- .../org/justinvisser/wolfskin/tv/TitleTrailerTest.kt | 10 ++++++---- .../java/org/justinvisser/wolfskin/tv/TitleTrailer.kt | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt index afa137ee..b2b6b3e6 100644 --- a/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt +++ b/app/src/test/java/org/justinvisser/wolfskin/tv/TitleTrailerTest.kt @@ -19,21 +19,23 @@ import org.robolectric.annotation.Config @Config(sdk = [34], application = Application::class) class TitleTrailerTest { private val context = ApplicationProvider.getApplicationContext() - private val url = "https://www.youtube.com/watch?v=abcdefghijk" + private val url = "https://www.youtube.com/watch?v=ab_-defghij" @Test fun missingYoutubeHandlerStaysOnTheTitleEvenWhenABrowserExists() { - register(Intent(Intent.ACTION_VIEW, Uri.parse(url)), "test.browser") + register(Intent(Intent.ACTION_VIEW, Uri.parse("https://www.youtube.com/watch?v=ab_-defghij")), "test.browser") assertFalse(TitleTrailer(context).open(url)) assertNull(shadowOf(context as Application).nextStartedActivity) } @Test fun installedYoutubeHandlerReceivesAnExplicitPackageAndNoBrowserUrl() { - register(Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:abcdefghijk")), "test.youtube") + register(Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube://ab_-defghij")), "test.youtube") assertTrue(TitleTrailer(context).open(url)) val launched = shadowOf(context as Application).nextStartedActivity + assertEquals(Intent.ACTION_VIEW, launched.action) assertEquals("test.youtube", launched.`package`) assertEquals("vnd.youtube", launched.data?.scheme) - assertEquals("abcdefghijk", launched.data?.schemeSpecificPart) + // SmartTube (IntentExtractor.extractVideoId) takes the id from Uri.getHost() for this scheme; the opaque `vnd.youtube:ID` form yields null there. + assertEquals("ab_-defghij", launched.data?.host) } @Test fun nonYoutubeTrailerNeverOpensAGeneralViewHandler() { diff --git a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt index 0dce1f9f..7cf330d3 100644 --- a/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt +++ b/app/src/wolfskin/java/org/justinvisser/wolfskin/tv/TitleTrailer.kt @@ -17,7 +17,8 @@ class TitleTrailer(private val context: Context) { ?: source.pathSegments.takeIf { it.firstOrNull() in setOf("shorts", "embed") }?.getOrNull(1) else -> null } ?: return false - val intent = Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube:$video")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + // Authority form: SmartTube's IntentExtractor reads the id from Uri.getHost(), which is null for the opaque `vnd.youtube:ID`. + val intent = Intent(Intent.ACTION_VIEW, Uri.parse("vnd.youtube://$video")).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) val handler = context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY) .firstOrNull { it.activityInfo.exported } ?: return false intent.setPackage(handler.activityInfo.packageName)