diff --git a/apps/stage-pocket/android/app/build.gradle b/apps/stage-pocket/android/app/build.gradle index 8e7876e01..005114daf 100644 --- a/apps/stage-pocket/android/app/build.gradle +++ b/apps/stage-pocket/android/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'org.jetbrains.kotlin.android' android { namespace = "ai.moeru.airi_pocket" @@ -22,6 +23,9 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + kotlinOptions { + jvmTarget = '21' + } } repositories { diff --git a/apps/stage-pocket/android/app/src/main/java/ai/moeru/airi_pocket/MainActivity.java b/apps/stage-pocket/android/app/src/main/java/ai/moeru/airi_pocket/MainActivity.java deleted file mode 100644 index e9dc211cb..000000000 --- a/apps/stage-pocket/android/app/src/main/java/ai/moeru/airi_pocket/MainActivity.java +++ /dev/null @@ -1,84 +0,0 @@ -package ai.moeru.airi_pocket; - -import android.net.Uri; -import android.net.http.SslError; -import android.webkit.SslErrorHandler; -import android.webkit.WebView; -import com.getcapacitor.Bridge; -import com.getcapacitor.BridgeActivity; -import com.getcapacitor.BridgeWebViewClient; -import com.getcapacitor.Logger; - -public class MainActivity extends BridgeActivity { - - @Override - protected void load() { - super.load(); - - if (bridge == null || !bridge.isDevMode()) { - return; - } - - bridge.setWebViewClient(new DebugTlsBypassWebViewClient(bridge)); - } - - private static final class DebugTlsBypassWebViewClient extends BridgeWebViewClient { - - private final Bridge bridge; - - private DebugTlsBypassWebViewClient(Bridge bridge) { - super(bridge); - this.bridge = bridge; - } - - @Override - public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - if (shouldBypassDevServerCertificate(error)) { - Logger.warn("Bypassing TLS certificate validation for debug dev server: " + error.getUrl()); - handler.proceed(); - return; - } - - super.onReceivedSslError(view, handler, error); - } - - // NOTICE: Android WebView rejects the self-signed HTTPS cert used by the debug dev server. - // Keep this bypass debug-only and scoped to the configured dev server origin. - private boolean shouldBypassDevServerCertificate(SslError error) { - if (error == null) { - return false; - } - - String serverUrl = bridge.getServerUrl(); - String errorUrl = error.getUrl(); - if (serverUrl == null || serverUrl.isEmpty() || errorUrl == null || errorUrl.isEmpty()) { - return false; - } - - Uri serverUri = Uri.parse(serverUrl); - Uri errorUri = Uri.parse(errorUrl); - if (!"https".equalsIgnoreCase(serverUri.getScheme())) { - return false; - } - - return serverUri.getHost().equalsIgnoreCase(errorUri.getHost()) && normalizePort(serverUri) == normalizePort(errorUri); - } - - private int normalizePort(Uri uri) { - int port = uri.getPort(); - if (port != -1) { - return port; - } - - if ("https".equalsIgnoreCase(uri.getScheme())) { - return 443; - } - - if ("http".equalsIgnoreCase(uri.getScheme())) { - return 80; - } - - return -1; - } - } -} diff --git a/apps/stage-pocket/android/app/src/main/java/ai/moeru/airi_pocket/MainActivity.kt b/apps/stage-pocket/android/app/src/main/java/ai/moeru/airi_pocket/MainActivity.kt new file mode 100644 index 000000000..694610a96 --- /dev/null +++ b/apps/stage-pocket/android/app/src/main/java/ai/moeru/airi_pocket/MainActivity.kt @@ -0,0 +1,63 @@ +package ai.moeru.airi_pocket + +import android.net.Uri +import android.net.http.SslError +import android.webkit.SslErrorHandler +import android.webkit.WebView +import com.getcapacitor.Bridge +import com.getcapacitor.BridgeActivity +import com.getcapacitor.BridgeWebViewClient +import com.getcapacitor.Logger + +class MainActivity : BridgeActivity() { + + override fun load() { + super.load() + + val bridge = bridge ?: return + if (!bridge.isDevMode) { + return + } + + bridge.setWebViewClient(DebugTlsBypassWebViewClient(bridge)) + } + + private class DebugTlsBypassWebViewClient( + private val bridge: Bridge, + ) : BridgeWebViewClient(bridge) { + + override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) { + if (shouldBypassDevServerCertificate(error)) { + Logger.warn("Bypassing TLS certificate validation for debug dev server: ${error.url}") + handler.proceed() + return + } + + super.onReceivedSslError(view, handler, error) + } + + // NOTICE: Android WebView rejects the self-signed HTTPS cert used by the debug dev server. + // Keep this bypass debug-only and scoped to the configured dev server origin. + private fun shouldBypassDevServerCertificate(error: SslError?): Boolean { + val serverUrl = bridge.serverUrl?.takeUnless(String::isEmpty) ?: return false + val errorUrl = error?.url?.takeUnless(String::isEmpty) ?: return false + + val serverUri = Uri.parse(serverUrl) + if (!serverUri.scheme.equals("https", ignoreCase = true)) { + return false + } + + val errorUri = Uri.parse(errorUrl) + return serverUri.host.equals(errorUri.host, ignoreCase = true) + && normalizePort(serverUri) == normalizePort(errorUri) + } + + private fun normalizePort(uri: Uri): Int = + uri.port.takeUnless { it == -1 } + ?: when (uri.scheme?.lowercase()) { + "https" -> 443 + "http" -> 80 + else -> -1 + } + } +} diff --git a/apps/stage-pocket/android/build.gradle b/apps/stage-pocket/android/build.gradle index f8f0e43b6..74a1f0c86 100644 --- a/apps/stage-pocket/android/build.gradle +++ b/apps/stage-pocket/android/build.gradle @@ -9,6 +9,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:8.13.0' classpath 'com.google.gms:google-services:4.4.4' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.21' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files