我想从 Android 的 Google AccountManager 获得授权,然后我想以某种方式创建一个 Google API 服务来使用 Google 日历。我可以运行客户经理,但我的问题是,在运行 AccountManager 并获得授权后,如何使用这些授权创建服务来访问 Google 日历?我得到这个结果:
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"
}
at com.google.api.client.googleapis.services.GoogleClient.execute(GoogleClient.java:123)
...
使用此代码:
public final class CalendarSample extends Activity {
public static final String ROOT_URL = "https://www.googleapis.com/calendar/v3";
/** Logging level for HTTP requests/responses. */
private static Level LOGGING_LEVEL = Level.CONFIG;
private static final String AUTH_TOKEN_TYPE = "cl";
private static final String TAG = "CalendarSample";
private static final int MENU_ADD = 0;
private static final int MENU_ACCOUNTS = 1;
private static final int CONTEXT_EDIT = 0;
private static final int CONTEXT_DELETE = 1;
private static final int REQUEST_AUTHENTICATE = 0;
public int selectedCalendarIndex = 0;
public ListView calendarList;
final HttpTransport transport = AndroidHttp.newCompatibleTransport();
JacksonFactory jsonFactory = new JacksonFactory();
String accountName;
static final String PREF = TAG;
static final String PREF_ACCOUNT_NAME = "accountName";
static final String PREF_AUTH_TOKEN = "authToken";
static final String PREF_GSESSIONID = "gsessionid";
GoogleAccountManager accountManager;
SharedPreferences settings;
CalendarAndroidRequestInitializer requestInitializer;
com.google.api.services.calendar.Calendar service;
public class CalendarAndroidRequestInitializer extends CalendarRequestInitializer {
String authToken;
public CalendarAndroidRequestInitializer() {
super(transport);
authToken = settings.getString(PREF_AUTH_TOKEN, null);
setGsessionid(settings.getString(PREF_GSESSIONID, null));
}
@Override
public void intercept(HttpRequest request) throws IOException {
super.intercept(request); request.getHeaders().setAuthorization(GoogleHeaders.getGoogleLoginValue(authToken));
}
@Override
public boolean handleResponse(HttpRequest request, HttpResponse response, boolean retrySupported)
throws IOException {
switch (response.getStatusCode()) {
case 302:
super.handleResponse(request, response, retrySupported);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_GSESSIONID, getGsessionid());
editor.commit();
return true;
case 401:
accountManager.invalidateAuthToken(authToken);
authToken = null;
SharedPreferences.Editor editor2 = settings.edit();
editor2.remove(PREF_AUTH_TOKEN);
editor2.commit();
return false;
}
return false;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calendar_main);
Logger.getLogger("com.google.api.client").setLevel(LOGGING_LEVEL);
accountManager = new GoogleAccountManager(this);
settings = this.getSharedPreferences(PREF, 0);
class InitializeTask extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... arg0) {
requestInitializer = new CalendarAndroidRequestInitializer();
//I think the problem occurs here. I am doing something wrong maybe.
service = Calendar.builder(transport, jsonFactory)
.setApplicationName("YOUR_APPLICATION_NAME")
.setHttpRequestInitializer(requestInitializer)
.build();
return null;
}
@Override
protected void onPostExecute(Void eventFeed) {
}
}
AsyncTask<Void, Integer, Void> t = new InitializeTask().execute();
try {
t.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
calendarList = (ListView) findViewById(R.id.calendar_list);
calendarList.setTextFilterEnabled(true);
calendarList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
selectedCalendarIndex = pos;
executeRefreshCalendars();
}
});
gotAccount();
}
void setAuthToken(String authToken) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_AUTH_TOKEN, authToken);
editor.commit();
requestInitializer.authToken = authToken;
}
void setAccountName(String accountName) {
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.remove(PREF_GSESSIONID);
editor.commit();
this.accountName = accountName;
requestInitializer.setGsessionid(null);
}
private void gotAccount() {
Account account = accountManager.getAccountByName(accountName);
if (account != null) {
// handle invalid token
if (requestInitializer.authToken == null) {
accountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE, true,
new AccountManagerCallback<Bundle>() {
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, CalendarSample.this, null, null,
new AccountManagerCallback<Bundle>() {
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);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_AUTHENTICATE:
if (resultCode == RESULT_OK) {
gotAccount();
} else {
chooseAccount();
}
break;
}
}
void executeRefreshCalendars() {
class ExecuteRefreshCalendarTask extends AsyncTask<Void, Integer, Void> {
Activity activity;
public ExecuteRefreshCalendarTask(Activity activity) {
this.activity = activity;
}
@Override
protected Void doInBackground(Void... arg0) {
com.google.api.services.calendar.model.Calendar calendar;
try {
calendar = service.calendars().get("primary").execute();
System.out.println(calendar.getSummary()); // here I want to print title of calendars to see if it is running correctly
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void eventFeed) {
}
AsyncTask<Void, Integer, Void> task = new ExecuteRefreshCalendarTask(this).execute();
}
void handleException(Exception e) {
e.printStackTrace();
if (e instanceof HttpResponseException) {
HttpResponse response = ((HttpResponseException) e).getResponse();
int statusCode = response.getStatusCode();
try {
response.ignore();
} catch (IOException e1) {
e1.printStackTrace();
}
// TODO(yanivi): should only try this once to avoid infinite loop
if (statusCode == 401) {
gotAccount();
return;
}
try {
Log.e(TAG, response.parseAsString());
} catch (IOException parseException) {
parseException.printStackTrace();
}
}
Log.e(TAG, e.getMessage(), e);
}
}