Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Drive REST API: java.lang.IllegalArgumentException: the name must not be empty: null

I'm developing an android application that makes use of Google Drive REST API. I just want to list all files in my drive. But when the method listDriveFiles() is called I get an error as java.lang.IllegalArgumentException: the name must not be empty: null.

I found similar problems asked here and most of them says to add the permission GET_ACCOUNT. I already did that but no luck. One answer points to check the value of getAccount() and when I did that I get the value as null.

Error:

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);
}
like image 990
Nipun Avatar asked Sep 22 '18 11:09

Nipun


2 Answers

After some research I found what was missing. As I mentioned in the question the getAccount() always returned null value. So I checked the documentation of GoogleSignInAccount class. You can check it here. There it states that

getAccount() is a convenient wrapper for getEmail() which returns an android.accounts.Account object

The getEmail() returns null if requestEmail() is not configured. If getEmail() is null, then is getAccount(). So I made changes in my code as below.

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

Now it works perfect.

like image 72
Nipun Avatar answered Nov 14 '22 21:11

Nipun


In my case (Google Drive REST API v3), ProGuard was the culprit, as the code was working fine in debug mode.

Just adding -keep class com.google.** { *;} to ProGuard rules got rid of the issue.

like image 42
Mangesh Avatar answered Nov 14 '22 23:11

Mangesh