应用程序默认凭据不可用 [英] The Application Default Credentials are not available

查看:116
本文介绍了应用程序默认凭据不可用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为我的Android应用程序使用Google Cloud Platform的语音转文本API.我已经通过了一个录制的音频文件以转换为文本.我无法解决被描述为""的IOException.应用程序默认凭据不可用.如果在Google Compute Engine中运行,它们将可用.否则,必须定义环境变量GOOGLE_APPLICATION_CREDENTIALS指向定义凭据的文件.请参见 https://developers.google.com/accounts/docs/application-default-凭证以获取更多信息."

I am trying to use speech-to-text API of Google Cloud Platform for my Android App. I have passed it a recorded audio file for conversion to text. I can't solve an IOException which is described as "The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information."

我创建了一个服务帐户,启用了特定的API,创建了一个帐户密钥(cred.json).将环境变量"GOOGLE_APPLICATION_CREDENTIALS"设置为文件的[path](上面的cred.json).这是在Mac上的.bash_profile文件中完成的.

I've created a service account, enabled the particular API, created a account key(cred.json). Set the environment variable "GOOGLE_APPLICATION_CREDENTIALS" to the [path] of the file(cred.json from above). This was done in .bash_profile file on mac.

这是问题所在:当我检查环境.使用

Here is the problem: When I check for the env. variable from terminal using

回显$ GOOGLE_APPLICATION_CREDENTIALS

结果是cred.json文件的[路径]

the result is [path] of the cred.json file

但是,如果我尝试检查"GOOGLE_APPLICATION_CREDENTIALS",则在为应用程序添加调试信息时,它显示为空.我使用

But while deubgging the app if I try to check "GOOGLE_APPLICATION_CREDENTIALS" it shows null. I checked it using

Log.d("@sttenv", System.getenv("GOOGLE_APPLICATION_CREDENTIALS"));

这就是为什么我得到上面提到的IOException的原因.该行引发IOException.

This is the reason why I get the IOException mentioned above. This line throws the IOException.

SpeechClient speechClient = SpeechClient.create();

SpeechClient(它是代码本身的开始)给出了IOException.

The SpeechClient which is the very start of the code itself gives an IOException.

try {

            SpeechClient speechClient = SpeechClient.create();

            // Reads the audio file into memory
            Path path = Paths.get(tempFileName);
            byte[] data = Files.readAllBytes(path);
            ByteString audioBytes = ByteString.copyFrom(data);

            // Builds the sync recognize request
            RecognitionConfig config = RecognitionConfig.newBuilder()
                    .setEncoding(AudioEncoding.LINEAR16)
                    .setSampleRateHertz(44100)
                    .setLanguageCode("en-US")
                    .build();
            RecognitionAudio audio = RecognitionAudio.newBuilder()
                    .setContent(audioBytes)
                    .build();

            // Performs speech recognition on the audio file
            RecognizeResponse response = speechClient.recognize(config, audio);
            List<SpeechRecognitionResult> results = response.getResultsList();

            for (SpeechRecognitionResult result : results) {
                // There can be several alternative transcripts for a given chunk of speech. Just use the
                // first (most likely) one here.
                SpeechRecognitionAlternative alternative = result.getAlternativesList().get(0);
                //System.out.printf("Transcription: %s%n", alternative.getTranscript());
                log.debug("Transcription: %s%n", alternative.getTranscript());
            }

}
catch (IOException e){
    e.printStackTrace();
}

我该如何解决?我尝试设置环境.来自终端的变量,无用.我也想知道,如果我们将此应用程序安装在Android手机中(而不是在模拟器上),是否需要cred.json文件出现在手机本身中?因为cred.josn(帐户密钥)在我的Mac上.我正在尝试通过Android手机访问API?因此,我应该将cred.json保存在手机上,并提供给env的路径.变量?

How should I tackle this? I tried setting the env. variable from the terminal, no use. Also I wanted to know, if we install this app in a android phone(not on emulator), does it require the cred.json file to be present in the phone itself? Because the cred.josn (account key) is on my mac. And I'm trying to access the API through a Android phone? So should I save the cred.json on my phone and give it's path to the env. variable?

推荐答案

GOOGLE_APPLICATION_CREDENTIALS是一个编译时变量.您会注意到build.gradle中存在一个任务,该任务会将凭证从变量指向的位置复制到原始目录中的credential.json文件:

GOOGLE_APPLICATION_CREDENTIALS is a compile time variable. you can notice there is task in the build.gradle that copies the credentials from where ever the variable points to to the credential.json file in the raw directory:

task copySecretKey(type: Copy) {
def File secretKey = file "$System.env.GOOGLE_APPLICATION_CREDENTIALS"
from secretKey.getParent()
include secretKey.getName()
into 'src/main/res/raw'
rename secretKey.getName(), "credential.json"
}

然后应使用代码对这个文件进行寻址,以产生用于API服务的访问令牌:

this file should then be addressed in code to produce an access token for the API services:

private class AccessTokenTask extends AsyncTask<Void, Void, AccessToken> {

    @Override
    protected AccessToken doInBackground(Void... voids) {
        final SharedPreferences prefs =
                getSharedPreferences(PREFS, Context.MODE_PRIVATE);
        String tokenValue = prefs.getString(PREF_ACCESS_TOKEN_VALUE, null);
        long expirationTime = prefs.getLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME, -1);

        // Check if the current token is still valid for a while
        if (tokenValue != null && expirationTime > 0) {
            if (expirationTime
                    > System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION_TOLERANCE) {
                return new AccessToken(tokenValue, new Date(expirationTime));
            }
        }

        // ***** WARNING *****
        // In this sample, we load the credential from a JSON file stored in a raw resource
        // folder of this client app. You should never do this in your app. Instead, store
        // the file in your server and obtain an access token from there.
        // *******************
        final InputStream stream = getResources().openRawResource(R.raw.credential);
        try {
            final GoogleCredentials credentials = GoogleCredentials.fromStream(stream)
                    .createScoped(SCOPE);
            final AccessToken token = credentials.refreshAccessToken();
            prefs.edit()
                    .putString(PREF_ACCESS_TOKEN_VALUE, token.getTokenValue())
                    .putLong(PREF_ACCESS_TOKEN_EXPIRATION_TIME,
                            token.getExpirationTime().getTime())
                    .apply();
            return token;
        } catch (IOException e) {
            Log.e(TAG, "Failed to obtain access token.", e);
        }
        return null;
    }

    @Override
    protected void onPostExecute(AccessToken accessToken) {
        mAccessTokenTask = null;
        final ManagedChannel channel = new OkHttpChannelProvider()
                .builderForAddress(HOSTNAME, PORT)
                .nameResolverFactory(new DnsNameResolverProvider())
                .intercept(new GoogleCredentialsInterceptor(new GoogleCredentials(accessToken)
                        .createScoped(SCOPE)))
                .build();
        mApi = SpeechGrpc.newStub(channel);

        // Schedule access token refresh before it expires
        if (mHandler != null) {
            mHandler.postDelayed(mFetchAccessTokenRunnable,
                    Math.max(accessToken.getExpirationTime().getTime()
                            - System.currentTimeMillis()
                            - ACCESS_TOKEN_FETCH_MARGIN, ACCESS_TOKEN_EXPIRATION_TOLERANCE));
        }
    }
}

这篇关于应用程序默认凭据不可用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