Учетные данные приложения по умолчанию недоступны - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь использовать текстовый API Google Cloud Platform для моего приложения для Android. Я передал ему записанный аудиофайл для преобразования в текст. Я не могу решить IOException, которое описывается как " Учетные данные приложения по умолчанию недоступны. Они доступны, если работают в Google Compute Engine. В противном случае должна быть определена переменная среды GOOGLE_APPLICATION_CREDENTIALS, указывающая на файл, определяющий учетные данные. См. https://developers.google.com/accounts/docs/application-default-credentials для получения дополнительной информации."

Я создал учетную запись службы, включил определенный API, создал ключ учетной записи (cred.json). Установите переменную окружения «GOOGLE_APPLICATION_CREDENTIALS» в [путь] файла (cred.json сверху). Это было сделано в файле .bash_profile на Mac.

Вот проблема: Когда я проверяю для env. переменная из терминала с использованием

echo $ GOOGLE_APPLICATION_CREDENTIALS

результат - [путь] файла cred.json

Но при отладке приложения, если я пытаюсь проверить "GOOGLE_APPLICATION_CREDENTIALS", оно показывает нулевое значение. Я проверил это с помощью

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

Это причина, по которой я получаю IOException, упомянутый выше. Эта строка выдает IOException.

SpeechClient speechClient = SpeechClient.create();

SpeechClient, который является началом самого кода, дает 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();
}

Как мне с этим справиться? Я попытался установить env. переменная из терминала, бесполезно. Также я хотел знать, если мы устанавливаем это приложение на телефон Android (не на эмуляторе), требуется ли для него файл cred.json, присутствующий в самом телефоне? Потому что cred.josn (ключ учетной записи) находится на моем Mac. И я пытаюсь получить доступ к API через телефон Android? Поэтому я должен сохранить файл cred.json на моем телефоне и указать путь к нему. переменная

1 Ответ

0 голосов
/ 10 апреля 2019

GOOGLE_APPLICATION_CREDENTIALS - переменная времени компиляции.вы можете заметить, что в build.gradle есть задача, которая копирует учетные данные из того места, где переменная указывает на файл credential.json в необработанном каталоге:

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:

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));
        }
    }
}
...