Google Drive API-имя не должно быть пустым: null (но я передал действительное имя учетной записи GoogleAccountCredential)

недавно у меня есть код Android, который обращается к Google Drive. Я использую клиентская библиотека Google APIs для Java вместо клиентская библиотека Google Play services

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();

код работает 100% отлично в течение нескольких лет, если я использую targetSdkVersion 21.

недавно я переношу свое приложение на targetSdkVersion 23, С 0 изменений на Google Drive код, связанный.

тем не менее, код разбивает тайну на FileList fileList = request.execute();, со следующими исключение.

журнал ошибок при использовании 1.18.0-rc

Process: org.yccheok.jstock.gui, PID: 30317
java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask.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.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.call(AsyncTask.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor.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) 

если я google, я получаю Google Drive на Android ошибка: java.ленг.IllegalArgumentException: имя не должно быть пустым: null, в котором указано, что имя учетной записи не передается объекту учетных данных.

однако я почти уверен, что мой объект учетных данных передается с допустимым именем учетной записи (в формате xxx@gmail.com)

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

кроме того, я уверен, что мой OAuth 2.0 правильно через консоль разработчиков Google (как для отладочного хранилища ключей, так и для производственного хранилища ключей) В последнее время Android 6 вводит разрешения на время выполнения. Мне было интересно, может ли это исключение связано с этим?

Я далее пытаюсь с последней версией библиотеки 1.21.0. Тем не менее, я все еще получаю подобный журнал ошибок

журнал ошибки при использовании 1.21.0

java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask.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.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.call(AsyncTask.java:295)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor.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) 

обновление моего дальнейшего тестирования

вышеуказанные журналы ошибок 2 генерируются во время тестирования с помощью Nexus 5, Android версии 6.0.1

однако, если я провожу то же самое тестирование с помощью Nexus 4, Android версии 5.1.1, никакой ошибки не происходит! И 1.18.0-rc и 1.21.0 работают нормально

следовательно, кажется, что авария сильно связана с версией Android.

3 ответов


похоже, что клиентская библиотека API диска для Java вызывает GoogleAuthUtil.getToken(), для чего требуется GET_ACCOUNTS разрешения. Вам нужно иметь это разрешение в манифесте и запрашивать его во время выполнения, если это необходимо.


Это потому, что от Android 6.0 (API level 23) перед вызовом конечных точек google необходимо получить разрешение "контакты".

вы можете увидеть полную информацию здесь -https://developer.android.com/training/permissions/requesting.html

Это верно только для опасных разрешений и групп разрешений (в зависимости от того, насколько они связаны с конфиденциальностью пользователя). Новые подробности - https://developer.android.com/guide/topics/security/permissions.html#perm-groups


у меня была та же проблема, все разрешения были предоставлены, и все же я получил эту ошибку.

моя простая проблема заключалась в том, что googleSignInAccount.getSignInAccount().getAccount() был null. Это имеет место, если вы не запрашиваете разрешения электронной почты (GoogleSignInOptions.Builder.requestEmail). Похоже, эта учетная запись не может быть создана без электронной почты пользователя.

поэтому обязательно добавьте это разрешение в GoogleSignInOptions...