Android 应用程序默认凭据不可用
我正在尝试为我的Android应用程序使用谷歌云平台的语音到文本API。我已经给了它一个录音文件,以便转换成文本。 我无法解决IOException,该异常被描述为“应用程序默认凭据不可用。如果在Google Compute Engine中运行,则这些凭据可用。否则,必须定义指向定义凭据的文件的环境变量Google\u Application\u Credentials。有关详细信息,请参阅。” 我创建了一个服务帐户,启用了特定的API,创建了一个帐户密钥(cred.json)。 将环境变量“GOOGLE\u APPLICATION\u CREDENTIALS”设置为文件的[path](上面的cred.json)。这是在mac上的.bash_配置文件中完成的 问题是: 当我检查环境时。从终端使用的变量 echo$GOOGLE\u应用程序\u凭证 结果是cred.json文件的[path] 但是,当我尝试检查“谷歌应用程序凭据”时,它显示为空。我用电脑检查了一下Android 应用程序默认凭据不可用,android,google-cloud-platform,speech-to-text,Android,Google Cloud Platform,Speech To Text,我正在尝试为我的Android应用程序使用谷歌云平台的语音到文本API。我已经给了它一个录音文件,以便转换成文本。 我无法解决IOException,该异常被描述为“应用程序默认凭据不可用。如果在Google Compute Engine中运行,则这些凭据可用。否则,必须定义指向定义凭据的文件的环境变量Google\u Application\u Credentials。有关详细信息,请参阅。” 我创建了一个服务帐户,启用了特定的API,创建了一个帐户密钥(cred.json)。 将环境变量“G
Log.d("@sttenv", System.getenv("GOOGLE_APPLICATION_CREDENTIALS"));
这就是我得到上面提到的IOException的原因。此行抛出IOException
SpeechClient speechClient = SpeechClient.create();
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();
}
SpeechClient是代码本身的开始,它给出了一个IOException
SpeechClient speechClient = SpeechClient.create();
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();
}
试试看{
SpeechClient SpeechClient=SpeechClient.create();
//将音频文件读入内存
Path Path=Path.get(tempFileName);
字节[]数据=文件。readAllBytes(路径);
ByteString audioBytes=ByteString.copyFrom(数据);
//生成同步识别请求
RecognitionConfig=RecognitionConfig.newBuilder()
.setEncoding(AudioEncoding.LINEAR16)
.setSampleRateHertz(44100)
.setLanguageCode(“en-US”)
.build();
RecognitionAudio=RecognitionAudio.newBuilder()
.setContent(音频字节)
.build();
//对音频文件执行语音识别
RecognizeResponse response=speechClient.recognize(配置,音频);
列表结果=response.getResultsList();
for(SpeechRecognitionResult:results){
//对于给定的一段演讲,可以有多个备选文本。只需使用
//第一个(很可能)在这里。
speechrecognitionalAlternative=result.getAlternativesList().get(0);
//System.out.printf(“转录:%s%n”,alternative.getTranscript());
log.debug(“转录:%s%n”,alternative.getTranscript());
}
}
捕获(IOE异常){
e、 printStackTrace();
}
我应该如何处理这个问题?我试着设置环境。从终端变量,没有用。
我还想知道,如果我们在android手机上安装这个应用程序(不是在模拟器上),它是否需要cred.json文件出现在手机本身中?因为cred.josn(帐户密钥)在我的mac上。我想通过安卓手机访问API?因此,我应该将cred.json保存在手机上,并给出它到env的路径。变量?谷歌应用程序凭据是一个编译时变量。 您可以注意到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));
}
}
}
私有类AccessTokenTask扩展了AsyncTask{
@凌驾
受保护的AccessToken doInBackground(无效…无效){
最终共享首选项=
GetSharedReferences(优先、上下文、模式\u私有);
String-tokenValue=prefs.getString(PREF\u-ACCESS\u-TOKEN\u-VALUE,null);
long expirationTime=prefs.getLong(PREF\u ACCESS\u TOKEN\u expirationTime,-1);
//检查当前令牌是否在一段时间内仍然有效
if(tokenValue!=null&&expirationTime>0){
如果(过期时间)
>System.currentTimeMillis()+访问\令牌\过期\容差){
返回新的AccessToken(tokenValue、新日期(expirationTime));
}
}
//******警告*****
//在本示例中,我们从存储在原始资源中的JSON文件加载凭据
//此客户端应用的文件夹。您不应在应用中执行此操作。请改为存储
//将该文件保存在服务器中,并从中获取访问令牌。
// *******************
final InputStream stream=getResources().openRawResource(R.raw.credential);
试一试{
final GoogleCredentials credentials=GoogleCredentials.fromStream(流)
.createScope(范围);
最终AccessToken令牌=凭据。refreshAccessToken();
prefs.edit()
.putString(PREF_ACCESS_TOKEN_VALUE,TOKEN.getTokenValue())
.putLong(预访问令牌到期时间),
token.getExpirationTime().getTime())
.apply();
返回令牌;
}捕获(IOE异常){
Log.e(标记“未能获取访问令牌”,e);
}
返回null;
}
@凌驾
受保护的void onPostExecute(AccessToken AccessToken){
mAccessTokenTask=null;
最终ManagedChannel通道=新的OkHttpChannelProvider()
.builderForAddress(主机名、端口)
.nameResolverFactory(新的DnsNameResolverProvider())
.intercept(新的Google凭据Interceptor)(新的Google凭据(accessToken)
.createScope(范围)))
.build();
mApi=SpeechGrpc.newStub(频道);
//在访问令牌过期之前安排刷新
if(mHandler!=null){
mHandler.postDelayed(mFetchAccessTokenRunnable,
数学