Monthly Archives: December 2011

[Android Dev] Gmail OAuth

自从几个月前Gmail更新之后,第三方app就不能再通过ContentResolver去获取gmail的内容和状态了。因此很多Gmail Unread/Reminder就没办法用以前的方式工作了。我的app里Gmail Reminder的功能也因此暂时取消。
最近终于有时间继续写code,google了一番之后发现目前最可靠的方法就是用OAuth来访问Gmail。

不过在Android实现OAuth还是有一点tricky的,在这边写下来,作为开发笔记,说不定也能帮到一些人 🙂
p.s. 得感谢Google Search和Stackoverflow,从里面抄了不少code.

计划分成2部分: 1) OAuth认证; 2) 通过Token访问Gmail并计算unread count
具体的细节可以直接访问开源项目 https://code.google.com/p/minemessagevibrator/

一)OAuth: 主要使用signpost库实现。(https://code.google.com/p/oauth-signpost/)

1. 是一个处理OAuth以及callback的Activity. 这个Activity负责打开oauth的网站,让用户认证完成之后得到callback,并得到和保存token.
说明:
i) android:scheme和android:host是为了回调的时候响应自定义的URI: “mine-activity://mine-vibration/”
ii) singleTask是为了回调的时候能得到onNewIntent()消息

<activity android:name=".oauth.MineOAuthAccessActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="mine-activity" android:host="mine-vibration"/>
</intent-filter>
</activity>

2. 准备signpost的OAuthProvider, 其中consumerKey和consumerSecret是应用的key和secret,熟悉Twitter OAuth的人肯定知道。在Google上可以用”anonymous”

mConsumer = new CommonsHttpOAuthConsumer(consumerKey, consumerSecret);
mProvider = new CommonsHttpOAuthProvider(
"https://www.google.com/accounts/OAuthGetRequestToken?scope="
+ URLEncoder.encode("https://mail.google.com/", "utf-8"),
"https://www.google.com/accounts/OAuthGetAccessToken",
"https://www.google.com/accounts/OAuthAuthorizeToken?hd=default");
mCallbackUrl = "mine-activity://mine-vibration/";

3. 获得request token的URL,很简单。但是注意这一步需要网络连接。

String authUrl = mProvider.retrieveRequestToken(mConsumer, mCallbackUrl);

4. 打开浏览器让用户进行认证,也很简单。

startActivity(new Intent("android.intent.action.VIEW", Uri.parse(ret)).
setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP |
Intent.FLAG_ACTIVITY_NO_HISTORY |
Intent.FLAG_FROM_BACKGROUND));

5. 当用户认证完,网站会重定向到callback URL,就是 “mine-activity://mine-vibration/”,在Android里,会启动MineOAuthAccessActivity并调用onNewIntent(),我们要做的事情是从回调的参数里获得verifier,并获取access token & secret。这样OAuth的认证过程就结束了。之后app可以通过access token去访问gmail。

Uri uri = intent.getData();
String verifier = uri.getQueryParameter("oauth_verifier");
mProvider.retrieveAccessToken(mConsumer, verifier);
mConsumer.getToken();    // AccessToken
mConsumer.getTokenSecret();    // Token Secret

6. 在小内存的机器上(比如说俺的Milestone),启动浏览器之后基本上原来的Activity就会被kill掉,而且process也很可能被杀掉,这样当callback回来的时候,会发现原来的变量都没了。所以我们必须保存OAuth相关的变量,这样可以在启动浏览器之前保存,在重启Activity之后恢复。可以通过java的Serialize object来实现。
保存:

