如何将 GOOGLE_APPLICATION_CREDENTIALS 指向我的 JSON 文件?

Rez*_*eza 1 java android google-api

我想在我的 Android 应用程序中使用Google 文本转语音

根据文档,我已经完成了所有这些步骤:

  1. 在 Cloud Console 中,转到创建服务帐号密钥页面。
  2. 从服务帐户列表中,选择新服务帐户。
  3. 在服务帐户名称字段中,输入名称。
  4. 从角色列表中,选择项目 > 所有者。
  5. 单击“创建”。包含您的密钥的 JSON 文件将下载到您的计算机。

我正在使用Google 的代码来传递凭据,这是我下载的 JSON 文件:

public void main(String... args) throws Exception {
    // You can specify a credential file by providing a path to GoogleCredentials.
    // Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment variable.
    InputStream stream = getResources().openRawResource(R.raw.credential); // R.raw.credential is credential.json
    GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(String.valueOf(stream)))
            .createScoped(Lists.newArrayList(Collections.singleton("https://www.googleapis.com/auth/cloud-platform")));
    Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();

    System.out.println("Buckets:");
    Page<Bucket> buckets = storage.list();
    for (Bucket bucket : buckets.iterateAll()) {
        System.out.println(bucket.toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

无论如何,我已经清理了 Gradle,重新启动了 Android Studio,但我仍然收到此日志:

java.io.IOException:应用程序默认凭据不可用。如果在 Google Compute Engine 中运行,则它们可用。否则,必须定义环境变量 GOOGLE_APPLICATION_CREDENTIALS 指向定义凭据的文件。 有关详细信息,请参阅 https://developers.google.com/accounts/docs/application-default-credentials 。

我究竟做错了什么?

更新

我意识到只有当我单击按钮时我才会收到此日志消息。如果我单击一个按钮,该方法hello()就会运行。查看完整代码:

package ch.yourclick.kitt;

import android.os.Build;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout;
import com.google.api.client.util.Lists;
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.api.gax.paging.Page;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.texttospeech.v1.AudioConfig;
import com.google.cloud.texttospeech.v1.AudioEncoding;
import com.google.cloud.texttospeech.v1.SsmlVoiceGender;
import com.google.cloud.texttospeech.v1.SynthesisInput;
import com.google.cloud.texttospeech.v1.SynthesizeSpeechResponse;
import com.google.cloud.texttospeech.v1.TextToSpeechClient;
import com.google.cloud.texttospeech.v1.TextToSpeechSettings;
import com.google.cloud.texttospeech.v1.VoiceSelectionParams;
import com.google.protobuf.ByteString;
import androidx.annotation.RequiresApi;
import androidx.viewpager.widget.ViewPager;
import androidx.appcompat.app.AppCompatActivity;
import android.os.StrictMode;
import android.view.View;

import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;

import ch.yourclick.kitt.ui.main.SectionsPagerAdapter;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager());
        ViewPager viewPager = findViewById(R.id.view_pager);
        viewPager.setAdapter(sectionsPagerAdapter);
        TabLayout tabs = findViewById(R.id.tabs);
        tabs.setupWithViewPager(viewPager);
        FloatingActionButton fab = findViewById(R.id.fab);

        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    public void main(String... args) throws Exception {
        // You can specify a credential file by providing a path to GoogleCredentials.
        // Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment variable.
        InputStream stream = getResources().openRawResource(R.raw.credential); // R.raw.credential is credential.json
        GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
                .createScoped(Lists.newArrayList(Collections.singleton("https://www.googleapis.com/auth/cloud-platform")));
        Storage storage = StorageOptions.newBuilder().setCredentials(credentials).build().getService();

        System.out.println("Buckets:");
        Page<Bucket> buckets = storage.list();
        for (Bucket bucket : buckets.iterateAll()) {
            System.out.println(bucket.toString());
        }
    }



    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void onClick(View view) {
        int SDK_INT = android.os.Build.VERSION.SDK_INT;
        if (SDK_INT > 8)
        {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                    .permitAll().build();
            StrictMode.setThreadPolicy(policy);

            try {
                hello();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /** Demonstrates using the Text-to-Speech API. */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    public void hello() throws Exception {
        InputStream stream = getResources().openRawResource(R.raw.credential); // R.raw.credential is credential.json
        GoogleCredentials credentials = GoogleCredentials.fromStream(stream);
        TextToSpeechSettings textToSpeechSettings =
                TextToSpeechSettings.newBuilder()
                        .setCredentialsProvider(
                                FixedCredentialsProvider.create(credentials)
                        ).build()
                ;


        // Instantiates a client
        try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create(textToSpeechSettings)) {
            // Set the text input to be synthesized
            SynthesisInput input = SynthesisInput.newBuilder().setText("Hello, World!").build();

            // Build the voice request, select the language code ("en-US") and the ssml voice gender
            // ("neutral")
            VoiceSelectionParams voice =
                    VoiceSelectionParams.newBuilder()
                            .setLanguageCode("en-US")
                            .setSsmlGender(SsmlVoiceGender.NEUTRAL)
                            .build();

            // Select the type of audio file you want returned
            AudioConfig audioConfig =
                    AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();

            // Perform the text-to-speech request on the text input with the selected voice parameters and
            // audio file type
            SynthesizeSpeechResponse response =
                    textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);

            // Get the audio contents from the response
            ByteString audioContents = response.getAudioContent();

            // Write the response to the output file.
            try (OutputStream out = new FileOutputStream("output.mp3")) {
                out.write(audioContents.toByteArray());
                System.out.println("Audio content written to file \"output.mp3\"");
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

依赖关系

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation group: 'io.grpc', name: 'grpc-okhttp', version: '1.0.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'com.google.cloud:google-cloud-storage:1.113.3'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.google.cloud:libraries-bom:4.3.0'
    implementation 'com.google.cloud:google-cloud-texttospeech:1.2.1'
    implementation 'com.google.android.gms:play-services:12.0.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
Run Code Online (Sandbox Code Playgroud)

jcc*_*ero 5

GoogleCredentials由于提供给该类的方式的原因,该类可能无法找到有效的凭证 JSON 文件。

请代替:

InputStream stream = getResources().openRawResource(R.raw.credential); // R.raw.credential is credential.json
GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(String.valueOf(stream)))
            .createScoped(Lists.newArrayList(Collections.singleton("https://www.googleapis.com/auth/cloud-platform")));
Run Code Online (Sandbox Code Playgroud)

尝试:

InputStream stream = getResources().openRawResource(R.raw.credential); // R.raw.credential is credential.json
GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
            .createScoped(Lists.newArrayList(Collections.singleton("https://www.googleapis.com/auth/cloud-platform")));
Run Code Online (Sandbox Code Playgroud)

getResources().openRawResource将为您提供stream所需的内容,您可以使用它stream来创建GoogleCredentials

GoogleCredentials.fromStream(stream)
Run Code Online (Sandbox Code Playgroud)

关于您的更新,您似乎是在TextToSpeechClient没有提供任何显式凭据的情况下创建的,因此图书馆正在环境中寻找它们。

TechToSpeechClient正如您在javadocs中看到的,您可以向客户端提供您的凭据。

而不是这个:

TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()
Run Code Online (Sandbox Code Playgroud)

使用与此类似的内容初始化您的客户端(请根据您认为适当的情况进行修改):

import com.google.api.gax.core.FixedCredentialsProvider;

// In your method...

InputStream stream = getResources().openRawResource(R.raw.credential); // R.raw.credential is credential.json
GoogleCredentials credentials = GoogleCredentials.fromStream(stream);
TextToSpeechSettings textToSpeechSettings =
  TextToSpeechSettings.newBuilder()
    .setCredentialsProvider(
      FixedCredentialsProvider.create(credentials)
    ).build()
;

TextToSpeechClient textToSpeechClient =
  TextToSpeechClient.create(textToSpeechSettings);

// The rest of your code
Run Code Online (Sandbox Code Playgroud)

请确保您的服务帐户凭据为您提供了访问所请求的 API 的正确授权。

事实上,正如我在您的问题中意识到的那样,如果您将项目所有者角色授予服务帐户,您就已经拥有这些权限。无论如何,请小心,项目所有者角色使您可以完全控制项目中的每个资源:对于服务帐户,始终建议采取更多限制。理想情况下,应仅授予它执行为其创建的操作所需的权限。