You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用调用Google Cloud Text-to-Speech API的认证方案咨询

在Android/Kotlin中解决Google Cloud Text-to-Speech API的认证问题

推荐方案:使用官方客户端库自动处理认证

官方客户端库会自动完成令牌的获取、刷新和管理,无需手动处理动态令牌的问题,步骤如下:

  1. 添加依赖
    在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'
}
  1. 配置OAuth客户端ID
  • 登录Google Cloud Console,找到你的项目,进入「API和服务」→「凭据」。
  • 创建「OAuth 2.0客户端ID」,选择「Android」类型,填入应用的包名和SHA-1指纹,完成后获取客户端ID。
  1. 集成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)
    }
}
  1. 调用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请求:

  1. 获取访问令牌
    利用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
    }
}
  1. 构造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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:23:17