问题描述
最近,我有Android代码访问Google Drive。我正在使用适用于Java的Google API客户端库,而不是 Google Play服务客户端库
$ b
private static GoogleCloudFile searchFromGoogleDrive(Drive drive,String qString,HandleUserRecoverableAuthIOExceptionable h,PublishProgressable p){
try {
Files.List request = drive.files()。list()。setQ QString的);
do {
if(p.isCancelled()){
return null;
}
FileList fileList = request.execute();
如果我使用 targetSdkVersion 21,代码几年内可以100%
。
最近,我将我的应用迁移到 targetSdkVersion 23
Google Drive相关的代码。
然而,代码在 FileList fileList = request.execute();
中崩溃了,有以下例外。
使用1.18.0-rc时的错误日志
进程:org.yccheok.jstock.gui,PID:30317
java.lang.RuntimeException:在android.os.AsyncTask中执行doInBackground()
时发生错误$ 3.done(AsyncTask。 java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
在java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:234)
在java.util.concurrent。 ThreadPoolEx $ java.util.concurrent.ThreadPoolExecutor
$ Worker.run(ThreadPoolExecutor.java:588)$ b $ java.util.run(Thread.java: 818)
导致:java.lang.IllegalArgumentException:名称不能为空:null在android.accounts.Account处为
。< init>(Account.java:48)
at com.google.android.gms.auth.zzd.getToken(未知来源)
,com.google.android.gms.auth.GoogleAuthUtil.getToken(未知来源)
,com.google.api。 client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:255)
,位于com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential $ RequestHandler.intercept (GoogleAccountCredential.java:279)
,位于com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
位于com.google.api.client.googleapis.services.AbstractGoogleClientRequest .executeUnparsed(AbstractGoogleClientRequest.java:4 10)
,位于com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
位于com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute( AbstractGoogleClientRequest.java:460)
at org.yccheok.jstock.gui.Utils.searchFromGoogleDrive(Utils.java:208)
at org.yccheok.jstock.gui.Utils._loadFromGoogleDrive(Utils.java: 277)
at org.yccheok.jstock.gui.Utils.loadFromGoogleDrive(Utils.java:344)
at org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:23)
在org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:9)
at android.os.AsyncTask $ 2.call(AsyncTask.java:295)
在java.util。并发.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor .java:1113)
a t java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:588)$ b $在java.lang.Thread.run(Thread.java:818)
如果我google,我会得到,其中规定帐户名不会传递给凭证对象。
但是,我非常确定我的凭证对象是通过有效的帐户名称传递的(格式为[email protected])
protected void onActivityResult(final int requestCode,final int resultCode,final Intent data){
switch(requestCode){
case RequestCode.REQUEST_ACCOUNT_PICKER_LOAD_FROM_CLOUD :
if(resultCode == RESULT_OK&& data!= null&& data.getExtras()!= null){
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
Log.i(CHEOK,accountName =+ accountName);
if(accountName!= null){
JStockApplication.instance()。getJStockOptions()。setUsername(accountName);
Utils.getGoogleAccountCredential()。setSelectedAccountName(accountName);
Utils.java
public static GoogleAccountCredential getGoogleAccountCredential(){
return googleAccountCredential;
private static final GoogleAccountCredential googleAccountCredential = GoogleAccountCredential.usingOAuth2(JStockApplication.instance(),
Arrays.asList(
DriveScopes.DRIVE_APPDATA,
/ / Legacy。一段时间后将被删除...
DriveScopes.DRIVE
)
);
私人驱动器getDriveService(){
返回新的Drive.Builder(AndroidHttp.newCompatibleTransport(),新的GsonFactory(),Utils.getGoogleAccountCredential())。
}
另外,我很确定我的OAuth 2.0可以正确地通过Google Developers Console (对于调试密钥库和生产密钥库)
最近,Android 6引入了运行时权限。我想知道,这个异常可以与此相关吗?
我进一步尝试使用最新的库版本1.21.0。但是,我仍然得到类似的错误日志
使用1.21.0时的错误日志
java.lang.RuntimeException:在android.os.AsyncTask执行doInBackground()
时发生错误$ 3.done(AsyncTask.java:309)$ java.util.concurrent.FutureTask中的
.finishCompletion(FutureTask.java:354)$ java.util.concurrent.FutureTask.setException处的
(FutureTask.java:223)$ java.util.concurrent.FutureTask.run处的
(FutureTask.java:242 )
at android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java .util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:588)$ b $在java.lang.Thread.run(Thread.java:818)
导致:java.lang.IllegalArgumentException:名称不能为空:null在android.accounts.Account处的
。< init>(Account.java:48)
在com.google.android.gms.auth.zzd.getToken(Unkn自己的源)
在com.google.android.gms.auth.GoogleAuthUtil.getToken(未知源)
在com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential。 getToken(GoogleAccountCredential.java:255)
,位于com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential $ RequestHandler.intercept(GoogleAccountCredential.java:279)
com。 google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
,位于com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
,位于com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at org.yccheok.jstock.gui.Utils.searchFromGoogleDrive(Utils.java:208)
at org.yccheok.jstock.gui.Utils._loadFromGo在org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask。)中, java:23)
at org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:9)
at android.os.AsyncTask $ 2.call(AsyncTask.java:295)
在java.util.concurrent.FutureTask.run(FutureTask.java:237)
在android.os.AsyncTask $ SerialExecutor $ 1.run(AsyncTask.java:234)
在java.util.concurrent .ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)$ b $在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:588)$ b $在java.lang.Thread.run(Thread.java :818)
我的进一步测试更新
因此,它的崩溃似乎与Android版本紧密相关。 b $ b
它看起来像用于Java的Drive API客户端库调用 GoogleAuthUtil.getToken()
,这需要 GET_ACCOUNTS
权限。您需要在清单中拥有该权限并在运行时请求它。
Recently, I have Android code which accesses to Google Drive. I'm using Google APIs Client Library for Java instead of Google Play services client library
private static GoogleCloudFile searchFromGoogleDrive(Drive drive, String qString, HandleUserRecoverableAuthIOExceptionable h, PublishProgressable p) {
try {
Files.List request = drive.files().list().setQ(qString);
do {
if (p.isCancelled()) {
return null;
}
FileList fileList = request.execute();
The code works 100% fine for several years, if I use targetSdkVersion 21
.
Recently, I migrate my app to targetSdkVersion 23
, with 0 change on Google Drive related code.
However, the code crashes mystery at FileList fileList = request.execute();
, with the following exception.
Error log while using 1.18.0-rc
Process: org.yccheok.jstock.gui, PID: 30317
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalArgumentException: the name must not be empty: null
at android.accounts.Account.<init>(Account.java:48)
at com.google.android.gms.auth.zzd.getToken(Unknown Source)
at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:255)
at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:279)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at org.yccheok.jstock.gui.Utils.searchFromGoogleDrive(Utils.java:208)
at org.yccheok.jstock.gui.Utils._loadFromGoogleDrive(Utils.java:277)
at org.yccheok.jstock.gui.Utils.loadFromGoogleDrive(Utils.java:344)
at org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:23)
at org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:9)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
If I google, I get Google Drive on android error: java.lang.IllegalArgumentException: the name must not be empty: null , which states that account name is not passed to credential object.
However, I'm pretty much sure that my credential object is passed with valid account name (in format [email protected])
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case RequestCode.REQUEST_ACCOUNT_PICKER_LOAD_FROM_CLOUD:
if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
Log.i("CHEOK", "accountName = " + accountName);
if (accountName != null) {
JStockApplication.instance().getJStockOptions().setUsername(accountName);
Utils.getGoogleAccountCredential().setSelectedAccountName(accountName);
Utils.java
public static GoogleAccountCredential getGoogleAccountCredential() {
return googleAccountCredential;
}
private static final GoogleAccountCredential googleAccountCredential = GoogleAccountCredential.usingOAuth2(JStockApplication.instance(),
Arrays.asList(
DriveScopes.DRIVE_APPDATA,
// Legacy. Shall be removed after a while...
DriveScopes.DRIVE
)
);
private Drive getDriveService() {
return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), Utils.getGoogleAccountCredential()).build();
}
Also, I'm pretty sure that my OAuth 2.0 correctly through Google Developers Console (For both debug keystore & production keystore)Recently, Android 6 introduces run-time permissions. I was wondering, can this exception related to that?
I further try with latest library version 1.21.0. However, I still get similar error log
Error log while using 1.21.0
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalArgumentException: the name must not be empty: null
at android.accounts.Account.<init>(Account.java:48)
at com.google.android.gms.auth.zzd.getToken(Unknown Source)
at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:255)
at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:279)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at org.yccheok.jstock.gui.Utils.searchFromGoogleDrive(Utils.java:208)
at org.yccheok.jstock.gui.Utils._loadFromGoogleDrive(Utils.java:277)
at org.yccheok.jstock.gui.Utils.loadFromGoogleDrive(Utils.java:344)
at org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:23)
at org.yccheok.jstock.gui.LoadFromCloudTask.doInBackground(LoadFromCloudTask.java:9)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Update on my further testing
The above 2 error logs are generated while I'm testing using Nexus 5, Android version 6.0.1
However, if I conduct the same testing using Nexus 4, Android version 5.1.1, no error occurs! Both 1.18.0-rc and 1.21.0 are working fine
Hence, it seems the crash is strongly related to Android version.
It looks like the Drive API Client Library for Java calls into GoogleAuthUtil.getToken()
, which requires the GET_ACCOUNTS
permission. You need to have that permission in your manifest and request it at runtime, as appropriate.
这篇关于Google Drive API - 名称不能为空:null(但我已将有效的帐户名称传递给GoogleAccountCredential)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!