I got stuck with an "java.lang.IllegalArgumentException: the name must not be empty: null" Exception on Google Drive Android app.
I have been googling several day without getting any clue. This is my code (an easy example) to get a file list on Google Drive: (It was taken from here: Google Drive SDK Exception)
import java.io.IOException;
import java.util.ArrayList;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.AccountPicker;
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.accounts.GoogleAccountManager;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpRequest;
import com.google.api.client.http.json.JsonHttpRequestInitializer;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.DriveRequest;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import com.maiko.xscanpet.R;
import com.maiko.xscanpet.cloud.GDriveHelper;
public class Fool_5 extends Activity {
private static final int CHOOSE_ACCOUNT=0;
private static String accountName;
private static int REQUEST_TOKEN=0;
private Button btn_drive;
private Context ctx = this;
private Activity a = this;
GoogleAccountCredential mCredential= null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set up the GUI layout
setContentView(R.layout.fool_5);
// set the variables to access the GUI controls
btn_drive = (Button) findViewById(R.id.btn_drive);
btn_drive.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
chooseAccount();
}
});
}
public void chooseAccount() {
Intent intent = AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null, null, null, null);
startActivityForResult(intent, CHOOSE_ACCOUNT);
}
// Fetch the access token asynchronously.
void getAndUseAuthTokenInAsyncTask(Account account) {
AsyncTask<Account, String, String> task = new AsyncTask<Account, String, String>() {
ProgressDialog progressDlg;
AsyncTask<Account, String, String> me = this;
@Override
protected void onPreExecute() {
progressDlg = new ProgressDialog(ctx, ProgressDialog.STYLE_SPINNER);
progressDlg.setMax(100);
progressDlg.setTitle("Validating...");
progressDlg.setMessage("Verifying the login data you entered...\n\nThis action will time out after 10 seconds.");
progressDlg.setCancelable(false);
progressDlg.setIndeterminate(false);
progressDlg.setOnCancelListener(new android.content.DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface d) {
progressDlg.dismiss();
me.cancel(true);
}
});
progressDlg.show();
}
@Override
protected String doInBackground(Account... params) {
return getAccessToken(params[0]);
}
@Override
protected void onPostExecute(String s) {
if (s == null) {
// Wait for the extra intent
} else {
accountName = s;
getDriveFiles();
}
progressDlg.dismiss();
}
};
task.execute(account);
}
/**
* Fetches the token from a particular Google account chosen by the user. DO NOT RUN THIS DIRECTLY. It must be run asynchronously inside an AsyncTask.
* @param activity
* @param account
* @return
*/
private String getAccessToken(Account account) {
try {
return GoogleAuthUtil.getToken(ctx, account.name, "oauth2:" + DriveScopes.DRIVE); // IMPORTANT: DriveScopes must be changed depending on what level of access you want
} catch (UserRecoverableAuthException e) {
// Start the Approval Screen intent, if not run from an Activity, add the Intent.FLAG_ACTIVITY_NEW_TASK flag.
a.startActivityForResult(e.getIntent(), REQUEST_TOKEN);
e.printStackTrace();
return null;
} catch (GoogleAuthException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private Drive getDriveService() {
mCredential = GoogleAccountCredential.usingOAuth2(this, DriveScopes.DRIVE);
mCredential.setSelectedAccountName(accountName);
return GDriveHelper.getDriveService(mCredential,getResources().getString(R.string.app_name));
}
/**
* Obtains a list of all files on the signed-in user's Google Drive account.
*/
private void getDriveFiles() {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
Drive service = getDriveService();
Log.d("SiteTrack", "FUNCTION getDriveFiles()");
Files.List request;
try {
request = service.files().list(); // .setQ("mimeType=\"text/plain\"");
} catch (IOException e) {
e.printStackTrace();
return;
}
do {
FileList files;
try {
System.out.println("got here");
Log.d("SiteTrack", request.toString());
//mCredential.setSelectedAccountName(accountName);
files = request.execute();
} catch (IOException e) {
e.printStackTrace();
Log.d("SiteTrack", "Exception");
return;
}
ArrayList<File> fileList = (ArrayList<File>) files.getItems();
Log.d("SiteTrack", "Files found: " + files.getItems().size());
for (File f : fileList) {
String fileId = f.getId();
String title = f.getTitle();
Log.d("SiteTrack", "File " + fileId + ": " + title);
}
request.setPageToken(files.getNextPageToken());
} while (request.getPageToken() != null && request.getPageToken().length() >= 0);
}
});
t.start();
}
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == CHOOSE_ACCOUNT && resultCode == RESULT_OK) {
accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
GoogleAccountManager gam = new GoogleAccountManager(this);
getAndUseAuthTokenInAsyncTask(gam.getAccountByName(accountName));
Log.d("SiteTrack", "CHOOSE_ACCOUNT");
} else if (requestCode == REQUEST_TOKEN && resultCode == RESULT_OK) {
accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
Log.d("SiteTrack", "REQUEST_TOKEN");
}
}
}
This generates the this trace on files = request.execute(); or any request.execute():
04-20 01:40:26.105: E/AndroidRuntime(27203): FATAL EXCEPTION: Thread-39033
04-20 01:40:26.105: E/AndroidRuntime(27203): java.lang.IllegalArgumentException: the name must not be empty: null
04-20 01:40:26.105: E/AndroidRuntime(27203): at android.os.Parcel.readException(Parcel.java:1429)
04-20 01:40:26.105: E/AndroidRuntime(27203): at android.os.Parcel.readException(Parcel.java:1379)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.android.gms.internal.x$a$a.a(Unknown Source)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:192)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:217)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:888)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:407)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:340)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:458)
04-20 01:40:26.105: E/AndroidRuntime(27203): at com.maiko.fool.Fool_5$3.run(Fool_5.java:184)
04-20 01:40:26.105: E/AndroidRuntime(27203): at java.lang.Thread.run(Thread.java:856)
I feel lost about this, without no clue about what could be wrong.I have followed this tutorial about configuring Google API Services: https://plus.google.com/u/0/114042449736049687152/posts/CD3L8zcJg5Z
Thank you for your help.
verify the var "accountName" you are passing to the "mCredential" object. Usually thats the reason of those errors. Greetings.
For other people facing the same problem ,
Try credential.setAccount() instead of credential.setAccountName();
as there is an additional "type" parameter in an account object which is required sometimes . For storage you could do something as in the case below : (pseudo code)
GoogleSignInAccount account = initAccount();
Account acct = account.getAccount();
storeStringInPrefs("NAME" , acct.name);
storeStringInPrefs("TYPE" , acct.type);
Then for retrieval
GoogleAccountCredential credential = GoogleAccountCredential.usingOauth(...);
String name = getPrefs("NAME");
String type = getPrefs("TYPE");
credential.setSelectedAccount(new Account(name , type));
Now it should work :D , This is just pseudo code for your basic understanding and will not work if copied into your project.
Just add .requestEmail()
to signing options :
GoogleSignInOptions.Builder options =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(new Scope(DriveScopes.DRIVE_APPDATA));
I got this when @gmail.com
was missing from the user name. Thought it was optional because it is in most Google forms...
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