You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android集成Google文本转语音遇凭据错误,如何配置GOOGLE_APPLICATION_CREDENTIALS?

解决Google Text-to-Speech在Android中凭据错误的问题

首先,咱们来揪出导致你看到Application Default Credentials are not available错误的核心原因,再一步步修复其他潜在问题:

核心问题:缺少TTS API所需的权限作用域

你在hello()方法里加载凭据时,没有为GoogleCredentials添加Text-to-Speech API要求的权限作用域。虽然你加载了JSON密钥,但没有授权它访问TTS服务,系统就会 fallback 到寻找默认凭据,从而抛出这个误导性的错误。

修复代码
在创建GoogleCredentials时添加作用域:

try (InputStream stream = getResources().openRawResource(R.raw.credential)) {
    // 添加TTS服务所需的作用域
    GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
        .createScoped(Collections.singletonList("https://www.googleapis.com/auth/cloud-platform"));
    
    // 后续的TextToSpeechSettings初始化逻辑...
}

也可以用更精准的https://www.googleapis.com/auth/texttospeech作用域,效果是一样的。


其他必须修复的问题

1. 错误的文件写入路径

Android不允许直接写入根目录的output.mp3,你需要使用应用的私有存储目录:

// 获取应用私有文件目录路径
String outputPath = getFilesDir().getAbsolutePath() + "/output.mp3";
try (OutputStream out = new FileOutputStream(outputPath)) {
    out.write(audioContents.toByteArray());
    System.out.println("音频已保存到:" + outputPath);
}

如果需要写入外部存储,还要在AndroidManifest中申请WRITE_EXTERNAL_STORAGE权限(Android 10+需改用MediaStore或MANAGE_EXTERNAL_STORAGE权限)。

2. 依赖版本冲突与优化

你的依赖存在版本不兼容的问题,会导致潜在的运行时错误:

  • 移除老旧的grpc-okhttp:1.0.1google-cloud-texttospeech会通过你已添加的libraries-bom自动引入适配的grpc版本
  • 移除臃肿且过时的com.google.android.gms:play-services:12.0.1,TTS服务不需要这个依赖
  • 利用BOM统一管理依赖版本,简化gradle配置:
dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    
    // 用BOM管理谷歌云依赖版本
    implementation platform('com.google.cloud:libraries-bom:4.3.0')
    implementation 'com.google.cloud:google-cloud-storage'
    implementation 'com.google.cloud:google-cloud-texttospeech'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

3. 资源流的正确关闭

用try-with-resources包裹InputStream,确保资源被正确释放,避免内存泄漏:

try (InputStream stream = getResources().openRawResource(R.raw.credential)) {
    // 加载凭据的逻辑
} catch (IOException e) {
    e.printStackTrace();
}

4. 避免在主线程执行网络操作

虽然你用StrictMode.permitAll()绕过了主线程限制,但这是不推荐的做法,会导致UI卡顿。建议把TTS调用放在异步任务中,比如用Java的AsyncTask

private class TTSAsyncTask extends AsyncTask<Void, Void, String> {
    @Override
    protected String doInBackground(Void... voids) {
        try {
            String outputPath = getFilesDir().getAbsolutePath() + "/output.mp3";
            try (InputStream stream = getResources().openRawResource(R.raw.credential)) {
                GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
                    .createScoped(Collections.singletonList("https://www.googleapis.com/auth/cloud-platform"));
                
                TextToSpeechSettings settings = TextToSpeechSettings.newBuilder()
                    .setCredentialsProvider(FixedCredentialsProvider.create(credentials)).build();
                
                try (TextToSpeechClient client = TextToSpeechClient.create(settings)) {
                    SynthesisInput input = SynthesisInput.newBuilder().setText("Hello, World!").build();
                    VoiceSelectionParams voice = VoiceSelectionParams.newBuilder()
                        .setLanguageCode("en-US")
                        .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                        .build();
                    AudioConfig audioConfig = AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();
                    
                    SynthesizeSpeechResponse response = client.synthesizeSpeech(input, voice, audioConfig);
                    try (OutputStream out = new FileOutputStream(outputPath)) {
                        out.write(response.getAudioContent().toByteArray());
                    }
                }
            }
            return "音频生成成功:" + outputPath;
        } catch (Exception e) {
            e.printStackTrace();
            return "生成失败:" + e.getMessage();
        }
    }

    @Override
    protected void onPostExecute(String result) {
        // 在UI线程更新提示
        Snackbar.make(findViewById(R.id.fab), result, Snackbar.LENGTH_LONG).show();
    }
}

然后在点击事件中调用:

@Override
public void onClick(View view) {
    new TTSAsyncTask().execute();
}

先修复作用域的问题,这是你当前错误的根源,再逐步处理其他优化点,应该就能顺利运行Google Text-to-Speech服务了。

内容的提问来源于stack exchange,提问作者xRay

火山引擎 最新活动