feat: sync httpdns sdk/platform updates without large binaries

This commit is contained in:
robin
2026-03-04 17:59:14 +08:00
parent 853897a6f8
commit 532891fad0
700 changed files with 6096 additions and 2712 deletions

View File

@@ -0,0 +1,33 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.new.ams.httpdns'
compileSdkVersion 34
defaultConfig {
minSdkVersion 21
consumerProguardFiles 'consumer-rules.pro'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '17'
}
}
dependencies {
implementation 'androidx.annotation:annotation:1.8.0'
implementation 'com.new.ams:new-android-httpdns:2.6.7'
}

View File

@@ -0,0 +1,4 @@
# Keep rules for vendor SDK (fill as needed)
# -keep class com.vendor.httpdns.** { *; }
# -dontwarn com.vendor.httpdns.**

View File

@@ -0,0 +1,19 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url 'https://maven.aliyun.com/nexus/content/repositories/releases/' }
}
}
rootProject.name = "httpdns_plugin"

View File

@@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application/>
</manifest>

View File

@@ -0,0 +1,366 @@
package com.TrustAPP.ams.httpdns
import android.content.Context
import android.util.Log
import androidx.annotation.NonNull
import com.Trust.sdk.android.httpdns.HttpDns
import com.Trust.sdk.android.httpdns.HttpDnsService
import com.Trust.sdk.android.httpdns.InitConfig
import com.Trust.sdk.android.httpdns.RequestIpType
import com.Trust.sdk.android.httpdns.log.HttpDnsLog
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
class TrustAPPHttpDnsPlugin : FlutterPlugin, MethodCallHandler {
private lateinit var channel: MethodChannel
private var appContext: Context? = null
private var service: HttpDnsService? = null
private var appId: String? = null
private var secretKey: String? = null
private var primaryServiceHost: String? = null
private var backupServiceHost: String? = null
private var servicePort: Int? = null
private var desiredPersistentCacheEnabled: Boolean? = null
private var desiredDiscardExpiredAfterSeconds: Int? = null
private var desiredReuseExpiredIPEnabled: Boolean? = null
private var desiredLogEnabled: Boolean? = null
private var desiredHttpsEnabled: Boolean? = null
private var desiredPreResolveAfterNetworkChanged: Boolean? = null
private var desiredIPRankingMap: Map<String, Int>? = null
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
appContext = flutterPluginBinding.applicationContext
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "TrustAPP_httpdns")
channel.setMethodCallHandler(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"initialize" -> {
val args = call.arguments as? Map<*, *> ?: emptyMap<String, Any>()
val ctx = appContext
if (ctx == null) {
result.error("no_context", "Android context not attached", null)
return
}
val appIdAny = args["appId"]
val parsedAppId = when (appIdAny) {
is Int -> appIdAny.toString()
is Long -> appIdAny.toString()
is String -> appIdAny.trim()
else -> ""
}
if (parsedAppId.isBlank()) {
Log.i("TrustAPPHttpDns", "initialize missing appId")
result.success(false)
return
}
val primaryHostArg = (args["primaryServiceHost"] as? String)?.trim()
if (primaryHostArg.isNullOrBlank()) {
Log.i("TrustAPPHttpDns", "initialize missing primaryServiceHost")
result.success(false)
return
}
val secret = (args["secretKey"] as? String)?.takeIf { it.isNotBlank() }
val backup = (args["backupServiceHost"] as? String)?.trim()
val port = when (val portAny = args["servicePort"]) {
is Int -> portAny
is Long -> portAny.toInt()
is String -> portAny.toIntOrNull()
else -> null
}
appId = parsedAppId
secretKey = secret
primaryServiceHost = primaryHostArg
backupServiceHost = backup?.trim()?.takeIf { it.isNotEmpty() }
servicePort = if (port != null && port > 0) port else null
Log.i(
"TrustAPPHttpDns",
"initialize appId=$appId, primaryServiceHost=$primaryServiceHost, backupServiceHost=$backupServiceHost, servicePort=$servicePort"
)
result.success(true)
}
"setLogEnabled" -> {
val enabled = call.argument<Boolean>("enabled") == true
desiredLogEnabled = enabled
result.success(null)
}
"setHttpsRequestEnabled" -> {
val enabled = call.argument<Boolean>("enabled") == true
desiredHttpsEnabled = enabled
result.success(null)
}
"setPersistentCacheIPEnabled" -> {
val enabled = call.argument<Boolean>("enabled") == true
val discard = call.argument<Int>("discardExpiredAfterSeconds")
desiredPersistentCacheEnabled = enabled
desiredDiscardExpiredAfterSeconds = discard
result.success(null)
}
"setReuseExpiredIPEnabled" -> {
val enabled = call.argument<Boolean>("enabled") == true
desiredReuseExpiredIPEnabled = enabled
result.success(null)
}
"setPreResolveAfterNetworkChanged" -> {
val enabled = call.argument<Boolean>("enabled") == true
desiredPreResolveAfterNetworkChanged = enabled
result.success(null)
}
"setIPRankingList" -> {
val hostPortMap = call.argument<Map<String, Int>>("hostPortMap")
desiredIPRankingMap = hostPortMap
result.success(null)
}
"setPreResolveHosts" -> {
val hosts = call.argument<List<String>>("hosts") ?: emptyList()
val type = mapIpType(call.argument<String>("ipType") ?: "auto")
try {
service?.setPreResolveHosts(hosts, type)
} catch (_: Throwable) {
}
result.success(null)
}
"getSessionId" -> {
val sid = try {
service?.getSessionId()
} catch (_: Throwable) {
null
}
result.success(sid)
}
"cleanAllHostCache" -> {
try {
service?.cleanHostCache(ArrayList())
} catch (_: Throwable) {
}
result.success(null)
}
"build" -> {
val ctx = appContext
val currentAppId = appId
if (ctx == null || currentAppId.isNullOrBlank()) {
result.success(false)
return
}
try {
desiredLogEnabled?.let { HttpDnsLog.enable(it) }
val builder = InitConfig.Builder()
var hostConfigApplied = false
try {
builder.javaClass.getMethod("setContext", Context::class.java)
.invoke(builder, ctx)
} catch (_: Throwable) {
}
try {
if (!secretKey.isNullOrBlank()) {
builder.javaClass.getMethod("setSecretKey", String::class.java)
.invoke(builder, secretKey)
}
} catch (_: Throwable) {
}
try {
val enableHttps = desiredHttpsEnabled ?: true
builder.javaClass.getMethod("setEnableHttps", Boolean::class.javaPrimitiveType)
.invoke(builder, enableHttps)
} catch (_: Throwable) {
}
try {
builder.javaClass.getMethod("setPrimaryServiceHost", String::class.java)
.invoke(builder, primaryServiceHost)
hostConfigApplied = true
} catch (t: Throwable) {
Log.w("TrustAPPHttpDns", "setPrimaryServiceHost failed: ${t.message}")
}
try {
backupServiceHost?.let {
builder.javaClass.getMethod("setBackupServiceHost", String::class.java)
.invoke(builder, it)
}
} catch (_: Throwable) {
}
try {
servicePort?.let {
builder.javaClass.getMethod("setServicePort", Int::class.javaPrimitiveType)
.invoke(builder, it)
}
} catch (_: Throwable) {
}
try {
desiredPersistentCacheEnabled?.let { enabled ->
val discardSeconds = desiredDiscardExpiredAfterSeconds
if (discardSeconds != null && discardSeconds >= 0) {
val thresholdMillis = discardSeconds.toLong() * 1000L
builder.javaClass.getMethod(
"setEnableCacheIp",
Boolean::class.javaPrimitiveType,
Long::class.javaPrimitiveType
).invoke(builder, enabled, thresholdMillis)
} else {
builder.javaClass.getMethod(
"setEnableCacheIp",
Boolean::class.javaPrimitiveType
).invoke(builder, enabled)
}
}
} catch (_: Throwable) {
}
try {
desiredReuseExpiredIPEnabled?.let {
builder.javaClass.getMethod("setEnableExpiredIp", Boolean::class.javaPrimitiveType)
.invoke(builder, it)
}
} catch (_: Throwable) {
}
try {
desiredPreResolveAfterNetworkChanged?.let {
builder.javaClass.getMethod("setPreResolveAfterNetworkChanged", Boolean::class.javaPrimitiveType)
.invoke(builder, it)
}
} catch (_: Throwable) {
}
try {
desiredIPRankingMap?.let { map ->
if (map.isNotEmpty()) {
val beanClass = Class.forName("com.Trust.sdk.android.httpdns.ranking.IPRankingBean")
val ctor = beanClass.getConstructor(String::class.java, Int::class.javaPrimitiveType)
val list = ArrayList<Any>()
map.forEach { (host, port) ->
list.add(ctor.newInstance(host, port))
}
builder.javaClass.getMethod("setIPRankingList", List::class.java)
.invoke(builder, list)
}
}
} catch (_: Throwable) {
}
if (!hostConfigApplied) {
Log.w("TrustAPPHttpDns", "build failed: sdk core does not support primaryServiceHost")
result.success(false)
return
}
builder.buildFor(currentAppId)
service = if (!secretKey.isNullOrBlank()) {
HttpDns.getService(ctx, currentAppId, secretKey)
} else {
HttpDns.getService(ctx, currentAppId)
}
result.success(true)
} catch (t: Throwable) {
Log.w("TrustAPPHttpDns", "build failed: ${t.message}")
result.success(false)
}
}
"resolveHostSyncNonBlocking" -> {
val hostname = call.argument<String>("hostname")
if (hostname.isNullOrBlank()) {
result.success(mapOf("ipv4" to emptyList<String>(), "ipv6" to emptyList<String>()))
return
}
val type = mapIpType(call.argument<String>("ipType") ?: "auto")
try {
val svc = service ?: run {
val ctx = appContext
val currentAppId = appId
if (ctx != null && !currentAppId.isNullOrBlank()) {
HttpDns.getService(ctx, currentAppId)
} else {
null
}
}
val r = svc?.getHttpDnsResultForHostSyncNonBlocking(hostname, type)
val v4 = r?.ips?.toList() ?: emptyList()
val v6 = r?.ipv6s?.toList() ?: emptyList()
result.success(mapOf("ipv4" to v4, "ipv6" to v6))
} catch (_: Throwable) {
result.success(mapOf("ipv4" to emptyList<String>(), "ipv6" to emptyList<String>()))
}
}
"resolveHostV1" -> {
val hostname = call.argument<String>("hostname")
if (hostname.isNullOrBlank()) {
result.success(mapOf("ipv4" to emptyList<String>(), "ipv6" to emptyList<String>(), "ttl" to 0))
return
}
val qtype = (call.argument<String>("qtype") ?: "A").uppercase()
val cip = call.argument<String>("cip")?.trim()
val requestType = if (qtype == "AAAA") RequestIpType.v6 else RequestIpType.v4
try {
val svc = service ?: run {
val ctx = appContext
val currentAppId = appId
if (ctx != null && !currentAppId.isNullOrBlank()) {
HttpDns.getService(ctx, currentAppId)
} else {
null
}
}
val params = if (!cip.isNullOrEmpty()) mapOf("cip" to cip) else null
val r = svc?.getHttpDnsResultForHostSyncNonBlocking(hostname, requestType, params, hostname)
val v4 = r?.ips?.toList() ?: emptyList()
val v6 = r?.ipv6s?.toList() ?: emptyList()
result.success(
mapOf(
"ipv4" to v4,
"ipv6" to v6,
"ttl" to (r?.ttl ?: 0),
)
)
} catch (_: Throwable) {
result.success(mapOf("ipv4" to emptyList<String>(), "ipv6" to emptyList<String>(), "ttl" to 0))
}
}
else -> result.notImplemented()
}
}
private fun mapIpType(ipType: String): RequestIpType {
return when (ipType.lowercase()) {
"ipv4", "v4" -> RequestIpType.v4
"ipv6", "v6" -> RequestIpType.v6
"both", "64" -> RequestIpType.both
else -> RequestIpType.auto
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
service = null
appContext = null
}
}