From 936a828cb72d20acd00cde494dd331db4e9e5e25 Mon Sep 17 00:00:00 2001 From: Simonx22 Date: Fri, 20 Mar 2026 15:04:32 -0400 Subject: [PATCH] Android: Convert AppLinkHelper to Kotlin --- .../dolphinemu/utils/AppLinkHelper.java | 164 ------------------ .../dolphinemu/utils/AppLinkHelper.kt | 117 +++++++++++++ 2 files changed, 117 insertions(+), 164 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.kt diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.java deleted file mode 100644 index c2f341e116..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.java +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.dolphinemu.dolphinemu.utils; - -import android.net.Uri; - -import androidx.annotation.StringDef; - -import org.dolphinemu.dolphinemu.ui.platform.PlatformTab; - -import java.util.List; - -/** - * Helps link home screen selection to a game. - */ -public class AppLinkHelper -{ - public static final String PLAY = "play"; - public static final String BROWSE = "browse"; - private static final String SCHEMA_URI_PREFIX = "dolphinemu://app/"; - private static final String URI_PLAY = SCHEMA_URI_PREFIX + PLAY; - private static final String URI_VIEW = SCHEMA_URI_PREFIX + BROWSE; - private static final int URI_INDEX_OPTION = 0; - private static final int URI_INDEX_CHANNEL = 1; - private static final int URI_INDEX_GAME = 2; - - public static Uri buildGameUri(long channelId, String gameId) - { - return Uri.parse(URI_PLAY) - .buildUpon() - .appendPath(String.valueOf(channelId)) - .appendPath(String.valueOf(gameId)) - .build(); - } - - public static Uri buildBrowseUri(PlatformTab platformTab) - { - return Uri.parse(URI_VIEW).buildUpon().appendPath(platformTab.getIdString()).build(); - } - - public static AppLinkAction extractAction(Uri uri) - { - if (isGameUri(uri)) - return new PlayAction(extractChannelId(uri), extractGameId(uri)); - else if (isBrowseUri(uri)) - return new BrowseAction(extractSubscriptionName(uri)); - - throw new IllegalArgumentException("No action found for uri " + uri); - } - - private static boolean isGameUri(Uri uri) - { - if (uri.getPathSegments().isEmpty()) - { - return false; - } - String option = uri.getPathSegments().get(URI_INDEX_OPTION); - return PLAY.equals(option); - } - - private static boolean isBrowseUri(Uri uri) - { - if (uri.getPathSegments().isEmpty()) - return false; - - String option = uri.getPathSegments().get(URI_INDEX_OPTION); - return BROWSE.equals(option); - } - - private static String extractSubscriptionName(Uri uri) - { - return extract(uri, URI_INDEX_CHANNEL); - } - - private static long extractChannelId(Uri uri) - { - return extractLong(uri, URI_INDEX_CHANNEL); - } - - private static String extractGameId(Uri uri) - { - return extract(uri, URI_INDEX_GAME); - } - - private static long extractLong(Uri uri, int index) - { - return Long.parseLong(extract(uri, index)); - } - - private static String extract(Uri uri, int index) - { - List pathSegments = uri.getPathSegments(); - if (pathSegments.isEmpty() || pathSegments.size() < index) - return null; - return pathSegments.get(index); - } - - @StringDef({BROWSE, PLAY}) - public @interface ActionFlags - { - } - - /** - * Action for deep linking. - */ - public interface AppLinkAction - { - /** - * Returns an string representation of the action. - */ - @ActionFlags - String getAction(); - } - - /** - * Action when clicking the channel icon - */ - public static class BrowseAction implements AppLinkAction - { - private final String mSubscriptionName; - - private BrowseAction(String subscriptionName) - { - this.mSubscriptionName = subscriptionName; - } - - @Override - public String getAction() - { - return BROWSE; - } - } - - /** - * Action when clicking a program(game) - */ - public static class PlayAction implements AppLinkAction - { - private final long channelId; - private final String gameId; - - private PlayAction(long channelId, String gameId) - { - this.channelId = channelId; - this.gameId = gameId; - } - - public long getChannelId() - { - return channelId; - } - - public String getGameId() - { - return gameId; - } - - @Override - public String getAction() - { - return PLAY; - } - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.kt new file mode 100644 index 0000000000..69cbcb4547 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/AppLinkHelper.kt @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.utils + +import android.net.Uri +import androidx.annotation.StringDef +import org.dolphinemu.dolphinemu.ui.platform.PlatformTab + +/** + * Helps link home screen selection to a game. + */ +object AppLinkHelper { + const val PLAY = "play" + const val BROWSE = "browse" + private const val SCHEMA_URI_PREFIX = "dolphinemu://app/" + private const val URI_PLAY = SCHEMA_URI_PREFIX + PLAY + private const val URI_VIEW = SCHEMA_URI_PREFIX + BROWSE + private const val URI_INDEX_OPTION = 0 + private const val URI_INDEX_CHANNEL = 1 + private const val URI_INDEX_GAME = 2 + + @JvmStatic + fun buildGameUri(channelId: Long, gameId: String): Uri { + return Uri.parse(URI_PLAY).buildUpon().appendPath(channelId.toString()).appendPath(gameId) + .build() + } + + @JvmStatic + fun buildBrowseUri(platformTab: PlatformTab): Uri { + return Uri.parse(URI_VIEW).buildUpon().appendPath(platformTab.idString).build() + } + + @JvmStatic + fun extractAction(uri: Uri): AppLinkAction { + if (isGameUri(uri)) { + return PlayAction(extractChannelId(uri), extractGameId(uri)) + } else if (isBrowseUri(uri)) { + return BrowseAction(extractSubscriptionName(uri)) + } + + throw IllegalArgumentException("No action found for uri $uri") + } + + private fun isGameUri(uri: Uri): Boolean { + if (uri.pathSegments.isEmpty()) { + return false + } + val option = uri.pathSegments[URI_INDEX_OPTION] + return PLAY == option + } + + private fun isBrowseUri(uri: Uri): Boolean { + if (uri.pathSegments.isEmpty()) { + return false + } + + val option = uri.pathSegments[URI_INDEX_OPTION] + return BROWSE == option + } + + private fun extractSubscriptionName(uri: Uri): String { + return extract(uri, URI_INDEX_CHANNEL)!! + } + + private fun extractChannelId(uri: Uri): Long { + return extractLong(uri, URI_INDEX_CHANNEL) + } + + private fun extractGameId(uri: Uri): String { + return extract(uri, URI_INDEX_GAME)!! + } + + private fun extractLong(uri: Uri, index: Int): Long { + return java.lang.Long.parseLong(extract(uri, index)!!) + } + + private fun extract(uri: Uri, index: Int): String? { + val pathSegments = uri.pathSegments + if (pathSegments.isEmpty() || pathSegments.size < index) { + return null + } + return pathSegments[index] + } + + @StringDef(BROWSE, PLAY) + @Retention(AnnotationRetention.SOURCE) + annotation class ActionFlags + + /** + * Action for deep linking. + */ + interface AppLinkAction { + /** + * Returns an string representation of the action. + */ + @get:ActionFlags + val action: String + } + + /** + * Action when clicking the channel icon + */ + class BrowseAction(private val subscriptionName: String) : AppLinkAction { + override val action: String + get() = BROWSE + } + + /** + * Action when clicking a program (game) + */ + class PlayAction( + val channelId: Long, val gameId: String + ) : AppLinkAction { + override val action: String + get() = PLAY + } +}