From 0d6722aa7ad1e249291d497897b2b179bf942685 Mon Sep 17 00:00:00 2001 From: Maufeat Date: Thu, 15 Jan 2026 10:08:10 +0100 Subject: [PATCH] trying to add open android web browser, basically took swkb as template --- .../java/org/yuzu/yuzu_emu/NativeLibrary.kt | 11 ++++ .../yuzu/yuzu_emu/applets/web/WebBrowser.kt | 35 +++++++++++++ src/android/app/src/main/jni/native.cpp | 4 +- src/common/CMakeLists.txt | 4 +- src/common/android/applets/web_browser.cpp | 50 +++++++++++++++++++ src/common/android/applets/web_browser.h | 30 +++++++++++ src/common/android/id_cache.cpp | 3 ++ 7 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/web/WebBrowser.kt create mode 100644 src/common/android/applets/web_browser.cpp create mode 100644 src/common/android/applets/web_browser.h diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 65d13ba2ba..ee10b87a43 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt @@ -26,6 +26,7 @@ import org.yuzu.yuzu_emu.model.InstallResult import org.yuzu.yuzu_emu.model.Patch import org.yuzu.yuzu_emu.model.GameVerificationResult import org.yuzu.yuzu_emu.network.NetPlayManager +import org.yuzu.yuzu_emu.applets.web.WebBrowser /** * Class which contains methods that interact @@ -457,6 +458,16 @@ object NativeLibrary { */ external fun setCurrentAppletId(appletId: Int) + /** + * Launch external URL when Web applet and opens browser + * + * @param String URL + */ + @JvmStatic + fun openExternalUrl(url: String) { + WebBrowser.openExternal(url) + } + /** * Sets the cabinet mode for launching the cabinet applet. * diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/web/WebBrowser.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/web/WebBrowser.kt new file mode 100644 index 0000000000..898c88f4ac --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/applets/web/WebBrowser.kt @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +package org.yuzu.yuzu_emu.applets.web + +import android.content.Intent +import android.net.Uri +import androidx.annotation.Keep +import org.yuzu.yuzu_emu.NativeLibrary +import org.yuzu.yuzu_emu.utils.Log + +/** + Should run WebBrowser as a new intent. +*/ + +@Keep +object WebBrowser { + @JvmStatic + fun openExternal(url: String) { + val activity = NativeLibrary.sEmulationActivity.get() ?: run { + return + } + + activity.runOnUiThread { + try { + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + activity.startActivity(intent) + } catch (e: Exception) { + Log.error("WebBrowser failed to launch $url: ${e.message}") + } + } + } +} diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index e656c2edad..5746659b68 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -66,6 +66,7 @@ #include "core/frontend/applets/profile_select.h" #include "core/frontend/applets/software_keyboard.h" #include "core/frontend/applets/web_browser.h" +#include "common/android/applets/web_browser.h" #include "core/hle/service/am/applet_manager.h" #include "core/hle/service/am/frontend/applets.h" #include "core/hle/service/filesystem/filesystem.h" @@ -275,6 +276,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string // Initialize system. jauto android_keyboard = std::make_unique(); + jauto android_webapplet = std::make_unique(); m_software_keyboard = android_keyboard.get(); m_system.SetShuttingDown(false); m_system.ApplySettings(); @@ -289,7 +291,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string nullptr, // Photo Viewer nullptr, // Profile Selector std::move(android_keyboard), // Software Keyboard - nullptr, // Web Browser + std::move(android_webapplet),// Web Browser nullptr, // Net Connect }); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8ec0f113bb..3d09c1caea 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -176,7 +176,9 @@ if(ANDROID) android/multiplayer/multiplayer.cpp android/multiplayer/multiplayer.h android/applets/software_keyboard.cpp - android/applets/software_keyboard.h) + android/applets/software_keyboard.h + android/applets/web_browser.cpp + android/applets/web_browser.h) endif() if(ARCHITECTURE_x86_64) diff --git a/src/common/android/applets/web_browser.cpp b/src/common/android/applets/web_browser.cpp new file mode 100644 index 0000000000..cf844ff5fc --- /dev/null +++ b/src/common/android/applets/web_browser.cpp @@ -0,0 +1,50 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "common/android/android_common.h" +#include "common/android/id_cache.h" +#include "common/android/applets/web_browser.h" +#include "common/logging/log.h" + +static jclass s_native_library_class = nullptr; +static jmethodID s_open_external_url = nullptr; + +namespace Common::Android::WebBrowser { + +void InitJNI(JNIEnv* env) { + const jclass local = env->FindClass("org/yuzu/yuzu_emu/NativeLibrary"); + s_native_library_class = static_cast(env->NewGlobalRef(local)); + env->DeleteLocalRef(local); + s_open_external_url = env->GetStaticMethodID(s_native_library_class, "openExternalUrl", "(Ljava/lang/String;)V"); +} + +void CleanupJNI(JNIEnv* env) { + if (s_native_library_class != nullptr) { + env->DeleteGlobalRef(s_native_library_class); + s_native_library_class = nullptr; + } + s_open_external_url = nullptr; +} + +void AndroidWebBrowser::OpenLocalWebPage(const std::string& local_url, ExtractROMFSCallback extract_romfs_callback, OpenWebPageCallback callback) const { + LOG_WARNING(Frontend, "(STUBBED)"); + callback(Service::AM::Frontend::WebExitReason::WindowClosed, ""); +} + +void AndroidWebBrowser::OpenExternalWebPage(const std::string& external_url, OpenWebPageCallback callback) const { + // do a dedicated thread, calling from the this thread crashed CPU fiber. + Common::Android::RunJNIOnFiber([&](JNIEnv* env) { + if (env != nullptr && s_native_library_class != nullptr && s_open_external_url != nullptr) { + const jstring j_url = Common::Android::ToJString(env, external_url); + env->CallStaticVoidMethod(s_native_library_class, s_open_external_url, j_url); + env->DeleteLocalRef(j_url); + } else { + LOG_ERROR(Frontend, "JNI not initialized, cannot open {}", external_url); + } + return; + }); + + callback(Service::AM::Frontend::WebExitReason::WindowClosed, external_url); +} + +} // namespace Common::Android::WebBrowser diff --git a/src/common/android/applets/web_browser.h b/src/common/android/applets/web_browser.h new file mode 100644 index 0000000000..a70903e3be --- /dev/null +++ b/src/common/android/applets/web_browser.h @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include + +#include "core/frontend/applets/web_browser.h" + +namespace Common::Android::WebBrowser { + +class AndroidWebBrowser final : public Core::Frontend::WebBrowserApplet { +public: + ~AndroidWebBrowser() override = default; + + void Close() const override {} + + void OpenLocalWebPage(const std::string& local_url, + ExtractROMFSCallback extract_romfs_callback, + OpenWebPageCallback callback) const override; + + void OpenExternalWebPage(const std::string& external_url, + OpenWebPageCallback callback) const override; +}; + +void InitJNI(JNIEnv* env); +void CleanupJNI(JNIEnv* env); + +} // namespace Common::Android::WebBrowser diff --git a/src/common/android/id_cache.cpp b/src/common/android/id_cache.cpp index 1198833996..eb43f4e213 100644 --- a/src/common/android/id_cache.cpp +++ b/src/common/android/id_cache.cpp @@ -4,6 +4,7 @@ #include #include "applets/software_keyboard.h" +#include "applets/web_browser.h" #include "common/android/id_cache.h" #include "common/assert.h" #include "common/fs/fs_android.h" @@ -602,6 +603,7 @@ namespace Common::Android { // Initialize applets Common::Android::SoftwareKeyboard::InitJNI(env); + Common::Android::WebBrowser::InitJNI(env); return JNI_VERSION; } @@ -631,6 +633,7 @@ namespace Common::Android { // UnInitialize applets SoftwareKeyboard::CleanupJNI(env); + WebBrowser::CleanupJNI(env); AndroidMultiplayer::NetworkShutdown(); }