Android应用调用Google Cloud Text-to-Speech API的认证方案咨询
在Android/Kotlin中解决Google Cloud Text-to-Speech API的认证问题
推荐方案:使用官方客户端库自动处理认证
官方客户端库会自动完成令牌的获取、刷新和管理,无需手动处理动态令牌的问题,步骤如下:
- 添加依赖
在Module级的build.gradle中加入以下依赖:
dependencies { // Text-to-Speech API客户端库 implementation 'com.google.api-client:google-api-client-android:1.34.1' implementation 'com.google.apis:google-api-services-texttospeech:v1-rev20230908-2.0.0' // Google Sign-In依赖,用于获取用户凭证 implementation 'com.google.android.gms:play-services-auth:20.7.0' }
- 配置OAuth客户端ID
- 登录Google Cloud Console,找到你的项目,进入「API和服务」→「凭据」。
- 创建「OAuth 2.0客户端ID」,选择「Android」类型,填入应用的包名和SHA-1指纹,完成后获取客户端ID。
- 集成Google Sign-In获取用户账号
先让用户通过Google账号登录,获取GoogleSignInAccount实例,作为后续认证的基础:
import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignInOptions import com.google.android.gms.common.api.Scope // 初始化Google Sign-In配置 val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestScopes(Scope("https://www.googleapis.com/auth/cloud-platform")) .requestIdToken("你的OAuth客户端ID") .build() val googleSignInClient = GoogleSignIn.getClient(this, gso) // 启动登录界面 startActivityForResult(googleSignInClient.signInIntent, RC_SIGN_IN) // 在onActivityResult中获取登录结果 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == RC_SIGN_IN) { val task = GoogleSignIn.getSignedInAccountFromIntent(data) val account = task.getResult(ApiException::class.java) // 拿到account后调用Text-to-Speech API synthesizeText(account) } }
- 调用Text-to-Speech API
用获取到的用户账号初始化API客户端,发起请求:
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential import com.google.api.services.texttospeech.v1.TextToSpeech import com.google.api.services.texttospeech.v1.model.* import com.google.api.client.extensions.android.http.AndroidHttp import com.google.api.client.json.gson.GsonFactory private fun synthesizeText(account: GoogleSignInAccount) { // 初始化凭证 val credential = GoogleAccountCredential.usingOAuth2( this, listOf("https://www.googleapis.com/auth/cloud-platform") ).setSelectedAccount(account.account) // 创建API客户端 val textToSpeechService = TextToSpeech.Builder( AndroidHttp.newCompatibleTransport(), GsonFactory.getDefaultInstance(), credential ).setApplicationName("你的应用名称").build() // 构造请求参数 val input = SynthesisInput().setText("需要转换的文本") val voice = VoiceSelectionParams() .setLanguageCode("zh-CN") .setSsmlGender("FEMALE") val audioConfig = AudioConfig().setAudioEncoding("MP3") val request = SynthesizeSpeechRequest() .setInput(input) .setVoice(voice) .setAudioConfig(audioConfig) // 异步发起请求(避免阻塞主线程) Thread { try { val response = textToSpeechService.text().synthesize(request).execute() val audioContent = response.audioContent // 处理返回的音频二进制数据,比如保存为文件或直接播放 } catch (e: Exception) { e.printStackTrace() // 处理请求错误 } }.start() }
备选方案:手动获取并使用访问令牌
如果不想依赖客户端库,可以手动获取令牌并构造POST请求:
- 获取访问令牌
利用GoogleAuthUtil获取令牌,它会自动处理令牌的刷新:
import com.google.android.gms.auth.GoogleAuthUtil import com.google.android.gms.auth.UserRecoverableAuthException private fun getAccessToken(account: Account): String? { return try { GoogleAuthUtil.getToken( this, account, "oauth2:https://www.googleapis.com/auth/cloud-platform" ) } catch (e: UserRecoverableAuthException) { // 需要用户授权,启动对应的Intent startActivity(e.intent) null } catch (e: Exception) { e.printStackTrace() null } }
- 构造POST请求
拿到令牌后,像curl那样添加到请求头中:
import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody private fun sendTextToSpeechRequest(token: String) { val client = OkHttpClient() val jsonBody = """ { "input": {"text": "需要转换的文本"}, "voice": {"languageCode": "zh-CN", "ssmlGender": "FEMALE"}, "audioConfig": {"audioEncoding": "MP3"} } """.trimIndent() val request = Request.Builder() .url("https://texttospeech.googleapis.com/v1/text:synthesize") .addHeader("Authorization", "Bearer $token") .addHeader("Content-Type", "application/json; charset=utf-8") .addHeader("x-goog-user-project", "text2speech") // 替换为你的项目ID .post(jsonBody.toRequestBody("application/json".toMediaType())) .build() // 异步执行请求 client.newCall(request).enqueue(object : okhttp3.Callback { override fun onFailure(call: okhttp3.Call, e: IOException) { e.printStackTrace() } override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) { val responseBody = response.body?.string() // 解析返回的JSON,提取音频base64数据 } }) }
关键注意事项
- 禁止在应用中嵌入Service Account密钥:这会导致密钥泄露,引发安全风险,必须通过用户账号的OAuth授权来获取凭证。
- 启用API权限:确保你的Google Cloud项目已经启用了Text-to-Speech API,并且用户账号拥有该API的访问权限。
- 异步处理请求:所有网络请求必须放在子线程中执行,避免阻塞Android主线程。
内容的提问来源于stack exchange,提问作者nikste
相关产品推荐
相关产品推荐

