diff --git a/frontend/mobile-app/android/app/build.gradle.kts b/frontend/mobile-app/android/app/build.gradle.kts index ec8b7f21..82556cb0 100644 --- a/frontend/mobile-app/android/app/build.gradle.kts +++ b/frontend/mobile-app/android/app/build.gradle.kts @@ -49,7 +49,7 @@ dependencies { } android { - namespace = "com.rwadurian.rwa_android_app" + namespace = "com.durianqueen.app" compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion @@ -64,7 +64,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.rwadurian.rwa_android_app" + applicationId = "com.durianqueen.app" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = flutter.minSdkVersion diff --git a/frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt b/frontend/mobile-app/android/app/src/main/kotlin/com/durianqueen/app/MainActivity.kt similarity index 93% rename from frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt rename to frontend/mobile-app/android/app/src/main/kotlin/com/durianqueen/app/MainActivity.kt index e715c3ef..7e803bc2 100644 --- a/frontend/mobile-app/android/app/src/main/kotlin/com/rwadurian/rwa_android_app/MainActivity.kt +++ b/frontend/mobile-app/android/app/src/main/kotlin/com/durianqueen/app/MainActivity.kt @@ -1,106 +1,106 @@ -package com.rwadurian.rwa_android_app - -import android.content.Intent -import android.net.Uri -import android.os.Build -import android.os.Bundle -import androidx.core.content.FileProvider -import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import io.flutter.embedding.android.FlutterActivity -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugin.common.MethodChannel -import java.io.File - -class MainActivity : FlutterActivity() { - private val INSTALLER_CHANNEL = "com.rwadurian.app/apk_installer" - private val MARKET_CHANNEL = "com.rwadurian.app/app_market" - - override fun onCreate(savedInstanceState: Bundle?) { - // Install splash screen - must be called before super.onCreate() - val splashScreen = installSplashScreen() - - // Keep splash screen visible until Flutter is ready - var keepSplashScreen = true - splashScreen.setKeepOnScreenCondition { keepSplashScreen } - - super.onCreate(savedInstanceState) - - // Dismiss splash screen after a short delay to ensure smooth transition - window.decorView.postDelayed({ - keepSplashScreen = false - }, 300) - } - - override fun configureFlutterEngine(flutterEngine: FlutterEngine) { - super.configureFlutterEngine(flutterEngine) - - // APK 安装器通道 - MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL) - .setMethodCallHandler { call, result -> - when (call.method) { - "installApk" -> { - val apkPath = call.argument("apkPath") - if (apkPath != null) { - try { - installApk(apkPath) - result.success(true) - } catch (e: Exception) { - result.error("INSTALL_FAILED", e.message, null) - } - } else { - result.error("INVALID_PATH", "APK path is null", null) - } - } - else -> result.notImplemented() - } - } - - // 应用市场检测通道 - MethodChannel(flutterEngine.dartExecutor.binaryMessenger, MARKET_CHANNEL) - .setMethodCallHandler { call, result -> - when (call.method) { - "getInstallerPackageName" -> { - try { - val installer = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - packageManager.getInstallSourceInfo(packageName).installingPackageName - } else { - @Suppress("DEPRECATION") - packageManager.getInstallerPackageName(packageName) - } - result.success(installer) - } catch (e: Exception) { - result.success(null) - } - } - else -> result.notImplemented() - } - } - } - - private fun installApk(apkPath: String) { - val apkFile = File(apkPath) - if (!apkFile.exists()) { - throw Exception("APK file not found: $apkPath") - } - - val intent = Intent(Intent.ACTION_VIEW) - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - - val apkUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - FileProvider.getUriForFile( - this, - "${applicationContext.packageName}.fileprovider", - apkFile - ) - } else { - Uri.fromFile(apkFile) - } - - intent.setDataAndType(apkUri, "application/vnd.android.package-archive") - startActivity(intent) - - // 关闭当前应用,让系统完成安装 - finishAffinity() - } -} +package com.durianqueen.app + +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.os.Bundle +import androidx.core.content.FileProvider +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugin.common.MethodChannel +import java.io.File + +class MainActivity : FlutterActivity() { + private val INSTALLER_CHANNEL = "com.durianqueen.app/apk_installer" + private val MARKET_CHANNEL = "com.durianqueen.app/app_market" + + override fun onCreate(savedInstanceState: Bundle?) { + // Install splash screen - must be called before super.onCreate() + val splashScreen = installSplashScreen() + + // Keep splash screen visible until Flutter is ready + var keepSplashScreen = true + splashScreen.setKeepOnScreenCondition { keepSplashScreen } + + super.onCreate(savedInstanceState) + + // Dismiss splash screen after a short delay to ensure smooth transition + window.decorView.postDelayed({ + keepSplashScreen = false + }, 300) + } + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { + super.configureFlutterEngine(flutterEngine) + + // APK 安装器通道 + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL) + .setMethodCallHandler { call, result -> + when (call.method) { + "installApk" -> { + val apkPath = call.argument("apkPath") + if (apkPath != null) { + try { + installApk(apkPath) + result.success(true) + } catch (e: Exception) { + result.error("INSTALL_FAILED", e.message, null) + } + } else { + result.error("INVALID_PATH", "APK path is null", null) + } + } + else -> result.notImplemented() + } + } + + // 应用市场检测通道 + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, MARKET_CHANNEL) + .setMethodCallHandler { call, result -> + when (call.method) { + "getInstallerPackageName" -> { + try { + val installer = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + packageManager.getInstallSourceInfo(packageName).installingPackageName + } else { + @Suppress("DEPRECATION") + packageManager.getInstallerPackageName(packageName) + } + result.success(installer) + } catch (e: Exception) { + result.success(null) + } + } + else -> result.notImplemented() + } + } + } + + private fun installApk(apkPath: String) { + val apkFile = File(apkPath) + if (!apkFile.exists()) { + throw Exception("APK file not found: $apkPath") + } + + val intent = Intent(Intent.ACTION_VIEW) + intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + + val apkUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + FileProvider.getUriForFile( + this, + "${applicationContext.packageName}.fileprovider", + apkFile + ) + } else { + Uri.fromFile(apkFile) + } + + intent.setDataAndType(apkUri, "application/vnd.android.package-archive") + startActivity(intent) + + // 关闭当前应用,让系统完成安装 + finishAffinity() + } +} diff --git a/frontend/mobile-app/lib/core/updater/apk_installer.dart b/frontend/mobile-app/lib/core/updater/apk_installer.dart index 9359dc62..7f8e5506 100644 --- a/frontend/mobile-app/lib/core/updater/apk_installer.dart +++ b/frontend/mobile-app/lib/core/updater/apk_installer.dart @@ -7,7 +7,7 @@ import 'package:permission_handler/permission_handler.dart'; /// 负责调用原生代码安装 APK 文件 class ApkInstaller { static const MethodChannel _channel = - MethodChannel('com.rwadurian.app/apk_installer'); + MethodChannel('com.durianqueen.app/apk_installer'); /// 安装 APK static Future installApk(File apkFile) async { diff --git a/frontend/mobile-app/lib/core/updater/app_market_detector.dart b/frontend/mobile-app/lib/core/updater/app_market_detector.dart index d35a381d..45668646 100644 --- a/frontend/mobile-app/lib/core/updater/app_market_detector.dart +++ b/frontend/mobile-app/lib/core/updater/app_market_detector.dart @@ -7,7 +7,7 @@ import 'package:url_launcher/url_launcher.dart'; /// 检测应用安装来源,决定升级策略 class AppMarketDetector { static const MethodChannel _channel = - MethodChannel('com.rwadurian.app/app_market'); + MethodChannel('com.durianqueen.app/app_market'); /// 常见应用市场包名 static const List _marketPackages = [