使用googleapi-client-java操作gtasks(一)
Google Tasks的API终于开放了,可以方便的保存树状工作任务,对照文档和例子摸索了一遍,将一些关键点给大家分享一下。
如果对于googleapi-client-java库没什么了解,可以参考我前面的一篇文章:
http://mypyg.iteye.com/admin/blogs/816237
当然这个库自从那个时候后又更新了很多,好用多了。
下载库:
http://code.google.com/p/google-api-java-client/wiki/APIs
这里面的包每个都包含了google api client,并且根据服务的不同,进行了各自的扩展,我们这儿选择Tasks的API,下载库,另外还有文档,还有个更有意思的:https://code.google.com/apis/explorer/#_s=tasks&_v=v1,API浏览页面,可以直接输入法参数然后与服务器通信很直观的看到与服务器交换的数据内容,因为要访问个人数据,使用explorer时注意右上角 Switch to Private Access,切换到授权模式。
阅读示例代码http://code.google.com/p/google-api-java-client/source/browse/taskqueue-json-oauth-sample?repo=samples
打开eclipse,首选创建一个空project,将刚才下载的zip包导入此项目,以方便其他项目引用其中的jar包。
然后创建一个新项目,设置build path,要手工加上以下几个包的依赖:
google-api-client-1.7.0
google-api-client-android2-1.7.0
google-api-tasks-v1-rev2-java-1.4.0
google-http-client-1.7.0
google-http-client-android2-1.7.0
google-oauth-client
guava-11.0.1
jackson-coer-asl
如果不加的话,最终生成apk包时不会包含,会导致运行时出现类找不到的情况。
其中android2的两个包时针对android sdk 2以上平台的,都是在相应的通用包上作了一点扩展,但是并没有包含通用包,所以对应的通用包也要加入build path。如果sdk是3的,那么就替换成android3的包。
使用google服务的流程:
1.使用用户名、密码获取授权Token(令牌,没有的话google不让访问数据,使用用户名和密码从google服务器获得)。
2.使用授权字符串以及其他的参数发送http请求。
3.解析响应,并处理结果。
在Android平台上获取授权可以通过AccountManager服务来实现,只要有绑定的Gmail账户,就无须再次输入密码。发送请求以及解析响应则通过googleapi-client-java库中封装的函数来实现了。
下面就结合实际的代码做下说明:
基础类:
com.google.api.services.tasks.v1.Tasks.Tasks:Tasks服务的封装类。
构造函数:
Tasks(HttpTransport transport, HttpRequestInitializer requestInitializer, JsonFactory jsonFactory)
参数transport:通过http交互数据的封装类。
参数requestInitializer:对http request进行初始化的对象
参数jsonFactory:解析、构造json数据的对象
代码片段(代码具体位置参见附件,文章的代码只是为了方便讲解,位置都是乱的):
1.基本对象
/** *保存Token的类,实现了接口HttpRequestInitializer,会在HTTP请求头中增加一行 *Authorization: Oath {你得到的token} **/private GoogleAccessProtectedResource mAccessProtectedResource = new GoogleAccessProtectedResource(null);//通过Http协议传输数据的类private final HttpTransport mTransport = AndroidHttp.newCompatibleTransport();//Google Tasks服务对象private Tasks mService = new Tasks(mTransport, mAccessProtectedResource, new JacksonFactory());//账户管理对象private GoogleAccountManager mAccountManager = new GoogleAccountManager(this);
2.获得Token并保存
//token类型:tasks的约定即为此字符串。不要漏了前面的oauth2:否则一直提示密码错误//或者使用tasks的auth token类型别名"Manage your tasks"。参见:http://code.google.com/apis/tasks/oauth-android-auth-token-type-aliases.html//这样用户看到的就不是一个url,而是一个可以理解的字符串。//所有的别名列表网上找不到了,好多人在问private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/tasks";//获取TokenmAccountManager.manager.getAuthToken(account, AUTH_TOKEN_TYPE, true, new AccountManagerCallback<Bundle>() {@Overridepublic void run(AccountManagerFuture<Bundle> future) {try {Bundle bundle = future.getResult();if(bundle.containsKey(AccountManager.KEY_INTENT)) {Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); //弹出窗口用户选择是否允许访问Google Tasks数据startActivityForResult(intent, REQUEST_AUTHENTICATE);}else if(bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) { //得到授权字符串并保存mAccessProtectedResource.setAccessToken(bundle.getString(AccountManager.KEY_AUTHTOKEN)); //从服务器获取数据onAuthToken();}}catch(Exception e) {handleException(e);}}}, null);
3.从服务器获取数据:
private void onAuthToken() { List<String> tasks = new ArrayList<String>(); try { /*向服务器发送请求,并解析成列表。 在这个过程中实际上向服务器发送了: GET https://www.googleapis.com/tasks/v1/users/@me/lists Authorization: OAuth {Token xxx x xx x x x} X-JavaScript-User-Agent: Google APIs Explorer google-api-gwt-client/0.1-alpha 服务器回应了: 200 OK 以及一个包含有所有列表的Json对象。 */List<TaskList> lists = mService.tasklists.list().execute().items;for(TaskList tl : lists) {tasks.add(tl.title);}setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, tasks));} catch (IOException e) {handleException(e);} }
4.关于API KEY:
如果直接使用Google的例子编译后运行,会发现服务器回应400 Bad request,跟踪发现是因为API KEY没有设置的原因(访问Google Calendar就没这个限制),Google为了防止资源被滥用,通过API KEY来限制Ap,比如Gtasks就限制每个API KEY每天只能访问5000次(一个请求就是1次),而且API KEY是跟着Ap走的,比如一个Ap有5000个人安装了,那么平均每个人每天只能访问1次Google Tasks服务了,即使这5000个人有5000个Google账户也是被这么限制。那么如何不受此限制呢?
我想的方法之一是Ap启动时,要求用户输入自己的API KEY,那么这样所有的用户就互不干扰了,各自都有5000次的可用次数了。
API Key的获得:
直接访问网址:https://code.google.com/apis/console#access
如果从来没有来过此网址,那么第一页会让你create project,点击后进入下一个页面,选择Services,把Tasks API的开关选择为ON,再选择API Access,在Simple API Access的框内就可以看到API KEY了,复制了即可。
API KEY在代码中的设置:
mService.accessKey = 你的API_KEY;
1 楼 Ovbk2c 2012-03-28 你好, 很感谢你分享的经验,
我在你的demo的基础上开发关联GTask的应用.
我把与服务器同步数据部分放到了Service下执行.
在同步时执行到Tasklists mTasklists = mService.tasklists(); TaskLists mTaskLists = mTasklists.list().execute();时发生了com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
调用execute()时触发的.
授权那部分我都是参照你的demo处理的.
原来的demo一直都好用. 我在做了一次service的更改后出现了这个问题.
我在网上查了一下信息 参照一个修改了一下private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/tasks.readonly";
从web端读取下来数据可以,但是对web端做修改就不行.因为是只读的.但是如果我去掉readonly.第一次执行到execute() 就会触发这个异常 你能帮我分析下吗 或者你想了解更多的问题 我的qq406704801 不胜感激 2 楼 mypyg 2012-03-28 看看你用Service发出去的数据是啥,对比一下和Demo中的有啥差异 3 楼 Ovbk2c 2012-03-28 mypyg 写道看看你用Service发出去的数据是啥,对比一下和Demo中的有啥差异
现在正常的情况是private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/tasks";我要用这个. 但是执行
Tasklists mTasklists = mService.tasklists();
TaskLists mTaskLists = mTasklists.list().execute();这句的execute()时报的错. 不明白为什么 GoogleJsonResponseException: 401 Unauthorized 4 楼 mypyg 2012-03-29 参考这篇 http://mypyg.iteye.com/blog/1468952
看看是不是授权码和令牌弄混了,只有授权码,没有令牌也是无法访问数据的。 5 楼 Ovbk2c 2012-04-09 mypyg 写道参考这篇 http://mypyg.iteye.com/blog/1468952
看看是不是授权码和令牌弄混了,只有授权码,没有令牌也是无法访问数据的。
还有 google task 的api_key 每天限制5000次访问. 这个限制有办法破除么 6 楼 mypyg 2012-04-09 1.使用oAuth2验证需要clientid,会被计算限额。
2.使用Android的AccountManager,虽然获得token时不需要clientid,但是执行任何操作都必须带上apikey,否则说你没登录,带上apikey了又会被计算限额。
经过试验,暂时没有找到破除的方法。
只能写mail管google要了。
或者另一种方法,多申请几个账号,10个账号就5w次了,程序里面随机使用某个账号的key。此种方法如果使用的是AccountManager获得的token,对于用户一点感觉都没有。