Google Drive REST API:java.lang.IllegalArgumentException:名称不能为空:null

时间:2018-09-22 11:19:19

标签: android rest google-drive-api google-drive-android-api

我正在开发一个使用Google Drive REST API的android应用程序。我只想列出驱动器中的所有文件。但是,当调用方法listDriveFiles()时,我得到的错误为java.lang.IllegalArgumentException: the name must not be empty: null

我在这里发现了类似的问题,其中大多数人说要添加权限GET_ACCOUNT。我已经做到了,但是没有运气。一个答案指向检查getAccount()的值,当我这样做时,我得到的值为null

错误:

java.lang.IllegalArgumentException: the name must not be empty: null
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2358)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2410)
        at android.app.ActivityThread.access$800(ActivityThread.java:155)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1331)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:5388)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:655)
        at dalvik.system.NativeStart.main(Native Method)
     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:267)
        at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:292)
        at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:868)
        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 com.datacubeinfo.drive2.MainActivity.listDriveFiles(MainActivity.java:68)
        at com.datacubeinfo.drive2.MainActivity.onDriveClientReady(MainActivity.java:88)
        at com.datacubeinfo.drive2.BaseGoogleDriveActivity.initializeDriveClient(BaseGoogleDriveActivity.java:149)
        at com.datacubeinfo.drive2.BaseGoogleDriveActivity.signIn(BaseGoogleDriveActivity.java:82)
        at com.datacubeinfo.drive2.BaseGoogleDriveActivity.onStart(BaseGoogleDriveActivity.java:43)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1174)
        at android.app.Activity.performStart(Activity.java:5290)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2410) 
        at android.app.ActivityThread.access$800(ActivityThread.java:155) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1331) 
        at android.os.Handler.dispatchMessage(Handler.java:110) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:5388) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:655) 
        at dalvik.system.NativeStart.main(Native Method)

MainActivity.java

public class MainActivity extends BaseGoogleDriveActivity {
    private static final String APPLICATION_NAME = "Google Drive API";
    /**
     * Global instance of the HTTP transport.
     */
    private static HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport();
    /**
     * Global instance of the JSON factory.
     */
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    private Drive mDrive;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.login).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                signIn();
            }
        });

        findViewById(R.id.listFile).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
                    @Override
                    protected Void doInBackground(Void... voids) {
                        try {
                            listDriveFiles();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
                };
                task.execute();
            }
        });
    }


    public void listDriveFiles() throws IOException {
        // Print the names and IDs for up to 10 files.
        FileList result = mDrive.files().list()
                .setPageSize(10)
                .setFields("nextPageToken, files(id, name)")
                .execute();
        List<File> files = result.getFiles();
        if (files == null || files.isEmpty()) {
            System.out.println("No files found.");
        } else {
            System.out.println("Files:");
            for (File file : files) {
                System.out.printf("%s (%s)\n", file.getName(), file.getId());
            }
        }
    }

    @Override
    protected void onDriveClientReady(String displayName, String email, Uri avatar) {
        // Build a new authorized API client service.
        mDrive = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredential())
                .setApplicationName(APPLICATION_NAME)
                .build();
        try {
            listDriveFiles();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BaseGoogleDriveActivity.java

public abstract class BaseGoogleDriveActivity extends AppCompatActivity {
    private static final String TAG = "BaseDriveActivity";
    public static final Scope SCOPE_FILE = new Scope("https://www.googleapis.com/auth/drive.file");
    public static final Scope SCOPE_APPFOLDER = new Scope("https://www.googleapis.com/auth/drive.appdata");
    /**
     * Request code for Google Sign-in
     */
    protected static final int REQUEST_CODE_SIGN_IN = 1;

    private String mToken;
    private GoogleAccountCredential mCredential;

    @Override
    protected void onStart() {
        super.onStart();
        signIn();
    }

    /**
     * Handles resolution callbacks.
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_SIGN_IN) {

            if (resultCode != RESULT_OK) {
                // Sign-in may fail or be cancelled by the user. For this sample, sign-in is
                // required and is fatal. For apps where sign-in is optional, handle
                // appropriately
                Log.e(TAG, "Sign-in failed.");
                return;
            }

            Task<GoogleSignInAccount> getAccountTask =
                    GoogleSignIn.getSignedInAccountFromIntent(data);
            if (getAccountTask.isSuccessful()) {
                initializeDriveClient(getAccountTask.getResult());
            } else {
                Log.e(TAG, "Sign-in failed.");
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    /**
     * Starts the sign-in process and initializes the Drive client.
     */
    protected void signIn() {
        Set<Scope> requiredScopes = new HashSet<>(2);
        requiredScopes.add(SCOPE_FILE);
        requiredScopes.add(SCOPE_APPFOLDER);
        GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(this);
        if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
            initializeDriveClient(signInAccount);
        } else {
            GoogleSignInOptions signInOptions =
                    new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                            .requestScopes(SCOPE_FILE)
                            .requestScopes(SCOPE_APPFOLDER)
                            .build();
            GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, signInOptions);
            startActivityForResult(googleSignInClient.getSignInIntent(), REQUEST_CODE_SIGN_IN);
        }
    }

    protected boolean checkSignedIn(boolean initClient) {
        Set<Scope> requiredScopes = new HashSet<>(2);
        requiredScopes.add(SCOPE_FILE);
        requiredScopes.add(SCOPE_APPFOLDER);
        GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(this);
        if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
            if (initClient) {
                initializeDriveClient(signInAccount);
            }
            return true;
        } else {
            return false;
        }
    }

    protected void signOut() {
        GoogleSignInOptions signInOptions =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .requestScopes(SCOPE_FILE)
                        .requestScopes(SCOPE_APPFOLDER)
                        .build();
        GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, signInOptions);
        googleSignInClient.signOut();
    }

    /**
     * Continues the sign-in process, initializing the Drive clients with the current
     * user's account.
     */
    private void initializeDriveClient(final GoogleSignInAccount signInAccount) {
        mCredential = GoogleAccountCredential.usingOAuth2(this, Collections.singleton(SCOPE_FILE.getScopeUri()));
        mCredential.setSelectedAccount(signInAccount.getAccount());
        Log.e(TAG, ""+signInAccount.getAccount());
        onDriveClientReady(signInAccount.getDisplayName(), signInAccount.getEmail(), signInAccount.getPhotoUrl());
    }

    public GoogleAccountCredential getCredential() {
        return mCredential;
    }

    protected String getToken() {
        return mToken;
    }

    /**
     * Called after the user has signed in and the Drive client has been initialized.
     */
    protected abstract void onDriveClientReady(final String displayName, final String email, final Uri avatar);
}

2 个答案:

答案 0 :(得分:2)

经过一番研究,我发现了所缺少的。正如我在问题中提到的,getAccount()始终返回null值。因此,我检查了GoogleSignInAccount类的文档。 您可以here对其进行检查。 在那里

  

getAccount()是getEmail()的便捷包装,该包装返回一个   android.accounts.Account对象

如果未配置getEmail(),则requestEmail()返回null。如果getEmail()null,则为getAccount()。因此,我对代码进行了如下更改。

GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                                   .requestScopes(SCOPE_FILE)
                                   .requestScopes(SCOPE_APPFOLDER)
                                   .requestEmail()
                                   .build();

现在可以正常使用了。

答案 1 :(得分:0)

就我而言(Google Drive REST API v3),ProGuard是罪魁祸首,因为代码在调试模式下运行良好。

只需在ProGuard规则中添加-keep class com.google.** { *;}即可解决问题。