
llama.cpp Android 集成:Kotlin 开发指南
将 llama.cpp 集成到 Android 应用的分步指南(Kotlin)。JNI 绑定、Vulkan GPU 加速、模型加载以及跨 Android 设备范围的内存管理。
llama.cpp 在 Android 设备上使用 CPU 多线程和 Vulkan GPU 加速运行 GGUF 语言模型。llama.android 项目通过 JNI 提供预构建的 Kotlin 绑定,使 Kotlin 开发者的集成非常简单。
本指南涵盖从项目设置到生产部署的完整集成路径。
集成选项
选项 1:llama.android 库(推荐)
llama.cpp 仓库包含 llama.android,一个带有 Kotlin 绑定的预构建 Android 库。这是实现端侧 AI 最快的途径。
将其添加到您的项目:
- 从 llama.cpp 仓库克隆或下载 llama.android 模块
- 将其作为模块包含在您的 Android 项目中
- 在应用的
build.gradle.kts中添加依赖
dependencies {
implementation(project(":llama"))
}
选项 2:从源码构建
如需更多控制权,使用 Android NDK 将 llama.cpp 构建为原生库:
mkdir build-android && cd build-android
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=$NDK_PATH/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-26 \
-DLLAMA_VULKAN=ON \
-DBUILD_SHARED_LIBS=ON
cmake --build . --config Release
这会生成 libllama.so,将其放入 jniLibs 目录即可。
选项 3:预构建 AAR
一些社区项目将 llama.cpp 发布为 AAR(Android Archive),您可以作为 Maven 依赖项包含。请检查最新且维护中的版本。
项目设置
最低要求
- Android API 26+(Android 8.0)
- ARM64(arm64-v8a)目标架构
- NDK r25+ 用于构建原生代码
- 目标设备 4GB+ RAM(用于 1B 模型)
构建配置
// app/build.gradle.kts
android {
defaultConfig {
ndk {
abiFilters += "arm64-v8a" // 仅 64 位 ARM
}
}
}
权限
推理无需特殊权限。模型下载需要:
<uses-permission android:name="android.permission.INTERNET" />
加载模型
class LlamaEngine(private val context: Context) {
private var model: Long = 0 // 原生指针
private var ctx: Long = 0 // 原生上下文指针
suspend fun loadModel(modelPath: String) = withContext(Dispatchers.Default) {
// 使用 GPU 加速加载模型
model = LlamaNative.loadModel(
modelPath = modelPath,
nGpuLayers = 99, // 将所有层卸载到 Vulkan
)
require(model != 0L) { "Failed to load model" }
// 创建推理上下文
ctx = LlamaNative.createContext(
model = model,
nCtx = 2048, // 上下文窗口
nThreads = 4, // CPU 线程数
nBatch = 512, // 批次大小
)
require(ctx != 0L) { "Failed to create context" }
}
fun unload() {
if (ctx != 0L) {
LlamaNative.freeContext(ctx)
ctx = 0
}
if (model != 0L) {
LlamaNative.freeModel(model)
model = 0
}
}
}
Vulkan GPU 加速
Vulkan 是 Android 的 GPU 计算 API。llama.cpp 使用它来加速推理过程中的矩阵运算。通过将 nGpuLayers 设置为模型的层数来启用。
Vulkan 支持取决于设备:
- 骁龙 8 Gen 2+:完 整 Vulkan 计算支持,性能最佳
- Tensor G3/G4:良好的 Vulkan 支持
- 骁龙 7 Gen 3+:支持 Vulkan,中等加速效果
- 旧款/入门级设备:可能缺少 Vulkan 计算支持。自动回退到 CPU。
运行时检查 Vulkan 可用性:
fun isVulkanAvailable(): Boolean {
return try {
val vk = android.hardware.HardwareBuffer::class.java
android.os.Build.VERSION.SDK_INT >= 26
// 更可靠的方式:尝试创建 Vulkan 实例
} catch (e: Exception) {
false
}
}
生成文本
class LlamaEngine(private val context: Context) {
// ... 上面的 loadModel 和 unload
suspend fun generate(
prompt: String,
maxTokens: Int = 256,
temperature: Float = 0.7f,
onToken: (String) -> Unit = {}
): String = withContext(Dispatchers.Default) {
val result = StringBuilder()
LlamaNative.generate(
context = ctx,
prompt = prompt,
maxTokens = maxTokens,
temperature = temperature,
) { token ->
result.append(token)
// 分派到主线程更新 UI
withContext(Dispatchers.Main) {
onToken(token)
}
}
result.toString()
}
}
ViewModel 集成
class AiViewModel(application: Application) : AndroidViewModel(application) {
private val engine = LlamaEngine(application)
private val _response = MutableStateFlow("")
val response: StateFlow<String> = _response
private val _isGenerating = MutableStateFlow(false)
val isGenerating: StateFlow<Boolean> = _isGenerating
fun loadModel(path: String) {
viewModelScope.launch {
engine.loadModel(path)
}
}
fun generate(prompt: String) {
viewModelScope.launch {
_isGenerating.value = true
_response.value = ""
engine.generate(prompt, maxTokens = 256) { token ->
_response.value += token
}
_isGenerating.value = false
}
}
override fun onCleared() {
engine.unload()
super.onCleared()
}
}
Jetpack Compose UI
@Composable
fun AiChatScreen(viewModel: AiViewModel = viewModel()) {
val response by viewModel.response.collectAsState()
val isGenerating by viewModel.isGenerating.collectAsState()
var input by remember { mutableStateOf("") }
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
// 回复区域
Text(
text = response,
modifier = Modifier.weight(1f).verticalScroll(rememberScrollState())
)
// 输入区域
Row(modifier = Modifier.fillMaxWidth()) {
TextField(
value = input,
onValueChange = { input = it },
modifier = Modifier.weight(1f),
enabled = !isGenerating
)
Button(
onClick = {
viewModel.generate(input)
input = ""
},
enabled = !isGenerating
) {
Text("Send")
}
}
}
}
内存管理
Android 的内存管理非常激进。系统会杀死后台进程以释放 RAM,并在内存压力下终止您的应用。
可用内存检查
fun getAvailableMemoryMb(): Long {
val memInfo = ActivityManager.MemoryInfo()
val activityManager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
activityManager.getMemoryInfo(memInfo)
return memInfo.availMem / (1024 * 1024)
}
fun canLoadModel(modelSizeMb: Long): Boolean {
val available = getAvailableMemoryMb()
// 为应用和系统预留 500MB
return available > modelSizeMb + 500
}
生命周期管理
class AiService : LifecycleObserver {
private var engine: LlamaEngine? = null
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun onResume() {
// 如果 AI 界面处于活动状态,考虑加载模型
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun onPause() {
// 卸载模型以释放内存
engine?.unload()
}
}
onTrimMemory 处理
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW) {
engine?.unload()
}
}
模型分发
Asset Delivery(Play Feature Delivery)
对于超过 150MB 的模型,使用 Play Asset Delivery 以避免 APK 大小限制:
// build.gradle.kts
assetPacks += ":model_pack"
// model_pack/build.gradle.kts
plugins {
id("com.android.asset-pack")
}
assetPack {
packName.set("model_pack")
dynamicDelivery {
deliveryType.set("install-time") // 或 "fast-follow" 或 "on-demand"
}
}
安装后下载
安装后下载模型:
suspend fun downloadModel(url: String, destination: File): Boolean {
return withContext(Dispatchers.IO) {
val client = OkHttpClient()
val request = Request.Builder().url(url).build()
val response = client.newCall(request).execute()
response.body?.let { body ->
val totalBytes = body.contentLength()
destination.outputStream().use { output ->
body.byteStream().use { input ->
val buffer = ByteArray(8192)
var bytesRead: Long = 0
var read: Int
while (input.read(buffer).also { read = it } != -1) {
output.write(buffer, 0, read)
bytesRead += read
val progress = bytesRead.toFloat() / totalBytes
// 更新进度 UI
}
}
}
true
} ?: false
}
}
对于可以在应用重启后继续的后台下载,使用 WorkManager。
跨设备测试
Android 设备种类繁多。需要在以下设备上测试:
- 旗舰机(SD 8 Gen 3, 12GB):验证最佳性能
- 中端机(SD 7 Gen 3, 6-8GB):验证 1B 模型流畅运行
- 入门机(SD 6 Gen 3, 4GB):验证模型无法加载时的优雅降级
- 旧款旗舰(SD 8 Gen 1, 8GB):验证两年前的旗舰机能正常工作
使用 Firebase Test Lab 或 BrowserStack 进行设备覆盖测试,无需拥有每台设备。
生产清单
- 模型在最低配置设备上正确加载并生成
- 检测到 Vulkan 时使用 Vulkan 加速
- Vulkan 不可用时 CPU 回退正常工作
- 内存检查防止在低 RAM 设备上加载
- 在 onPause/onTrimMemory 时卸载模型
- 安装后下载的进度正确显示
- 下载后验证模型完整性(SHA256)
- 用户可以取消生成
- 模型不可用时应用正常运行
GGUF 模型决定了输出质量。在您的领域数据上微调的模型(通过 Ertas 等平台)会生成针对您应用目的的特定回复。无论使用哪个模型,llama.cpp 的集成方式都是一样的。
Ship AI that runs on your users' devices.
Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.
Keep reading

AI in Android Apps: ML Kit, Cloud APIs, and On-Device LLMs Compared
Three paths to AI in your Android app. Google ML Kit for common tasks, cloud APIs for full LLM capability, and on-device models via llama.cpp for cost and privacy. A practical comparison for Kotlin developers.

LLM Benchmarks on Android: Snapdragon, Tensor, and Exynos Compared
Real benchmark data for running LLMs on Android via llama.cpp. Token speeds across Snapdragon 8 Gen 2/3, Tensor G3/G4, Exynos 2400, and mid-range chipsets with practical deployment guidance.

llama.cpp on iOS: A Swift Integration Guide
Step-by-step guide to integrating llama.cpp into an iOS app. Project setup, Metal GPU acceleration, model loading, token streaming, and memory management for production deployment.