Android 集成指南
将 FlexUI SDK(AAR 包)集成到 Android 应用中的完整步骤。
参考项目:
demos/android-demo— 完整的 FlexUI + Agent Runtime 集成示例。
1. 环境要求
| 工具 | 版本要求 |
|---|---|
| Android Studio | Hedgehog+ (2023.1+) |
| Android SDK | compileSdk 33+, minSdk 21+ |
| Kotlin | 1.8+ |
| Gradle | 7.2+ |
| AGP | 7.2.2 |
| NDK | 25.0.8775105(如需编译 native) |
2. 引入 AAR 包
2.1 打包 AAR
在 FlexUI 项目根目录执行:
# Debug 构建
./build.sh pkg --platform android
# Release 构建
./build.sh pkg --platform android --release
产物位于 build/pkg-<date>/android/:
| 文件 | 说明 |
|---|---|
flexui_engine.aar |
原生渲染引擎(C++ DOM + JS 驱动 + 平台连接器),包含所有 native .so |
agent_runtime.aar |
Agent 运行时库(LLM 对话、工具调用、卡片渲染,基于 Jetpack Compose) |
as_apis.aar |
ASCF 小程序 API 实现层 |
2.2 复制 AAR 到项目
将 AAR 文件复制到 app/libs/ 目录:
cp build/pkg-*/android/*.aar <your-project>/app/libs/
2.3 配置 build.gradle
在 app 模块的 build.gradle 中:
// 如果项目使用 fat-aar 合并多个 AAR,可取消注释以下依赖
// AGP 7.4+ 已原生支持 AAR 合并,仅在 AGP < 7.4 时需要
// buildscript {
// dependencies {
// classpath 'com.github.kezong:fat-aar:1.3.8'
// }
// }
// app/build.gradle
android {
compileSdkVersion 33
defaultConfig {
minSdkVersion 21
targetSdkVersion 33
ndk {
abiFilters 'arm64-v8a' // 根据需要添加 'armeabi-v7a', 'x86', 'x86_64'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.7"
}
}
dependencies {
// FlexUI AARs
implementation fileTree(dir: 'libs', include: ['flexui_engine.aar'])
implementation fileTree(dir: 'libs', include: ['agent_runtime.aar'])
implementation fileTree(dir: 'libs', include: ['as_apis.aar'])
// 传递依赖(agent_runtime 需要)
implementation 'androidx.compose.ui:ui:1.5.0'
implementation 'androidx.compose.material3:material3:1.1.0'
implementation 'androidx.compose.material:material-icons-extended:1.5.0'
implementation 'androidx.compose.foundation:foundation:1.5.0'
implementation 'androidx.compose.ui:ui-tooling-preview:1.5.0'
implementation 'androidx.activity:activity-compose:1.7.2'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
// Ktor (HTTP client)
implementation 'io.ktor:ktor-client-core:2.3.8'
implementation 'io.ktor:ktor-client-android:2.3.8'
implementation 'io.ktor:ktor-client-content-negotiation:2.3.8'
implementation 'io.ktor:ktor-serialization-kotlinx-json:2.3.8'
implementation 'io.ktor:ktor-client-logging:2.3.8'
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
// JSON
implementation 'org.json:json:20230227'
}
3. 初始化引擎
3.1 Activity 中初始化 FlexUIEngine
参考 demos/android-demo/src/main/java/org/flexui/agentdemo/MainActivity.kt:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.tencent.mtt.hippy.HippyEngineContext
import com.tencent.mtt.hippy.flexui.FlexUIEngine
import com.tencent.mtt.hippy.flexui.FlexUIEngineConfig
import com.tencent.mtt.hippy.flexui.ContextHolder
import com.tencent.mtt.hippy.flexui.AccountProvider
import com.tencent.mtt.hippy.flexui.PaymentProvider
import com.tencent.mtt.hippy.modules.Promise
import com.tencent.mtt.hippy.modules.nativemodules.HippyNativeModuleBase
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Step 1: 设置 Account/Payment Provider(可选)
ContextHolder.accountProvider = object : AccountProvider {
override fun login(params: Map<String, Any>, promise: Promise) {
promise.resolve(mapOf("errMsg" to "login:ok"))
}
}
ContextHolder.paymentProvider = object : PaymentProvider {
override fun requestPayment(params: Map<String, Any>, promise: Promise) {
promise.resolve(mapOf("errMsg" to "requestPayment:ok"))
}
}
// Step 2: 初始化引擎
FlexUIEngine.ensureInit(
FlexUIEngineConfig(
context = this,
coreJSAssetsPath = "ascf/jsfwk.js", // assets 中的 JS bundle 路径
enableLog = true,
debugMode = false,
debugServerHost = "localhost:38989",
modules = mapOf() // 自定义 Native Module
)
)
}
override fun onDestroy() {
super.onDestroy()
FlexUIEngine.destroy()
}
}
关键参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
context |
Context |
Application 或 Activity Context |
coreJSAssetsPath |
String |
assets 目录下 JS 引擎 bundle 的路径 |
enableLog |
Boolean |
是否启用日志 |
debugMode |
Boolean |
是否启用 CDP 调试模式 |
debugServerHost |
String |
CDP debug server 地址 |
modules |
Map<Class, Creator> |
自定义 Native Module 注册表 |
3.2 assets 资源
将 JS bundle 文件放入 app/src/main/assets/ 目录(如 ascf/jsfwk.js)。
4. 使用 Agent Runtime
4.1 创建 AgentRuntime 实例
参考 demos/android-demo/src/main/java/org/flexui/agentdemo/MainActivity.kt:
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.flexui.agent.AgentRuntime
import org.flexui.agent.AgentRuntimeConfig
val config = AgentRuntimeConfig(
baseUrl = "https://api.deepseek.com/v1", // LLM API 地址
apiKey = "your-api-key", // LLM API Key
model = "deepseek-chat", // 模型名称
skillsBasePath = "ascf-ai-demo/skills", // assets 中 skills 路径
baseBundlePath = "ascf-ai-demo", // assets 中 bundle 路径
maxIterations = 10,
)
val agentRuntime = AgentRuntime(config).apply {
setContext(this@MainActivity)
}
CoroutineScope(Dispatchers.IO).launch {
agentRuntime.initialize()
}
4.2 集成 AgentChatView(Compose)
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import org.flexui.agent.ui.AgentChatView
val composeView = ComposeView(this).apply {
setContent {
AgentChatView(
agentRuntime = agentRuntime,
modifier = Modifier.fillMaxSize(),
startupMessage = "帮我点奶茶",
onError = { error -> Log.e(TAG, "Agent error", error) }
)
}
}
setContentView(composeView)
4.3 注册 AscfAIModule(JS ↔ Native 桥接)
Agent 的 JS bundle 通过 AscfAIModule Native Module 与原生层通信。需要注册为 Hippy NativeModule 并设置 callJS 桥接:
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.tencent.mtt.hippy.common.HippyArray
import com.tencent.mtt.hippy.common.HippyMap
import com.tencent.mtt.hippy.flexui.FlexUIEngine
import com.tencent.mtt.hippy.modules.HippyModulePromise
import com.tencent.mtt.hippy.modules.nativemodules.NativeCallback
import org.flexui.agent.modelcontext.AscfAIModule
private const val TAG = "AscfAIModule"
fun wireAscfAIModule(runtime: AgentRuntime) {
val ascfModule = runtime.getAscfAIModule() ?: return
FlexUIEngine.onReady {
val engine = FlexUIEngine.hippyEngine ?: return@onReady
val engineCtx = engine.engineContext ?: return@onReady
val bridgeManager = engineCtx.bridgeManager ?: return@onReady
// 设置 callJS
val callJS: (String, Array<Any>) -> Unit = { method, args ->
val params = HippyMap()
val hippyArgs = HippyArray()
args.forEach { hippyArgs.pushString(it.toString()) }
params.pushObject("args", hippyArgs)
bridgeManager.callJavaScriptModule(
"__ascfCallbacks", method, params,
HippyModulePromise.BridgeTransferType.BRIDGE_TRANSFER_TYPE_NORMAL
)
}
// 设置 runScript
val runScript: (String) -> Unit = { assetUri ->
bridgeManager.runScriptFromUri(assetUri, false, "", object : NativeCallback(
Handler(Looper.getMainLooper())
) {
override fun Call(result: Long, message: Message?, action: String?, reason: String?) {
if (result == 0L) Log.i(TAG, "runScript OK: $assetUri")
}
})
}
ascfModule.setCallJSBridge(callJS, { _, _ -> "[]" }, runScript)
}
}
5. API 概览
flexui_engine
| 类 | 说明 |
|---|---|
FlexUIEngine |
引擎单例,ensureInit() 初始化,destroy() 销毁,onReady() 就绪回调 |
FlexUIEngineConfig |
引擎配置(context、assets 路径、debug 模式等) |
ContextHolder |
Account/Payment Provider 持有者 |
FlexUIView |
引擎渲染 View |
NativeRender |
原生渲染器(内部类,消费方通常不直接使用,请通过 FlexUIEngine 操作) |
agent_runtime
| 类 | 说明 |
|---|---|
AgentRuntime |
Agent 运行时主入口 |
AgentRuntimeConfig |
Agent 配置(LLM URL、API Key、bundle 路径等) |
AgentChatView |
Compose 聊天 UI 组件 |
FlexCardView |
Compose FlexView 卡片渲染组件 |
AscfAIModule |
JS ↔ Native 桥接模块 |
as_apis
| 类 | 说明 |
|---|---|
ASAPIsModule |
ASCF 小程序 API 注册入口 |
StorageAPI |
本地存储 API |
6. 常见问题
SO 加载失败
现象:UnsatisfiedLinkError 或 java.lang.RuntimeException: so library not found。
解决:
- 确认 AAR 包含对应 ABI 的 .so 文件:解压 AAR,检查
jni/目录 - 确认
build.gradle中abiFilters与实际设备匹配 - 确认
minSdkVersion >= 21
Compose 版本冲突
现象:编译报 Compose 相关类找不到或方法签名不匹配。
解决:确保 composeOptions.kotlinCompilerExtensionVersion 与 Compose 库版本兼容:
- Compose UI 1.5.0 → Compose Compiler 1.4.7 (Kotlin 1.8.21)
- Compose UI 1.6.0+ → Compose Compiler 1.5.x (Kotlin 1.9.x)
Gradle 同步失败
现象:Could not resolve all files。
解决:
- 确认 AAR 文件在
app/libs/目录 - 确认
fileTree的dir路径正确 - 清理 Gradle 缓存:
./gradlew clean --refresh-dependencies
调试日志
# adb logcat 过滤 FlexUI 相关日志
adb logcat -s FlexUI:V Hippy:V AgentRuntime:V