2024年进入尾声,作为一名聋人独立开发者,我常常回顾和反思过去半年的成长和收获。最近,我在Gemma2竞赛独立开发项目中再创佳绩,荣获亚军,然后我要专注工作。我会抽时间编写有价值的技术文章,感谢大家的理解与支持!
Gemini API 是 Google 提供的一款强大的 AI 解决方案,它为移动应用开发者提供了丰富的 AI 功能,比如自然语言处理、图片识别等。用Gemini API,可以轻松把智能化功能集成到你的Android应用中。特别是对那些想要快速嵌入AI功能的开发者来说,这个API提供了很大的便利。
为什么要使用Gemini API?
因为随着移动设备的普及,越来越多的应用需要利用云端的AI服务来减轻本地设备的压力。通过Gemini API,应用可以在云端执行复杂的AI任务,比如处理大规模的图像识别,自然语言生成,确保本地应用的性能不会受到影响。
在这篇文章中,我们会带你一步步地从零开始,用Android Studio新建一个基于Gemini API的项目。作为聋人独立开发者,你不需要太多繁杂的配置,通过提供的模板就能轻松上手。
要开始一个新的Gemini项目,首先,你需要打开Android Studio,选择“新建项目”选项。在弹出的界面中,找到“Gemini API Starter”模板,这个模板是Google专门为集成Gemini API准备的(参见图示)。
点击"Next",你需要填写以下项目信息:
com.nim.nimgeminidemo
。接下来,你会被要求输入一个API Key。这个API Key是为了访问Gemini API服务必须的。点击页面上的"Generate API key with Google AI Studio",进入Google AI Studio获取API Key并填入框中。确保API Key准确无误,最后点击“Finish”完成项目创建。
Keys官方链接:https://aistudio.google.com/app/apikey?hl=zh-cn
创建完项目后,Android Studio会生成一个完整的项目结构,其中包括:
Gemini API所需的依赖已经通过模板自动添加,无需手动引入。这样,你的项目已经具备了AI调用的能力。
为了让你的应用成功连接到Gemini API服务,还需要在AndroidManifest.xml
中添加一些权限。特别是与网络相关的权限,包括:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
这两项权限允许应用访问网络服务,并能与Google的AI服务器通信。
API Key 是项目中至关重要的一部分。在项目配置文件 gradle.properties
中,你可以将API Key保存为环境变量,这样不仅可以提高安全性,还能避免在代码中直接暴露Key:
API_KEY="你的API密钥"
在代码中,通过读取环境变量的方式获取API Key,这样既便捷又安全。
通过使用 Gemini API Starter 模板,所有的依赖都已经配置好,只需关注核心代码的实现。
(1).我详细介绍Demo中的核心代码部分,以下代码展示了如何通过 Gemini API 发送图片和提示信息,生成AI输出内容:
package com.nim.nimgeminidemo
class BakingViewModel : ViewModel() {
private val _uiState: MutableStateFlow<UiState> =
MutableStateFlow(UiState.Initial)
val uiState: StateFlow<UiState> =
_uiState.asStateFlow()
private val generativeModel = GenerativeModel(
modelName = "gemini-pro-vision",
apiKey = BuildConfig.apiKey
)
fun sendPrompt(
bitmap: Bitmap,
prompt: String
) {
_uiState.value = UiState.Loading
viewModelScope.launch(Dispatchers.IO) {
try {
val response = generativeModel.generateContent(
content {
image(bitmap)
text(prompt)
}
)
response.text?.let { outputContent ->
_uiState.value = UiState.Success(outputContent)
}
} catch (e: Exception) {
_uiState.value = UiState.Error(e.localizedMessage ?: "")
}
}
}
}
ViewModel
通过 sendPrompt
函数,图片和提示信息发送至 Gemini API 并获取AI生成的文本结果。在界面上,会根据返回的状态更新UI,展示生成的文本或错误信息。
package com.nim.nimgeminidemo
/**
* A sealed hierarchy describing the state of the text generation.
*/
sealed interface UiState {
/**
* Empty state when the screen is first shown
*/
object Initial : UiState
/**
* Still loading
*/
object Loading : UiState
/**
* Text has been generated
*/
data class Success(val outputText: String) : UiState
/**
* There was an error generating text
*/
data class Error(val errorMessage: String) : UiState
}
简单来说,这段代码通过不同的状态来控制界面上的显示内容,比如显示加载中、展示结果、或者报错提示,用起来也很灵活。
package com.nim.nimgeminidemo
val images = arrayOf(
R.drawable.baked_goods_1,
R.drawable.baked_goods_2,
R.drawable.baked_goods_3,
)
val imageDescriptions = arrayOf(
R.string.image1_description,
R.string.image2_description,
R.string.image3_description,
)
@Composable
fun BakingScreen(
bakingViewModel: BakingViewModel = viewModel()
) {
val selectedImage = remember { mutableIntStateOf(0) }
val placeholderPrompt = stringResource(R.string.prompt_placeholder)
val placeholderResult = stringResource(R.string.results_placeholder)
var prompt by rememberSaveable { mutableStateOf(placeholderPrompt) }
var result by rememberSaveable { mutableStateOf(placeholderResult) }
val uiState by bakingViewModel.uiState.collectAsState()
val context = LocalContext.current
Column(
modifier = Modifier.fillMaxSize()
) {
Text(
text = stringResource(R.string.baking_title),
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(16.dp)
)
LazyRow(
modifier = Modifier.fillMaxWidth()
) {
itemsIndexed(images) { index, image ->
var imageModifier = Modifier
.padding(start = 8.dp, end = 8.dp)
.requiredSize(200.dp)
.clickable {
selectedImage.intValue = index
}
if (index == selectedImage.intValue) {
imageModifier =
imageModifier.border(BorderStroke(4.dp, MaterialTheme.colorScheme.primary))
}
Image(
painter = painterResource(image),
contentDescription = stringResource(imageDescriptions[index]),
modifier = imageModifier
)
}
}
Row(
modifier = Modifier.padding(all = 16.dp)
) {
TextField(
value = prompt,
label = { Text(stringResource(R.string.label_prompt)) },
onValueChange = { prompt = it },
modifier = Modifier
.weight(0.8f)
.padding(end = 16.dp)
.align(Alignment.CenterVertically)
)
Button(
onClick = {
val bitmap = BitmapFactory.decodeResource(
context.resources,
images[selectedImage.intValue]
)
bakingViewModel.sendPrompt(bitmap, prompt)
},
enabled = prompt.isNotEmpty(),
modifier = Modifier
.align(Alignment.CenterVertically)
) {
Text(text = stringResource(R.string.action_go))
}
}
if (uiState is UiState.Loading) {
CircularProgressIndicator(modifier = Modifier.align(Alignment.CenterHorizontally))
} else {
var textColor = MaterialTheme.colorScheme.onSurface
if (uiState is UiState.Error) {
textColor = MaterialTheme.colorScheme.error
result = (uiState as UiState.Error).errorMessage
} else if (uiState is UiState.Success) {
textColor = MaterialTheme.colorScheme.onSurface
result = (uiState as UiState.Success).outputText
}
val scrollState = rememberScrollState()
Text(
text = result,
textAlign = TextAlign.Start,
color = textColor,
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(16.dp)
.fillMaxSize()
.verticalScroll(scrollState)
)
}
}
}
@Preview(showSystemUi = true)
@Composable
fun BakingScreenPreview() {
BakingScreen()
}
(4)解释代码:
images
和 imageDescriptions
: 定义了一个图片数组和对应的图片描述,用于在界面上显示可供用户选择的图片。BakingScreen
组件: 这是主界面的显示逻辑,用户在这里可以选择图片并输入文本提示,调用ViewModel生成文本结果。
selectedImage
: 记录用户选择的图片索引。prompt
和 result
: 分别用于保存用户输入的提示文字和生成的结果。uiState
: 保存界面的当前状态,比如正在加载、显示成功结果、或者发生错误。LazyRow
显示可横向滑动的图片列表,用户点击图片会更新选中的图片,图片会显示带边框的选中状态。bakingViewModel
调用AI生成文本。uiState
的值,界面会显示加载进度、成功生成的文本或者错误信息。
GenerativeModel
是API的核心类在这个类中,构造函数接受多个参数:
modelName
:指定使用哪个AI模型,例如 gemini-pro-vision
。apiKey
:用于认证的API密钥,保证客户端与Google的AI服务能够进行安全的通信。generationConfig
:生成配置参数,控制生成内容的特性,例如输出文本的长度或生成图像的分辨率。safetySettings
:安全设置,用于控制生成内容时的安全性和过滤规则,防止不合适的内容生成。requestOptions
:控制与后端通信时的其他配置,比如超时时间或请求头信息。
解释代码
val harassmentSetting = SafetySetting(
category = SafetyCategory.HARASSMENT,
setting = SafetyLevel.ONLY_HIGH
)
val harmfulSetting = SafetySetting(
category = SafetyCategory.HARMFUL_CONTENT,
setting = SafetyLevel.ONLY_HIGH
)
val hateSetting = SafetySetting(
category = SafetyCategory.HATE_SPEECH,
setting = SafetyLevel.ONLY_HIGH
)
val violenceSetting = SafetySetting(
category = SafetyCategory.VIOLENCE,
setting = SafetyLevel.ONLY_HIGH
)
HARASSMENT
):防止生成与骚扰相关的内容。HARMFUL_CONTENT
):防止生成有可能伤害他人或自我伤害的内容。HATE_SPEECH
):防止生成与仇恨言论相关的内容。VIOLENCE
):防止生成与暴力行为相关的内容。ONLY_HIGH
设置:ONLY_HIGH
表示只阻止那些被认为高度危害的内容。较轻微的内容可能不会被阻止,适合那些希望保持一定灵活性但仍避免重大违规内容的场景。使用Gemini API 时,你可能会遇到几个技术上的挑战。首先是 API Key 的管理。API Key硬编码在代码中是非常不安全的,容易被恶意用户获取并滥用。建议通过环境变量的方式管理API Key,或者使用更高级的密钥管理系统来保护它。
通过这次实践,我们成功构建了一个具备AI功能的Android应用,并了解了如何快速使用Android Studio结合Gemini API进行开发。从项目搭建到API配置,每一步都有详细的操作介绍。希望这篇文章能帮助你快速上手Gemini API,并在自己的项目中集成AI功能。即使是初学者也可以通过本教程,了解在安卓开发中的AI集成基础。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。