Android Kotlin 快速开始
- AI 快速开始
- 完整开发指引
准备工作
在开始之前,请确保您已完成以下准备:
- 开通云开发环境:开通云开发环境
- 获取 API 访问凭证:在 CloudBase 控制台 获取环境 ID 和 API 密钥
Client
配置你的 AI 工具以连接 CloudBase 能力 支持本地与托管两种连接方式,详见 连接方式。
步骤 1:安装 / 配置 CloudBase
步骤 2:和 AI 对话
在 AI 对话中依次输入以下内容:
prompt
安装 CloudBase Skills:命令 npx skills add tencentcloudbase/cloudbase-skills -y使用 CloudBase Skills: 使用 CloudBase Skills:在 Android Kotlin 应用中集成 CloudBase HTTP API准备工作
在开始之前,请确保您已完成以下准备:
- 开通云开发环境:开通云开发环境
- 获取 API 访问凭证:在 CloudBase 控制台 获取环境 ID 和 API 密钥
更多详情请参考:Android Kotlin 完整文档
身份认证
- 短信验证码注册
- 邮箱验证码注册
- 账号密码登录
- 短信验证码登录
- 邮箱验证码登录
suspend fun signUpWithPhoneCode(cloudbase: CloudBaseClient, phoneNumber: String, verificationCode: String, username: String? = null, password: String? = null, captchaToken: String? = null): Map<String, Any>? {
// 步骤1: 发送短信验证码
val sendBody = mutableMapOf<String, Any>(
"phone_number" to if (phoneNumber.startsWith("+86")) phoneNumber else "+86$phoneNumber",
"target" to "NON_USER" // "NON_USER" - 账号不存在才发送; "ANY" - 不限制
)
val sendHeaders = captchaToken?.let { mapOf("x-captcha-token" to it) } ?: emptyMap()
val sendResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification",
body = sendBody,
customHeaders = sendHeaders,
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (sendResult == null) {
println("发送验证码失败")
return null
}
val verificationId = sendResult["verification_id"] as? String ?: return null
println("验证码发送成功! ID: $verificationId")
// 步骤2: 验证验证码
val verifyResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification/verify",
body = mapOf(
"verification_id" to verificationId,
"verification_code" to verificationCode
),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (verifyResult == null) {
println("验证码错误")
return null
}
val verificationToken = verifyResult["verification_token"] as? String ?: return null
println("验证成功!")
// 步骤3: 使用验证令牌注册
val signUpBody = mutableMapOf<String, Any>(
"phone_number" to if (phoneNumber.startsWith("+86")) phoneNumber else "+86$phoneNumber",
"verification_token" to verificationToken
)
// 可选:添加用户名和密码
username?.let { signUpBody["username"] = it }
password?.let { signUpBody["password"] = it }
val signUpResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/signup",
body = signUpBody,
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (signUpResult != null) {
val accessToken = signUpResult["access_token"] as? String
val userId = signUpResult["sub"] as? String
println("注册成功! 用户ID: $userId")
println("访问令牌: ${accessToken?.take(20)}...")
// 更新访问令牌
accessToken?.let { cloudbase.updateAccessToken(it) }
return signUpResult
}
println("注册失败")
return null
}
// 使用示例
// lifecycleScope.launch {
// val result = signUpWithPhoneCode(cloudbase, "13800138000", "123456", "myusername", "mypassword")
// if (result != null) {
// println("手机号注册成功")
// }
// }
suspend fun signUpWithEmailCode(cloudbase: CloudBaseClient, email: String, verificationCode: String, username: String? = null, password: String? = null, captchaToken: String? = null): Map<String, Any>? {
// 步骤1: 发送邮箱验证码
val sendBody = mutableMapOf<String, Any>(
"email" to email,
"target" to "NON_USER" // "NON_USER" - 账号不存在才发送; "ANY" - 不限制
)
val sendHeaders = captchaToken?.let { mapOf("x-captcha-token" to it) } ?: emptyMap()
val sendResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification",
body = sendBody,
customHeaders = sendHeaders,
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (sendResult == null) {
println("发送验证码失败")
return null
}
val verificationId = sendResult["verification_id"] as? String ?: return null
println("验证码发送成功! ID: $verificationId")
// 步骤2: 验证验证码
val verifyResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification/verify",
body = mapOf(
"verification_id" to verificationId,
"verification_code" to verificationCode
),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (verifyResult == null) {
println("验证码错误")
return null
}
val verificationToken = verifyResult["verification_token"] as? String ?: return null
println("验证成功!")
// 步骤3: 使用验证令牌注册
val signUpBody = mutableMapOf<String, Any>(
"email" to email,
"verification_token" to verificationToken
)
// 可选:添加用户名和密码
username?.let { signUpBody["username"] = it }
password?.let { signUpBody["password"] = it }
val signUpResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/signup",
body = signUpBody,
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (signUpResult != null) {
val accessToken = signUpResult["access_token"] as? String
val userId = signUpResult["sub"] as? String
println("注册成功! 用户ID: $userId")
println("访问令牌: ${accessToken?.take(20)}...")
// 更新访问令牌
accessToken?.let { cloudbase.updateAccessToken(it) }
return signUpResult
}
println("注册失败")
return null
}
// 使用示例
// lifecycleScope.launch {
// val result = signUpWithEmailCode(cloudbase, "user@example.com", "123456", "myusername", "mypassword")
// if (result != null) {
// println("邮箱注册成功")
// }
// }
suspend fun signIn(cloudbase: CloudBaseClient, username: String, password: String): Map<String, Any>? {
// 账号密码登录
val result = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/signin",
body = mapOf("username" to username, "password" to password),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (result != null) {
val accessToken = result["access_token"] as? String
val refreshToken = result["refresh_token"] as? String
val userId = result["sub"] as? String
println("登录成功! 用户ID: $userId")
println("访问令牌: ${accessToken?.take(20)}...")
// 更新访问令牌
accessToken?.let { cloudbase.updateAccessToken(it) }
return result
}
return null
}
// 使用示例
// lifecycleScope.launch {
// val result = signIn(cloudbase, "your_username", "your_password")
// println(result)
// }
suspend fun loginWithPhoneCode(cloudbase: CloudBaseClient, phoneNumber: String, verificationCode: String, captchaToken: String? = null): Boolean {
// 步骤1: 发送短信验证码
val sendBody = mutableMapOf<String, Any>(
"phone_number" to if (phoneNumber.startsWith("+86")) phoneNumber else "+86$phoneNumber",
"target" to "ANY" // "ANY" - 不限制,无论用户是否存在都发送; "USER" - 账号必须存在才发送
)
val sendHeaders = captchaToken?.let { mapOf("x-captcha-token" to it) } ?: emptyMap()
val sendResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification",
body = sendBody,
customHeaders = sendHeaders,
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (sendResult == null) {
println("发送验证码失败")
return false
}
val verificationId = sendResult["verification_id"] as? String ?: return false
println("验证码发送成功! ID: $verificationId")
// 步骤2: 验证验证码
val verifyResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification/verify",
body = mapOf(
"verification_id" to verificationId,
"verification_code" to verificationCode
),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (verifyResult == null) {
println("验证码错误")
return false
}
val verificationToken = verifyResult["verification_token"] as? String ?: return false
println("验证成功!")
// 步骤3: 使用验证令牌登录
val loginResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/signin",
body = mapOf(
"phone_number" to if (phoneNumber.startsWith("+86")) phoneNumber else "+86$phoneNumber",
"verification_token" to verificationToken
),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (loginResult != null) {
val accessToken = loginResult["access_token"] as? String
println("登录成功!")
accessToken?.let { cloudbase.updateAccessToken(it) }
return true
}
println("登录失败")
return false
}
// 使用示例
// lifecycleScope.launch {
// val success = loginWithPhoneCode(cloudbase, "13800138000", "123456")
// if (success) {
// println("手机号登录成功")
// }
// }
suspend fun loginWithEmailCode(cloudbase: CloudBaseClient, email: String, verificationCode: String, captchaToken: String? = null): Boolean {
// 步骤1: 发送邮箱验证码
val sendBody = mutableMapOf<String, Any>(
"email" to email,
"target" to "ANY" // "ANY" - 不限制,无论用户是否存在都发送; "USER" - 账号必须存在才发送
)
val sendHeaders = captchaToken?.let { mapOf("x-captcha-token" to it) } ?: emptyMap()
val sendResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification",
body = sendBody,
customHeaders = sendHeaders,
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (sendResult == null) {
println("发送验证码失败")
return false
}
val verificationId = sendResult["verification_id"] as? String ?: return false
println("验证码发送成功! ID: $verificationId")
// 步骤2: 验证验证码
val verifyResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/verification/verify",
body = mapOf(
"verification_id" to verificationId,
"verification_code" to verificationCode
),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (verifyResult == null) {
println("验证码错误")
return false
}
val verificationToken = verifyResult["verification_token"] as? String ?: return false
println("验证成功!")
// 步骤3: 使用验证令牌登录
val loginResult = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/auth/v1/signin",
body = mapOf(
"email" to email,
"verification_token" to verificationToken
),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (loginResult != null) {
val accessToken = loginResult["access_token"] as? String
println("登录成功!")
accessToken?.let { cloudbase.updateAccessToken(it) }
return true
}
println("登录失败")
return false
}
// 使用示例
// lifecycleScope.launch {
// val success = loginWithEmailCode(cloudbase, "user@example.com", "123456")
// if (success) {
// println("邮箱登录成功")
// }
// }
云存储
- 上传文件
- 获取文件链接
- 下载文件
- 删除文件
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
suspend fun uploadFile(cloudbase: CloudBaseClient, filePath: String, objectId: String? = null): Map<String, String>? = withContext(Dispatchers.IO) {
// 上传文件到云存储
val file = File(filePath)
if (!file.exists()) {
println("文件不存在: $filePath")
return@withContext null
}
val finalObjectId = objectId ?: "uploads/${System.currentTimeMillis()}-${file.name}"
// 1. 获取上传信息
val uploadInfo = cloudbase.request<List<Map<String, Any>>>(
method = "POST",
path = "/v1/storages/get-objects-upload-info",
body = listOf(mapOf("objectId" to finalObjectId)),
typeToken = object : TypeToken<List<Map<String, Any>>>() {}
)
if (uploadInfo.isNullOrEmpty()) {
return@withContext null
}
val info = uploadInfo[0]
val uploadUrl = info["uploadUrl"] as String
try {
// 2. 上传文件
val fileData = file.readBytes()
val uploadHeaders = mapOf(
"Authorization" to (info["authorization"] as String),
"X-Cos-Security-Token" to (info["token"] as String),
"X-Cos-Meta-Fileid" to (info["cloudObjectMeta"] as String)
)
val requestBuilder = Request.Builder()
.url(uploadUrl)
.put(fileData.toRequestBody())
uploadHeaders.forEach { (key, value) ->
requestBuilder.header(key, value)
}
val client = OkHttpClient()
val uploadResponse = client.newCall(requestBuilder.build()).execute()
if (uploadResponse.isSuccessful) {
val result = mapOf(
"cloudObjectId" to (info["cloudObjectId"] as String),
"downloadUrl" to (info["downloadUrl"] as String),
"objectId" to finalObjectId
)
println("文件上传成功:")
println("- 对象ID: ${result["objectId"]}")
println("- 下载URL: ${result["downloadUrl"]}")
return@withContext result
}
println("文件上传失败: ${uploadResponse.code}")
return@withContext null
} catch (e: Exception) {
println("文件上传失败: ${e.message}")
e.printStackTrace()
return@withContext null
}
}
// 使用示例
// lifecycleScope.launch {
// val result = uploadFile(cloudbase, "/path/to/example.jpg")
// println(result)
// }
suspend fun getFileUrl(cloudbase: CloudBaseClient, cloudObjectId: String): String? {
// 获取云存储文件的临时访问链接
val result = cloudbase.request<List<Map<String, Any>>>(
method = "POST",
path = "/v1/storages/get-objects-download-info",
body = listOf(mapOf("cloudObjectId" to cloudObjectId)),
typeToken = object : TypeToken<List<Map<String, Any>>>() {}
)
if (!result.isNullOrEmpty()) {
val downloadUrl = result[0]["downloadUrl"] as? String
println("文件链接: $downloadUrl")
return downloadUrl
}
return null
}
// 使用示例
// lifecycleScope.launch {
// val fileUrl = getFileUrl(cloudbase, "cloud://xxx.png")
// println(fileUrl)
// }
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
suspend fun downloadFile(cloudbase: CloudBaseClient, cloudObjectId: String, savePath: String = "./"): Boolean = withContext(Dispatchers.IO) {
// 下载云存储文件到本地
// 1. 获取下载链接
val result = cloudbase.request<List<Map<String, Any>>>(
method = "POST",
path = "/v1/storages/get-objects-download-info",
body = listOf(mapOf("cloudObjectId" to cloudObjectId)),
typeToken = object : TypeToken<List<Map<String, Any>>>() {}
)
if (result.isNullOrEmpty()) {
return@withContext false
}
val downloadUrl = result[0]["downloadUrl"] as String
try {
// 2. 从URL中提取文件名
val filename = downloadUrl.split("/").last().split("?").first()
// 3. 确定完整路径
val fullPath = if (File(savePath).isDirectory || savePath.endsWith("/")) {
"$savePath/$filename"
} else {
savePath
}
// 4. 下载文件
val client = OkHttpClient()
val request = Request.Builder().url(downloadUrl).build()
val fileResponse = client.newCall(request).execute()
if (fileResponse.isSuccessful) {
// 5. 保存到本地
val file = File(fullPath)
file.parentFile?.mkdirs()
file.writeBytes(fileResponse.body!!.bytes())
println("下载成功! 文件已保存到: $fullPath")
return@withContext true
}
println("下载失败: ${fileResponse.code}")
return@withContext false
} catch (e: Exception) {
println("下载失败: ${e.message}")
e.printStackTrace()
return@withContext false
}
}
// 使用示例
// lifecycleScope.launch {
// // 下载到指定目录
// downloadFile(cloudbase, "cloud://xxx.png", "/sdcard/Download/")
//
// // 下载并重命名
// downloadFile(cloudbase, "cloud://xxx.png", "/sdcard/Download/my-image.png")
// }
suspend fun deleteFile(cloudbase: CloudBaseClient, cloudObjectIds: Any): Boolean {
// 删除云存储文件
val ids = when (cloudObjectIds) {
is String -> listOf(cloudObjectIds)
is List<*> -> cloudObjectIds.filterIsInstance<String>()
else -> {
println("参数类型错误")
return false
}
}
val data = ids.map { mapOf("cloudObjectId" to it) }
val result = cloudbase.request<Any>(
method = "POST",
path = "/v1/storages/delete-objects",
body = data
)
if (result != null) {
println("删除成功!")
return true
}
return false
}
// 使用示例
// lifecycleScope.launch {
// val result = deleteFile(cloudbase, "cloud://xxx.png")
// println(result)
// }
云函数
suspend fun callFunction(cloudbase: CloudBaseClient, functionName: String, data: Map<String, Any>? = null): Map<String, Any>? {
// 调用云函数
val result = cloudbase.request<Map<String, Any>>(
method = "POST",
path = "/v1/functions/$functionName",
body = data ?: emptyMap<String, Any>(),
typeToken = object : TypeToken<Map<String, Any>>() {}
)
if (result != null) {
println("云函数调用结果: $result")
}
return result
}
// 使用示例
// lifecycleScope.launch {
// val result = callFunction(cloudbase, "{%FUNCTION_NAME%}")
// println(result)
// }
大模型
- 生文模型
- 生图模型
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.MediaType.Companion.toMediaType
import com.google.gson.Gson
suspend fun streamText(cloudbase: CloudBaseClient, model: String, subModel: String, messages: List<Map<String, String>>): String? = withContext(Dispatchers.IO) {
// 流式文本 生成
val payload = mapOf(
"model" to subModel,
"messages" to messages,
"stream" to true
)
val url = "${cloudbase.baseUrl}/v1/ai/$model/chat/completions"
val gson = Gson()
val requestBody = gson.toJson(payload).toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url(url)
.header("Content-Type", "application/json")
.header("Accept", "text/event-stream")
.header("Authorization", "Bearer ${cloudbase.accessToken}")
.post(requestBody)
.build()
try {
val client = OkHttpClient()
val response = client.newCall(request).execute()
if (response.isSuccessful) {
println("AI 流式响应:")
var fullContent = ""
response.body?.source()?.use { source ->
while (!source.exhausted()) {
val line = source.readUtf8Line() ?: continue
if (line.startsWith("data: ")) {
val dataStr = line.substring(6)
if (dataStr.trim() != "[DONE]") {
try {
val chunkData = gson.fromJson(dataStr, Map::class.java)
val choices = chunkData["choices"] as? List<*>
val delta = (choices?.get(0) as? Map<*, *>)?.get("delta") as? Map<*, *>
val content = delta?.get("content") as? String ?: ""
if (content.isNotEmpty()) {
print(content)
fullContent += content
}
} catch (e: Exception) {
// 忽略JSON解析错误
}
}
}
}
}
println()
return@withContext fullContent
} else {
println("AI 调用失败: ${response.code}")
return@withContext null
}
} catch (e: Exception) {
println("AI 调用失败: ${e.message}")
e.printStackTrace()
return@withContext null
}
}
// 使用示例
// lifecycleScope.launch {
// val response = streamText(
// cloudbase,
// "{%AI_MODEL_NAME%}",
// "{%AI_SUB_MODEL_NAME%}",
// listOf(
// mapOf("role" to "system", "content" to "请严格按照七言绝句或七言律诗的格律要求创作"),
// mapOf("role" to "user", "content" to "春天")
// )
// )
// println("\n完整回复: $response")
// }
生图模型通过调用云函数来实现,在生图模型 页面点击「一键创建云函数」,函数调用示例如下:
import com.google.gson.Gson
suspend fun generateImage(cloudbase: CloudBaseClient, prompt: String): Map<String, Any>? = withContext(Dispatchers.IO) {
/// 调用生图云函数
val result = cloudbase.request(
"POST",
"/v1/functions/<YOUR_FUNCTION_NAME>/invoke",
mapOf("prompt" to prompt)
)
if (result != null) {
val success = result["success"] as? Boolean ?: false
if (success) {
// 生成成功
println("生成成功!")
println("图片URL: ${result["imageUrl"]}")
println("优化后的提示词: ${result["revised_prompt"]}")
// 使用图片
// 注意:图片URL有效期为24小时,请及时保存或转存
return@withContext result
} else {
// 生成失败
println("生成失败: ${result["code"]} ${result["message"]}")
return@withContext null
}
}
return@withContext null
}
// 使用示例
// lifecycleScope.launch {
// val result = generateImage(cloudbase, "一只可爱的猫咪在阳光下玩耍")
// if (result != null) {
// println("图片URL: ${result["imageUrl"]}")
// }
// }