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);
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With