FileOutputStream fos = context.openFileOutput("xxx", // saved file name
Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(xxx);    // the object to save
os.close();

读取:

FileInputStream fis;
fis = context.openFileInput("xxx");  // the file name
ObjectInputStream is = new ObjectInputStream(fis);
xxx= (xxx) is.readObject();    // the object to load
is.close();

但是signpost的类虽然是Serializable的,但是其中有个不知道算不算bug的问题,其中CommonsHttpOAuthProvider里的httpClient被声明成transient的,所以这个变量是不能被serialize的。因此得额外加一句:

mProvider.setHttpClient(new DefaultHttpClient());

Done!

btw, 通过Token访问Gmail并计算unread count会有另外一篇blog来介绍。

Share

2011.12.10 月全食

    这些年来最佳观测月全食的时机,不容错过。正好有同事是个天文迷,有不少望远镜可借;而舍友有专业的单反+三角架。这回可以好好观测、好好拍照了。
    唯一缺的是望远镜接相机的转接环,不过那也太专业了,咱们还是玩业余的…

    晚上七点多,很试了一下定时拍摄功能,每两分钟一张,中间调试过一次,最后照片合成的效果是这样的:

 

    半影食开始一会儿之后,19:43~20:04,每隔7分钟拍一张照:

 

    半影食过程中,20:08~20:28,间隔5分钟:

 

    初亏即将开始,20:33~20:45,间隔4分钟:

 

    月食过程中,20:52~21:12,间隔4分钟:

 

    月食快全吃完了,21:25~21:37,间隔4分钟:

    最后我要说,用高倍望远镜手持着找月亮,难度颇高,而且天气太冷,还是单反定时拍摄,效果不错,哈!

Share

[zz] 讳疾忌医,一场事先张扬的谋杀,不仅仅是一场比赛

这几年看球,已经很淡定了,有英超、欧冠的曼联比赛基本上都是每场都看,无论是输是赢。
这两年又是转型年,然而流年不利,伤病实在太多,也难为老头子了。其实去年的阵容居然能拿联赛冠军欧冠还进决赛,已经是奇迹了,今年只是被打回原形而已。。。
看到篇文章写得不错,转载一下。

————–

扁鹊见蔡桓公,立有间,扁鹊曰:“君有疾在腠理,不治将恐深。”桓侯曰:“寡人无疾。”

09年夏天,曼联在罗马完败巴萨,彼时宇宙队雏形初现,爵爷曾在赛季末对媒体表示球队进攻线依赖个人能力需要提高。不日C罗9400W欧元转会皇马,单直至市场休市,只进补瓦伦西亚、奥贝坦、欧文。高层表示并无合适人选且泡沫太多。参考其他豪门出售核心,尤文用齐达内的钱换来了图拉姆、内德维德、布冯,反而提升整体实力。利物浦5000W托雷斯,转手3500W卡罗尔和2500W苏亚雷斯,一赔一赚保住了锋线实力。国米5000W+埃托奥送出伊布,换的第二赛季三冠王5位主力,莫塔卢西奥埃托奥斯内德米利托。只有A米和我们一样,卡卡换来的6000W存入银行,导致直到看到德比对手辉煌才痛定思痛打开钱包。核心离去后未及时进补,为后来薄弱的阵容埋下第一个隐患。

扁鹊复见曰:“君之病在肌肤,不治将益深。”桓侯不应。扁鹊出,桓侯又不悦。

次年赛季末,两线赛事在魔鬼赛程下崩盘,对拜仁皆是下半场逆转,看似是首回合埃弗拉一次不经意的解围,实际是一套阵容打到底,5月已如强弩之末,只看到了埃弗拉在左路上上下下,却不见其身后板凳无合格替补。且哈格持续养伤,卡里克状态下滑,安德森迟迟不见开窍,中场问题突然摆上桌面,曾一度依赖斯科尔斯的表现。当年SIR对吉布森成长和哈格的身体仍然抱有希望,中场未有实际进补。

居十日,扁鹊望桓侯而还走。桓侯故使人问之,扁鹊曰:“疾在腠理,汤熨之所及也;在肌肤,针石之所及也;在肠胃,火齐之所及也;在骨髓,司命之所属,无奈何也。今在骨髓,臣是以无请也。”

今年5月,曼联自信的带着第19座联赛奖杯进入温布利,却重复了2年前的剧情。只是赛季里中场依赖的人,从S18变成了38岁的G11。于是整个夏天的基调表示如何复仇,在期待中迎来了难得的“大”手笔,一个个青年才俊进驻卡灵顿,一度接近风光无限的三冠王核心中场。最终,最需要的位置反而只有一个预备队的提拔,而其他位置单纯为对位更新换代。
而中场的问题,也终于像病毒一样传染开来,已经影响到了锋线和后防。最恶劣的影响就是鲁尼,不能安心的在锋线做一个前锋,经常地后撤组织进攻为中场买单,甚至在中场缺人时直接安排到大禁区之外,当梅西和c罗舒舒服服的待在锋线上享受中场的输送打出华丽的数据时,鲁尼需要往回跑给别人擦屁股。这事曾经发生过,那会我们锋线上有还有个无与伦比的葡萄牙人,现在只有个模仿的走火入魔的葡萄牙人。进攻没有创造性,防守的拦截能力同样一塌糊涂,最直接的就是显示在数据上那被射门次数最多的,开始大家觉得没什么,直到那个1比6,才真实感觉到痛,才想起来数据不会说谎,才发现我们其实玩不起大开大阖,才想起来上赛季的猥琐流。

以上,是因为爵爷的固执还是球员的无能?我觉得都不是,能把如此阵容带进温布利,超过利物浦,爵爷已经是做到资源利用最大化了,1700w的瓦伦西亚和阿什利杨这些球员,对中下游球队和偶尔对强队的亮点已经值了,你无法要求他们像某罗和某西一样又稳定又强大,他们都是好球员,但不是Mr.Key。要怪只能怪我们“聪明的”美国老板,我们也曾是去别国联赛挖头牌的队伍(贝隆),但现在爵爷却在转会市场上束手束脚,我们本应迎娶贝尔和斯内德这样的球员,但现在却只能在一个A+和B+中选择后者。现在我们的指望变成了爵爷的眼光,带来更多的豌豆,以及更早的看清吉布森之流。反正给你1个亿转会费也只是有可能冠军,给你2000W怎么也是前三,都无碍市值稳定增长。老板现在做的,完全就是压榨教练。

Share

达文西行走中队 -《脑蒸发》

第一次成功参加“达文西行走中队”活动,纪念一下。(之前要么报名失败,要么时间不合适错过…)

这回是在上海话剧艺术中心•D6空间的小剧场话剧《脑蒸发》,由“深圳大学师范学院艺术系”剧团上演。
——–以下有剧透———-
有那么一间精神病院,三个护士、四个医生、八个病人。
在护士和医生的严密看护下,病人们在自己的幻想中,表面上平静地生活着。某一天开始,他们开始密谋想要“飞越疯人院”。
虽然都是精神病人,虽然各自有各自的幻想,但在“蒸发”这件任务上,他们却是目标明确,喊着“自重、自爱、自强、自救”的口号,分工协作,一个个小目标渐渐完成,来到了他们计划的蒸发的最后时刻。
蒸发行动开始之后,他们又是和护士、医生斗智斗勇,充分利用之前获得的“资源”逃出了生天,开始了自由的新生活…
——–以下安全————-

· 剧情很有新意,各处都有笑点,是部很欢乐的话剧;
· 演员们的表演尤其专业!印象最深的是,其中一个爱上了自己另一幅面孔,导致前后不分的的精神病人,真的演出了前后不分的感觉,无论是向前或是向后(假如不看脚的方向),真的很难分清楚她哪一面才是前。
· 剧本可能还是弱了点,毕竟是学生的“作业”,某些场景稍显凌乱了些。也许剧本可以更有深度,更能让人思考…
· 总之,很赞,很推荐~


Share