对于很多第三方的机器没有安装Google账户管理,要访问GTasks,那么可以使用OAuth 2.0的认证方式。
OAuth 2.0的认证流程:
1.得到授权码
2.使用授权码获得真正的数据访问令牌
其中数据访问令牌一般有效期为60分钟,在得到此访问令牌的时候还会得到一个刷新令牌,当访问令牌过期后可以用此刷新令牌自动获得一个新的。
1.授权码的获得:
用浏览器打开一个url,这个url是由要访问的服务以及其他一些相关信息生成的。
/*
* https://code.google.com/oauthplayground 可以找到一个scope列表。
*/
private final static String SCOPE = "https://www.googleapis.com/auth/tasks";
/*以下信息来自于https://code.google.com/apis/console
*创建一个Project,然后选择要激活的Service,我激活了Calendar和Tasks API
*选择API Access,可以设置OAuth 2.0,进而得到相关信息。
*创建id时选择for installed applications。
*/
private final static String CLIENT_ID = "你的id.apps.googleusercontent.com";
private final static String CLIENT_SECRET = "你的secret";
private static final String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";
private void requestAuthCode() {
String authorizeUrl = new GoogleAuthorizationRequestUrl(CLIENT_ID, CALLBACK_URL, SCOPE).build();
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(authorizeUrl));
startActivity(intent);
}
用户看到一个浏览器打开的页面,输入用户名和密码后就可以得到授权码,不过要手工复制一下,然后到程序中粘贴。
授权码是时刻在变的,即使是同一个设备同一个ap去获取同一个账户的授权码也是在变的。
2.数据访问令牌的获取
用授权码作为参数,获取后保存。
private boolean requestToken(String authCode) {
GoogleAuthorizationCodeGrant authRequest = new GoogleAuthorizationCodeGrant(mTransport,
new JacksonFactory(), CLIENT_ID, CLIENT_SECRET, authCode, CALLBACK_URL);
authRequest.useBasicAuthorization = false;
AccessTokenResponse authResponse;
try {
authResponse = authRequest.execute(); //发出请求
mAccessToken = authResponse.accessToken;
mRefreshToken = authResponse.refreshToken;
return true;
} catch( HttpResponseException he) {
he.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
3.读取数据
使用token构造一个可以进行访问保护资源的对象。
然后构造一个Tasks对象。
执行tasks的execute()方法就可以获得数据了。
当获取数据时,token有可能过期,这个时候会得到401的响应值,此时需要刷新一下token,然后再获取数据。
if(mAccessProtectedResource == null) {
mAccessProtectedResource = new GoogleAccessProtectedResource(mAccessToken,
mTransport, new JacksonFactory(), CLIENT_ID, CLIENT_SECRET, mRefreshToken);
}
if(mService == null) mService = new Tasks(mTransport, mAccessProtectedResource, new JacksonFactory());
mTaskListNames.clear();
try {
List<TaskList> lists = mService.tasklists.list().execute().items;
for(TaskList tl : lists) {
mTaskListNames.add(tl.title);
}
mAdapter.notifyDataSetChanged();
} catch(HttpResponseException he) {
if(he.getResponse().getStatusCode() == 401) {
//token 过期,刷新token
try {
mAccessProtectedResource.refreshToken();
mAccessToken = mAccessProtectedResource.getAccessToken();
mRefreshToken = mAccessProtectedResource.getRefreshToken();
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
}
另外此种方法访问用户数据因为Client_ID没有改变,所以每个Ap的限额仍然是每日5000次,即使访问的是不同账户的数据。
那么解决限额的方法只能是交钱买更多的,或者Ap里面多内置几个Client_ID,随机选用了,当然这些Client_ID必须是隶属于不同账户的。
或者就好像(一)中提到的,让用户自己输入自己的API KEY,不过这个太专业了,一般人不好搞。
直接通过HttpClient走REST协议似乎可以不用client_id和api key,可参见:
https://code.google.com/apis/explorer 应该也不行,在获取授权码的时候就要client id
如果授权失败返回的错误码是401,如果是超限额返回的错误码是403。
另外如果使用proguard,那么要增加配置:
(来自于http://code.google.com/p/google-api-java-client/wiki/Setup)
# Needed by google-api-client to keep generic types and @Key annotations accessed via reflection
-keepclassmembers class * {
@com.google.api.client.util.Key <fields>;
}
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
# Needed by Guava
-dontwarn sun.misc.Unsafe
# See https://groups.google.com/forum/#!topic/guava-discuss/YCZzeCiIVoI
-dontwarn com.google.common.collect.MinMaxPriorityQueue
PS:经试验task的title的长度最大为1024字节;note的最大长度为8192字节。