I am trying to follow the lesson on developer.android.com and I am getting stuck on the
am.getAuthToken(
myAccount_, AUTH_TOKEN_TYPE,options,this,new OnTokenAcquired(),new Handler(new OnError()));
I don't get what to put in for the myAccount_; Is it accounts that is linked to the account array? Account[] accounts = accountManager.getAccountsByType("com.google");
The token part on class OnTokenAcquired is also gennerating an error saying it isn't a var, should I just make it a global var even though it is suposse to be a constant in the AccountManager.KEY_AUTHTOKEN?
This is the other link for the Authentication lesson and I am getting an error with DIALOG_ACCOUNTS, showDialog(DIALOG_ACCOUNTS) and manager.getAuthToken(account, AUTH_TOKEN_TYPE, null, activity, new AccountManagerCallback<Bundle>() in that tutorioul. I haven't gone much further in it because of the errors I am currently getting.
I don't get why these errors are happening? I assume it is just me not putting in the right vars though.
Any suggestions?
Here is the code I have copied.
public class AccountManagerActivity extends Activity {
AccountManager accountManager = AccountManager.get(this);
Account[] accounts = accountManager.getAccountsByType("com.google");
String AUTH_TOKEN_TYPE = "Manage your tasks";
String your_api_key;
String your_client_id;
String your_client_secret;
String token;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
URL url = new URL("https://www.googleapis.com/tasks/v1/users/#me/lists?key=" + your_api_key);
URLConnection conn = (HttpURLConnection) url.openConnection();
conn.addRequestProperty("client_id", your_client_id);
conn.addRequestProperty("client_secret", your_client_secret);
conn.setRequestProperty("Authorization", "OAuth " + token);
AccountManager am = AccountManager.get(this);
Bundle options = new Bundle();
am.invalidateAuthToken(token, AUTH_TOKEN_TYPE);
am.getAuthToken(
/*Error here*/ myAccount_, // Account retrieved using getAccountsByType()
AUTH_TOKEN_TYPE, // Auth scope
options, // Authenticator-specific options
this, // Your activity
new OnTokenAcquired(), // Callback called when a token is successfully acquired
new Handler(new OnError())); // Callback called if an error occurs
}
}
And then the OnTokenAcquired class
public class OnTokenAcquired implements AccountManagerCallback<Bundle> {
public void run(AccountManagerFuture<Bundle> result) {
// TODO Auto-generated method stub
// Get the result of the operation from the AccountManagerFuture.
Bundle bundle = result.getResult();
// The token is a named value in the bundle. The name of the value
// is stored in the constant AccountManager.KEY_AUTHTOKEN.
/*Error here*/ Token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
Intent launch = (Intent) result./*Error here*/get(AccountManager.KEY_INTENT);
if (launch != null) {
/*Error here*/ startActivityForResult(launch, 0);
return;
}
}
}
am.invalidateAuthToken(token, AUTH_TOKEN_TYPE);
should be
am.invalidateAuthToken(AUTH_TOKEN_TYPE, token);
Related
i'm new with android and i need to do a connection with server with oauth 2.0 i looked in internet and found just example how to dowit with google or github but my need is to connect with my own server i have the clientId clientSecret and the scope all i need is to get the token correctly
i hope my question is clear
thank you
this what i have donne
AccountManager am = AccountManager.get(Authentification.this);
Bundle options = new Bundle();
options.putSerializable("numero", numero);
am.getAuthToken(
null,
"whrite",
options,
this,
new OnTokenAcquired(),
null);
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
#Override
public void run(AccountManagerFuture<Bundle> result) {
// Get the result of the operation from the AccountManagerFuture.
try{
Bundle bundle = result.getResult();
// The token is a named value in the bundle. The name of the value
// is stored in the constant AccountManager.KEY_AUTHTOKEN.
String token = bundle.getString(AccountManager.KEY_AUTHTOKEN);
System.out.println("================>>>>"+token);
}catch(Exception e){
}
}
}
I would start with the AppAuth code sample. My blog post
has step by step instructions on how to run it.
Once it is working reconfigure it to point to your own Authorization Server.
I have completed all operation related to syncAdapter but now i m stuck on one minor issue
Auth Token
After 2hr my token just expired and then i need to show user a dialog to enter his password again so that he can renew his token.
AccountManager.get(getContext()).getAuthToken(account, LoginActivity.ACCOUNT_TYPE, null, false, new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> arg0) {
try {
arg0.getResult();
} catch (OperationCanceledException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AuthenticatorException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, null);
I m running this on onPerformSync but this is not opening an activity.
There are two parts to doing this
1) in your AbstractThreadedSyncAdapter implementation of overridden onPerformSync method you need to
Get the authcode from the AccountManager using method blockingGetAuthToken()
Try to use the authcode to perform your sync processes (i.e. web service call or whatever you use it for)
If the previous step failed because authcode has expired (e.g. your web serivce returns some kind of authcode expired message) then you need to invalidate the authcode via the AccountManager using method invalidateAuthToken()
2) in your AbstractAccountAuthenticator implementation of overridden getAuthToken() method
Use the AccountManager to retrieve the password that the user last provided and try to get a new authcode from your web service using those credentials.
If the previous step failed then add an intent to open your login activity to the bundle that is returned from the getAuthToken() method. This will cause the login screen to display
Example
#Override
public Bundle getAuthToken(AccountAuthenticatorResponse oResponse, Account oAccount, String strAuthTokenType, Bundle options)
throws NetworkErrorException {
// Validate the authentication type
if (!strAuthTokenType.equals("TODO: your auth token type URL here"))
{
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ERROR_MESSAGE, "invalid authTokenType");
return result;
}
// Try to get the password already stored in account manger, if there is one
final AccountManager oAccountManager = AccountManager.get(moContext);
final String strPassword = oAccountManager.getPassword(oAccount);
if (strPassword != null)
{
// TODO: Call the authentication web service method to get a fresh authcode
// Pass the strPassword and oAccount.name
Boolean blnVerified = //TODO: were the username + password authenticated?
String strNewAuthCode = //TODO: the new authcode returned by your authentication web service
// If it worked then return the result
if (blnVerified)
{
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, oAccount.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, "TODO: your account type URI here");
result.putString(AccountManager.KEY_AUTHTOKEN, strNewAuthCode);
return result;
}
}
// Password is missing or incorrect. Start the activity to ask user to provide the missing credentials.
// Open a UI form to get the user to input their username and password again
final Intent oIntent = new Intent(moContext, frmAccount_Auth.class);
oIntent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, oResponse);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, oIntent);
return bundle;
}
Well i need to authorize Google Calendar's access for a user, first google Id works fine when i use
blockingGetAuthToken
and it gets a token, i usually log on this token.
So when i tried to use other accounts i got a null token.
I searched a lot and found out that using getAuthToken is preferred as it uses a context from the activity calling it.. then i converted the whole process to use it
private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/calendar";
public static String authorize(AndroidtestActivity parent, Account account) {
AccountManager accountManager = AccountManager.get(parent);
Bundle options= new Bundle();
Log.d("MyAPP", "Get Authorization");
try {
AccountManagerFuture<Bundle> acc=accountManager.getAuthToken ( account, AUTH_TOKEN_TYPE, options, true, null, null);
Bundle authTokenBundle = acc.getResult();
String authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
Log.d("MyAPP","Token= "+authToken);
return authToken;
} catch (Exception ex) {
Logger.getLogger(GoogleAuthorize.class.getName()).log(Level.SEVERE,
null, ex);
}
return null;
}
}
but still no accounts could get a valid token, they all get a null one
then i saw this answer https://stackoverflow.com/a/2021337/1280902 and followed using invalidateAuthToken
private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/calendar";
public static String authorize(AndroidtestActivity parent, Account account) {
AccountManager accountManager = AccountManager.get(parent);
Bundle options= new Bundle();
Log.d("MyAPP", "Get Authorization");
try {
AccountManagerFuture<Bundle> acc=accountManager.getAuthToken ( account, AUTH_TOKEN_TYPE, options, true, null, null);
Bundle authTokenBundle = acc.getResult();
String authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
accountManager.invalidateAuthToken("com.google",authToken);
acc=accountManager.getAuthToken ( account, AUTH_TOKEN_TYPE, options, true, null, null);
authTokenBundle = acc.getResult();
authToken = authTokenBundle.get(AccountManager.KEY_AUTHTOKEN).toString();
Log.d("MyAPP","Token= "+authToken);
return authToken;
} catch (Exception ex) {
Logger.getLogger(GoogleAuthorize.class.getName()).log(Level.SEVERE,
null, ex);
}
return null;
}
}
but i had the same problem on every account i use, even the one that used to work at the beginning with blockingGetAuthToken
So am i missing something?
Ok it works fine when i use
getAuthToken (Account account, String authTokenType, Bundle options, Activity activity, AccountManagerCallback<Bundle> callback, Handler handler)
The activity parameter solved the problem..
I'm trying to figure out how to use Google Api for accessing/editing Google SpreadSheet.
I want to have a connection always with the same spreadsheet from many devices. I got examples using the AccountManager, but i should not use the user account. There is any good turorial?
Right now i've got the following..is that right?
AccountManager accountManager = AccountManager.get(this);
ArrayList googleAccounts = new ArrayList();
// Just for the example, I am using the first google account returned.
Account account = new Account("email#gmail.com", "com.google");
// "wise" = Google Spreadheets
AccountManagerFuture<Bundle> amf = accountManager.getAuthToken(account, "wise", null, this, null, null);
try {
Bundle authTokenBundle = amf.getResult();
String authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
// do something with the token
//InputStream response = sgc.getFeedAsStream(feedUrl, authToken, null, "2.1");
}
catch (Exception e) {
// TODO: handle exception
}
Required permissions:
<uses-permission android:name="android.permission.ACCOUNT_MANAGER"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
Choose needed outh token type from the table:
http://code.google.com/intl/ja/apis/spreadsheets/faq_gdata.html#Authentication
Spreadsheets Data API wise
Code sample:
public class OuthTokenActivity extends Activity {
String tag = "DEBUG";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AccountManager mAccountManager = AccountManager.get(this);
for (Account account : mAccountManager.getAccountsByType("com.google")) {
mAccountManager.getAuthToken(account, "wise", savedInstanceState,
this, resultCallback, null);
}
}
AccountManagerCallback<Bundle> resultCallback = new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle result = future.getResult();
String token = (String) result.get(AccountManager.KEY_AUTHTOKEN);
String name = (String) result.get(AccountManager.KEY_ACCOUNT_NAME);
Log.d(tag, String.format("name: %s, token: %s", name, token));
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
There is an API released now, available for java script, which could be run in your app. And they show how to integrate this into an Android app in a video here.
I am working on an Android Honeycomb (v3.0) application that has a requirement of communicating with the Google Calendar API. I would like to allow my application to access a particular Google account's Calendar data in order to read and create events.
Unfortunately, I ran into a problem with authorization using OAuth2. Here's what I have so far:
1) The Google account whose calendar I would like to access is registered within the Android device I am working with.
2) I enabled the Calendar API within the Google APIs Console on the account.
3) I am able to access this account using the following code:
AccountManager accountManager = AccountManager.get(this.getBaseContext());
Account[] accounts = accountManager.getAccountsByType("com.google");
Account acc = accounts[0]; // The device only has one account on it
4) I would now like to obtain an AuthToken for use when communicating with the calendar. I followed this tutorial, but converted everything to work with Google Calendar instead of Google Tasks. I successfully retrieve an authToken from the AccountManager with the account I would like to use by using getAuthToken with AUTH_TOKEN_TYPE == "oauth2:https://www.googleapis.com/auth/calendar".
5) Here's where the problems begin. I am now at this point:
AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(tokens[0]); // this is the correct token
HttpTransport transport = AndroidHttp.newCompatibleTransport();
Calendar service = Calendar.builder(transport, new JacksonFactory())
.setApplicationName("My Application's Name")
.setHttpRequestInitializer(accessProtectedResource)
.build();
service.setKey("myCalendarSimpleAPIAccessKey"); // This is deprecated???
Events events = service.events().list("primary").execute(); // Causes an exception!
6) Here's the exception returned by the last line:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "usageLimits",
"message" : "Daily Limit Exceeded. Please sign up",
"reason" : "dailyLimitExceededUnreg",
"extendedHelp" : "https://code.google.com/apis/console"
} ],
"message" : "Daily Limit Exceeded. Please sign up"
}
7) According to this Google API Video (wait a minute or so to get to the applicable content), a reason for this exception may be the fact that I did not enable the API access within the Google APIs Console for the account. However, if you look at 2), you can see that I did do so.
8) To me, it seems that the problem is that I was unable to set the Simple API Access Key correctly, because the Calendar.setKey method is deprecated. Within the Google Tasks tutorial that I previously linked, the key is set using Tasks.accessKey = "key". I'm not sure how to get this working with the Calendar API, though. I have tried multiple Google accounts, which all came up with the exception from 5).
9) I would like to point out that the traditional method of using OAuth2 did work for me. Here's the code I used for that:
HttpTransport TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
String SCOPE = "https://www.googleapis.com/auth/calendar";
String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";
String CLIENT_ID = "myClientID";
String CLIENT_SECRET = "myClientSecret";
String authorizeUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, CALLBACK_URL, SCOPE).build();
String authorizationCode = "???"; // At this point, I have to manually go to the authorizeUrl and grab the authorization code from there to paste it in here while in debug mode
GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, authorizationCode, CALLBACK_URL);
authRequest.useBasicAuthorization = false;
AccessTokenResponse authResponse = authRequest.execute();
String accessToken = authResponse.accessToken; // gets the correct token
GoogleAccessProtectedResource access = new GoogleAccessProtectedResource(accessToken, TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, authResponse.refreshToken);
HttpRequestFactory rf = TRANSPORT.createRequestFactory(access);
AccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(accessToken);
HttpTransport transport = AndroidHttp.newCompatibleTransport();
Calendar service = Calendar.builder(transport, new JacksonFactory())
.setApplicationName("My Application's Name")
.setHttpRequestInitializer(accessProtectedResource)
.build();
Events events = service.events().list("primary").execute(); // this works!
10) Finally, my question: I would like to use the account from the AccountManager on the device itself in order to retrieve a working OAuth2 token for use with the Google Calendar API. The second method is not useful for me, because the user will have to manually go to their web browser and get the authorization code, which is not user friendly. Anyone have any ideas? Apologies for the long post, and thanks!
Try adding a JsonHttpRequestInitializer to the builder and setting your key there:
Calendar service = Calendar.builder(transport, new JacksonFactory())
.setApplicationName("My Application's Name")
.setHttpRequestInitializer(accessProtectedResource)
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
public void initialize(JsonHttpRequest request) {
CalendarRequest calRequest = (CalendarRequest) request;
calRequest.setKey("myCalendarSimpleAPIAccessKey");
}
}).build();
To answer no 10 : I've basically had to do what you had to do working with the TaskSample and then use the Android GData Calendar Sample available here : http://code.google.com/p/google-api-java-client/source/browse/calendar-android-sample/src/main/java/com/google/api/client/sample/calendar/android/CalendarSample.java?repo=samples
to get the AuthToken from the AccountManager itself:
accountManager = new GoogleAccountManager(this);
settings = this.getSharedPreferences(PREF, 0);
gotAccount();
private void gotAccount() {
Account account = accountManager.getAccountByName(accountName);
if (account != null) {
if (settings.getString(PREF_AUTH_TOKEN, null) == null) {
accountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE,
true, new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> future) {
try {
Bundle bundle = future.getResult();
if (bundle
.containsKey(AccountManager.KEY_INTENT)) {
Intent intent = bundle
.getParcelable(AccountManager.KEY_INTENT);
int flags = intent.getFlags();
flags &= ~Intent.FLAG_ACTIVITY_NEW_TASK;
intent.setFlags(flags);
startActivityForResult(intent,
REQUEST_AUTHENTICATE);
} else if (bundle
.containsKey(AccountManager.KEY_AUTHTOKEN)) {
setAuthToken(bundle
.getString(AccountManager.KEY_AUTHTOKEN));
// executeRefreshCalendars();
}
} catch (Exception e) {
handleException(e);
}
}
}, null);
} else {
// executeRefreshCalendars();
}
return;
}
chooseAccount();
}
private void chooseAccount() {
accountManager.manager.getAuthTokenByFeatures(
GoogleAccountManager.ACCOUNT_TYPE, AUTH_TOKEN_TYPE, null,
ExportClockOption.this, null, null,
new AccountManagerCallback<Bundle>() {
#Override
public void run(AccountManagerFuture<Bundle> future) {
Bundle bundle;
try {
bundle = future.getResult();
setAccountName(bundle
.getString(AccountManager.KEY_ACCOUNT_NAME));
setAuthToken(bundle
.getString(AccountManager.KEY_AUTHTOKEN));
// executeRefreshCalendars();
} catch (OperationCanceledException e) {
// user canceled
} catch (AuthenticatorException e) {
handleException(e);
} catch (IOException e) {
handleException(e);
}
}
}, null);
}
void setAuthToken(String authToken) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_AUTH_TOKEN, authToken);
editor.commit();
createCalendarService(authToken);
try {
Events events = service.events().list("primary").execute();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void createCalendarService(String authToken) {
accessProtectedResource = new GoogleAccessProtectedResource(authToken);
Log.i(TAG, "accessProtectedResource.getAccessToken() = "
+ accessProtectedResource.getAccessToken());
JacksonFactory jsonFactory = new JacksonFactory();
service = com.google.api.services.calendar.Calendar
.builder(transport, jsonFactory)
.setApplicationName("Time Journal")
.setJsonHttpRequestInitializer(
new JsonHttpRequestInitializer() {
#Override
public void initialize(JsonHttpRequest request) {
CalendarRequest calendarRequest = (CalendarRequest) request;
calendarRequest
.setKey("<YOUR SIMPLE API KEY>");
}
}).setHttpRequestInitializer(accessProtectedResource)
.build();
}