I am working on an app that, among other things, authenticates with Google to grab a user's profile picture and name from their Google account. At present, I am just trying to print out the token received from Google as a debug measure, to verify that it is working that far. However, I consistently have a null token (it doesn't appear to be set at all), giving the following error:
java.lang.NullPointerException
com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
com.sp.norsesquare.froyo.NorseSquare$LoginAsyncTask.doInBackground(NS.java:465)
com.sp.norsesquare.froyo.NorseSquare$LoginAsyncTask.doInBackground(NS.java:1)
android.os.AsyncTask$2.call(AsyncTask.java:287)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
java.util.concurrent.FutureTask.run(FutureTask.java:137)
android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
java.lang.Thread.run(Thread.java:856)
I am using an custom AsyncTask class to get the data and return it to the main activity, this is defined as a public class within the main activity.
public class LoginAsyncTask extends AsyncTask<String, Void, String>
{
NS ns;
String email;
String mScope;
String authToken;
Context context;
Bundle bundle;
public LoginAsyncTask(String e)
{
email = e;
bundle = new Bundle();
}
protected void onPreExecute()
{
Log.i("BEGIN","Getting authtoken");
}
protected String doInBackground(String... args)
{
try
{
authToken = GoogleAuthUtil.getToken(context, email, "oauth2:"+"https://www.googleapis.com/auth/userinfo.profile", bundle);
Log.i("MESSAGEGEGEGE","YOUR TOKEN = "+authToken);
}
catch (UserRecoverableAuthException recoverableException) {
Toast.makeText(context, "UserRecoverableException Occurred", Toast.LENGTH_LONG).show();
Log.e("GOOGLEAUTH","UserRecoverableException Triggered");
Intent recoveryIntent = recoverableException.getIntent();
} catch (GoogleAuthException authEx) {
Log.e("MESSAAGEGEG", "Unrecoverable authentication exception: " + authEx.getMessage(), authEx);
} catch (IOException ioEx) {
Log.i("MESSAGEGEGE", "transient error encountered: " + ioEx.getMessage());
}
catch (Exception e) {
e.printStackTrace();
}
return authToken;
}
protected void onProgressUpdate(Integer... progress)
{
Log.i("PROGRESS","Getting somewhere");
}
protected void onPostExecute(String result)
{
Log.i("GOOGLEAUTH", "Returning Received Google Token");
googleAuthToken = result;
//This is a variable defined in the main activity
}
}
I am somewhat lost as to where this is coming from, and cannot find anything anywhere. I would deeply appreciate your help, thanks!
As suggested by Arhimed, the context you're passing to getToken() is likely null. This happened to me when I was cobbling some things together for quick and dirty testing. Passing it a valid context resolved the error.
Related
I am trying to get OAuth token from AccountManager for twitter account and using it to follow a twitter handle using Twitter4j. But I am getting no authenticating challenges found TwitterException.
Bellow is the code to get the token and follow the user:
try{
AccountManager accountManager = AccountManager.get(getActivity());
Account twitterAccount = accountManager.getAccountsByType(AccountType.TWITTER.getType())[0];
AccountManagerFuture<Bundle> tokenFuture = accountManager.getAuthToken(twitterAccount, "com.twitter.android.oauth.token", null, true, new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> result) {
Bundle bundle;
try {
bundle = result.getResult();
Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (intent != null) {
// User input required
getActivity().startActivity(intent);
} else {
String token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
Log.i(TAG, "Token:" + token);
userToken = token;
}
} catch (Exception e) {
Log.e(TAG, "Error getting token", e);
}
}
}, null);
AccountManagerFuture<Bundle> secretFuture = accountManager.getAuthToken(twitterAccount, "com.twitter.android.oauth.token.secret", null, true, new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> result) {
Bundle bundle;
try {
bundle = result.getResult();
Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (intent != null) {
// User input required
getActivity().startActivity(intent);
} else {
String secret = bundle.getString(AccountManager.KEY_AUTHTOKEN);
Log.i(TAG, "Secret Token:" + secret);
userSecret = secret;
}
} catch (Exception e) {
Log.e(TAG, "Error getting token", e);
}
}
}, null);
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder
.setOAuthConsumerKey(<Consumer-key>);
configurationBuilder
.setOAuthConsumerSecret(<Consumer-Secret>);
configurationBuilder.setOAuthAccessToken(userToken);
configurationBuilder.setOAuthAccessTokenSecret(userSecret);
Twitter twitter = new TwitterFactory(configurationBuilder.build()).getInstance();
User user = twitter.createFriendship(param.getUserName());
Toast.makeText(followListActivity,"Followed user #"+user.getScreenName()+" :)",Toast.LENGTH_SHORT);
} catch (TwitterException e) {
e.printStackTrace();
}
Getting this exception:
TwitterException{exceptionCode=[ec1fe56d-1e3b4ac5 3ea58453-a92e09a2], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=4.0.2}
at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:178)
at twitter4j.HttpClientBase.request(HttpClientBase.java:53)
at twitter4j.HttpClientBase.get(HttpClientBase.java:71)
at twitter4j.TwitterBaseImpl.fillInIDAndScreenName(TwitterBaseImpl.java:128)
at twitter4j.TwitterImpl.verifyCredentials(TwitterImpl.java:545)
at asynctask.FollowTwitterUserAsyncTask.doInBackground(FollowTwitterUserAsyncTask.java:113)
at asynctask.FollowTwitterUserAsyncTask.doInBackground(FollowTwitterUserAsyncTask.java:33)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.io.IOException: No authentication challenges found
at libcore.net.http.HttpURLConnectionImpl.getAuthorizationCredentials(HttpURLConnectionImpl.java:438)
at libcore.net.http.HttpURLConnectionImpl.processAuthHeader(HttpURLConnectionImpl.java:418)
at libcore.net.http.HttpURLConnectionImpl.processResponseHeaders(HttpURLConnectionImpl.java:367)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:301)
at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)
at twitter4j.HttpResponseImpl.<init>(HttpResponseImpl.java:35)
at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:142)
Please point out what I am doing wrong here.
You don’t do anything wrong at all, that’s an issue with the library. In Android, a HTTP response code of 401 causes an IOException be thrown. The library implementor checks for the message string of the IOException to catch it, however your message string is slightly different so the exception handling doesn’t execute. Unluckily, the issue tracker is not enabled for that GitHub project, but you may try to contact the project owner, maybe he will fix it for you. Otherwise you will have to modify the library code and build it yourself.
My app allows users to login with Google Plus, and gets their name, and email address. I am tried to access the token.
Code to access the token:
Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
AccountManager am = AccountManager.get(this);
final Account[] accounts = am.getAccountsByType(GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
AsyncTask<Void, Void, String> task2 = new AsyncTask<Void, Void, String>() {
public static final int REQUEST_CODE_TOKEN_AUTH = 100;
#Override
protected String doInBackground(Void... params) {
String mScope="audience:server:client_id:899555500747-38rpnq51of946grhdvofck7r8u5p09cd.apps.googleusercontent.com:api_scope:https://www.googleapis.com/auth/plus.login";
// Get the token for the current user
String token = null;
try {
token = GoogleAuthUtil.getToken(getApplicationContext(), Plus.AccountApi.getAccountName(mGoogleApiClient), mScope);
Log.i("G token", token);
} catch (IOException transientEx) {
// Network or server error, try later
Log.e(TAG, transientEx.toString());
} catch (UserRecoverableAuthException e) {
// Recover (with e.getIntent())
Log.e(TAG, e.toString());
Intent recover = e.getIntent();
startActivityForResult(recover, REQUEST_CODE_TOKEN_AUTH );
} catch (GoogleAuthException authEx) {
// The call is not ever expected to succeed
// assuming you have already verified that
// Google Play services is installed.
Log.e(TAG, authEx.toString());
}
return token;
}
#Override
protected void onPostExecute(String token) {
Log.i(TAG, "Access token retrieved:" + token);
}
};
task2.execute();
Error:
01-27 23:42:14.877 30994-31262/com.unicloud.mittal E/loginWithGooglePlus﹕ com.google.android.gms.auth.GoogleAuthException: Unknown
01-27 23:42:14.877 30994-30994/com.unicloud.mittal I/loginWithGooglePlus﹕ Access token retrieved:null
I have tried various solutions which I could find on stackoverflow. At the moment, I am using Client ID from "Service Account" from dev console, I have also tried using it for "Client ID for Android Application", it still showed the same error.
Please let me know what am I doing wrong? Thanks.
I solved this question by replacing this line
String mScope="audience:server:client_id:899555500747-38rpnq51of946grhdvofck7r8u5p09cd.apps.googleusercontent.com:api_scope:https://www.googleapis.com/auth/plus.login";
with this
String mScope = "oauth2:https://www.googleapis.com/auth/plus.login";
I got the access token, and I was wondering if I am doing right. So I verified if the token was correct.
I tried to go to this address, I replaced accessToken with the token I retrieved.
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=accessToken
It showed me this kind of output.
{
"issued_to": "xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
"audience": "xxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
"user_id": "xxxxxxxxxxxxxxxxxxxxxxx",
"scope": "https://www.googleapis.com/auth/userinfo.profile https://gdata.youtube.com",
"expires_in": 3019,
"access_type": "online"
}
In the issued_to it showed me my Client ID for Android Application that means this token is issued to my client id. So I assume I am on the right track.
I need to get access token and send it to the server. With that access token server should get all user details, like name, profile picture and email.
I can get access token using Scopes.PLUS_LOGIN and Scopes.PLUS_ME, but with that access token server can't get user email.
Here is my code:
#Override
public void onConnected(Bundle arg0) {
mSignInClicked = false;
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String token = null;
String scope = "oauth2:" + Scopes.PLUS_LOGIN + " " + Scopes.PLUS_ME;
try {
token = GoogleAuthUtil.getToken(
getApplicationContext(),
Plus.AccountApi.getAccountName(mGoogleApiClient),
scope);
appUser.setToken(token);
} catch (IOException transientEx) {
// Network or server error, try later
Log.e(TAG, transientEx.toString());
} catch (UserRecoverableAuthException e) {
// Recover (with e.getIntent())
} catch (GoogleAuthException authEx) {
// The call is not ever expected to succeed
// assuming you have already verified that
// Google Play services is installed.
Log.e(TAG, authEx.toString());
}
return token;
}
#Override
protected void onPostExecute(String token) {
Log.i(TAG, "Access token retrieved:" + appUser.getToken());
// Get user's information
}
};
}
Does anybody know how to solve this problem?
You are missing the scope
https://www.googleapis.com/auth/userinfo.email
I tested the other scopes and only that one appears to return the users email. You can test the different scopes and what they return here: People: get.
Note: I'm not an android programmer, you will probably have better luck finding out how to request that scope with android. I am looking, but haven't been able to find it.
Looks like the scope might just be email https://developers.google.com/+/api/oauth#email
In my android application, I am trying to get AccessToken from GoogleAuthUtil as below :
accessToken = GoogleAuthUtil.getToken(this, mPlusClient.getAccountName(), "oauth2:" + SCOPES);
But At this line I am gettting error as below :
E/GoogleAuthUtil(4696): Calling this from your main thread can lead to deadlock and/or ANRs
E/GoogleAuthUtil(4696): java.lang.IllegalStateException: calling this from your main thread can lead to deadlock
E/GoogleAuthUtil(4696): at com.google.android.gms.auth.GoogleAuthUtil.b(Unknown Source)
E/GoogleAuthUtil(4696): at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
E/GoogleAuthUtil(4696): at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
Any solution of this problem? Any help will be appreciated.
Try it with an AsyncTask like this:
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String token = null;
try {
token = GoogleAuthUtil.getToken(
MainActivity.this,
mGoogleApiClient.getAccountName(),
"oauth2:" + SCOPES);
} catch (IOException transientEx) {
// Network or server error, try later
Log.e(TAG, transientEx.toString());
} catch (UserRecoverableAuthException e) {
// Recover (with e.getIntent())
Log.e(TAG, e.toString());
Intent recover = e.getIntent();
startActivityForResult(recover, REQUEST_CODE_TOKEN_AUTH);
} catch (GoogleAuthException authEx) {
// The call is not ever expected to succeed
// assuming you have already verified that
// Google Play services is installed.
Log.e(TAG, authEx.toString());
}
return token;
}
#Override
protected void onPostExecute(String token) {
Log.i(TAG, "Access token retrieved:" + token);
}
};
task.execute();
SCOPES is a space separated list of OAuth 2.0 scope strings. For example SCOPES could be defined as:
public static final String SCOPES = "https://www.googleapis.com/auth/plus.login "
+ "https://www.googleapis.com/auth/drive.file";
These represent the permissions that your app is requesting from the user. The scopes requested in this example are documented here:
https://developers.google.com/+/api/oauth
https://developers.google.com/drive/android/files
Use separate thread for your internet code. Error is telling that more time consuming process is running in the app and here that is internet. So use separate thread or Async task.
Check out this link NetworkOnMainThreadException
Hope it will help you.
E/GoogleAuthUtil(4696): java.lang.IllegalStateException: calling this
from your main thread can lead to deadlock
Sounds like you need to do that on a separate thread, have you tried that?
Here you can find information about threads in Android.
Thread CrearEventoHilo = new Thread(){
public void run(){
//do something that retrun "Calling this from your main thread can lead to deadlock"
}
};
CrearEventoHilo.start();
CrearEventoHilo.interrupt();
public class Foo {
MyThread mTh;
void cantBeBothered() {
mTh = new MyThread( /*...*/ );
mTh.run();
mTh.start();
}
void imFinishedNowWaitingForThread() {
mTh.join();
}
void imOutKillingOffPendingThread() {
mTh.interrupt();
}
// .....
private class MyThread extends Thread {
// ...;
MyThread( /*...*/) {
// this... = ...;
}
public void run() {
doSomething( /*this...*/ );
}
}
}
While implementing Twitter integration in my app, I discovered the following oddness of the Eclipse debugger. What is causing this?
I'm using this AsyncTask for getting a request token from twitter using twitter4j 3.0.3.
public class TwitterRequestAsync extends AsyncTask<Void, Void, RequestToken> {
private Context context;
public TwitterRequestAsync(Context context) {
this.context = context;
}
#Override
protected RequestToken doInBackground( Void... params ) {
Twitter twitter = getTwitter(); // getTwitter() is in enclosing class
try {
RequestToken token = twitter.getOAuthRequestToken();
return token;
}
catch (TwitterException e) {
Log.e( TAG, e.getMessage(), e );
return null;
}
}
#Override
protected void onPostExecute( RequestToken result ) {
super.onPostExecute( result );
if ( result != null ) {
// stuffs concerning request token here
}
}
}
When I debug this code it appears that there is an exception thrown when getOAuthRequestToken() executes and the next line that the debugger shows executing is in the catch clause, return null;
However, the result that is returned to onPostExecute(...) is a valid request token, so the debugger is doing something weird. I've cleaned my project and restarted Eclipse each multiple times with no change in this behavior. Am I broken?
This is a known issue. It appears that it could be a problem with the Dalvik VM. The last return statement of the method is shown to execute in the debugger.
Changing the doInBackground body to:
#Override
protected RequestToken doInBackground( Void... params ) {
Twitter twitter = getTwitter();
RequestToken token = null;
try {
token = twitter.getOAuthRequestToken();
}
catch (TwitterException e) {
Log.e( TAG, e.getMessage(), e );
}
return token;
}
Causes execution to appear to proceed as expected.
See https://groups.google.com/forum/?fromgroups=#!topic/android-developers/DEU6JmdyFyM for an old mention of the problem with a link to an even older mention. Someone finally created an issue for this at https://code.google.com/p/android/issues/detail?id=34193.
As your self-answer notes, this is a known issue. I wanted to point out that it (and other quirks) are documented in the Dalvik docs. You can find it in the official but raw form, or unofficial but formatted -- skip down to "Known Issues and Limitations".
It would be nice if the documentation was more prominent.