refactor: 更换包名和签名证书以绕过华为风险软件检测
## 更改内容 - 包名: com.rwadurian.rwa_android_app → com.durianqueen.app - 签名证书: 使用新的 durianqueen-release.keystore - MethodChannel: 更新为新包名前缀 ## 原因 华为应用市场 13.2+ 版本对未上架应用检测更严格, 会记录包名和签名,标记为"风险应用"。 更换包名和签名证书让华为识别为全新应用。 ## 注意 - 用户需要卸载旧版本重新安装 - 本地数据会丢失 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1dfa02b386
commit
9508861fd1
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<String>("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<String>("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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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<bool> installApk(File apkFile) async {
|
||||
|
|
|
|||
|
|
@ -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<String> _marketPackages = [
|
||||
|
|
|
|||
Loading…
Reference in New Issue