<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D0cFSX4-fip7ImA9WhRbEEU.&quot;"><id>tag:blogger.com,1999:blog-14443318</id><updated>2012-02-01T17:30:18.056+09:00</updated><category term="Hack for Japan" /><category term="AozoraReader" /><category term="android" /><category term="taintdroid" /><category term="android oauth" /><category term="rails" /><category term="iPhone App" /><category term="redmine" /><category term="遠野" /><category term="android oauth GData" /><category term="google-api-java-client" /><category term="Mercurial" /><category term="android app" /><title>What happens today?</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://abekatsu.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>58</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/WhatHappensToday" /><feedburner:info uri="whathappenstoday" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;C08DRHc5fSp7ImA9WhRTE00.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-7869677174236855224</id><published>2011-11-03T15:30:00.001+09:00</published><updated>2011-11-03T15:31:15.925+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-03T15:31:15.925+09:00</app:edited><title /><content type="html">android関連のarticleは11月6日までに全削除いたします。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-7869677174236855224?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/F4ZF9aDbzXjfL-kyJ9gTD8yVFWw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/F4ZF9aDbzXjfL-kyJ9gTD8yVFWw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/F4ZF9aDbzXjfL-kyJ9gTD8yVFWw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/F4ZF9aDbzXjfL-kyJ9gTD8yVFWw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/w-2IauC6TPg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/7869677174236855224/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=7869677174236855224" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7869677174236855224?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7869677174236855224?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/w-2IauC6TPg/androidarticle116.html" title="" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/11/androidarticle116.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4ESXo5cSp7ImA9WhdSFk8.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-7761631152757354715</id><published>2011-07-26T06:21:00.001+09:00</published><updated>2011-07-26T06:21:48.429+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-26T06:21:48.429+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="遠野" /><category scheme="http://www.blogger.com/atom/ns#" term="Hack for Japan" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Hack for Japan 遠野会場へ行ってきました</title><content type="html">&lt;p&gt;&lt;a href="http://www.hack4.jp/RelatedInfo/Events/PastEvents/110723tono"&gt;遠野でのHack For Japanイベント&lt;/a&gt;に行ってきました。&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://goo.gl/photos/ulcLcIIYBa" imageanchor="1" style="clear:right;margin-bottom:1em;margin-left:1em"&gt;&lt;img border="0" src="https://lh5.googleusercontent.com/-qI42zu-iufU/Ti3crqGmFgE/AAAAAAAACCk/j_Me6ZNnXcs/s160-c/HackForJapan.jpg"&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h4&gt;作ったもの&lt;/h4&gt;&lt;iframe src="https://docs.google.com/present/embed?id=df9phz46_18f94tv4fb" frameborder="0" width="410" height="342"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="296" id="utv57959" name="utv_n_294313"&gt;&lt;param name="flashvars" value="loc=%2F&amp;amp;autoplay=false&amp;amp;vid=16210978&amp;amp;locale=ja_JP&amp;amp;hasticket=false&amp;amp;v3=1" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://www.ustream.tv/flash/viewer.swf" /&gt;&lt;embed flashvars="loc=%2F&amp;amp;autoplay=false&amp;amp;vid=16210978&amp;amp;locale=ja_JP&amp;amp;hasticket=false&amp;amp;v3=1" width="480" height="296" allowfullscreen="true" allowscriptaccess="always" id="utv57959" name="utv_n_294313" src="http://www.ustream.tv/flash/viewer.swf" type="application/x-shockwave-flash" /&gt;&lt;/object&gt;&lt;br /&gt;
36:30ぐらいから。&lt;br /&gt;
&lt;br /&gt;
&lt;p&gt;コメントとして，&lt;br /&gt;
&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;状況は変化していくので，updateもできるような機能がほしい&lt;br /&gt;
  &lt;li&gt;PersonFinderと連携してほしい&lt;br /&gt;
  &lt;li&gt;緊急退避情報として，現在地付近のこれまでの津波の高さ（「波高」，「浸水高」，「遡上高」？）を表示して，近くの高台の場所を緊急避難場所として表示する。過去の教訓をもとにした資料に，1時間は動くなという石碑があったのでそれを参考に。&lt;br /&gt;
&lt;/ul&gt;&lt;p&gt;（不足していたらご指摘いただけませんでしょうか）などがあり，今後の課題とします。
&lt;/p&gt;
&lt;h4&gt;改善点&lt;/h4&gt;&lt;h5&gt;開発環境の準備&lt;/h5&gt;&lt;p&gt;今回，現地で&lt;a href="http://developer.android.com/sdk/installing.html"&gt;Android SDKをインストール&lt;/a&gt;したのですが，&lt;a href="http://developer.android.com/sdk/installing.html#AddingComponents"&gt;Step 4のAdding Platforms and Other Components&lt;/a&gt;で，全てのコンポーネントをインストールしようとして，この作業で1，2時間ぐらいかかった。今回，アイデアソンでしゃべった内容を当日作ることになったので，必ずしも全員が開発環境わけではないので，できれば事前告知しておけばよかった。&lt;/p&gt;&lt;p&gt;&lt;h5&gt;妥協リストの作成&lt;/h5&gt;&lt;p&gt;まずは動くものを成果物にあげようというコンセプトで，実装する際に妥協したこともあった。たとえば，設定項目（送信先メールアドレス，SMS送信先電話番号）は，保存できていない。このリストを共有できれば，後日協力者を集めるのに役立てられるだろう。
&lt;/p&gt;
&lt;p&gt;今回遠野まごころネットさんの方とお話する機会があり，支援物資管理などICTの技術が利用できるところは多々あるが，瞬発力も必要ということで，速やかに動くものを提供する，柔軟に変更点に対応するなど，表に出てくることが必要かと思う。
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-7761631152757354715?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/itVG_MWvnH23E_VV01sCiHiadWE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/itVG_MWvnH23E_VV01sCiHiadWE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/itVG_MWvnH23E_VV01sCiHiadWE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/itVG_MWvnH23E_VV01sCiHiadWE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/80hhQ6oxIHc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/7761631152757354715/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=7761631152757354715" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7761631152757354715?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7761631152757354715?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/80hhQ6oxIHc/hack-for-japan.html" title="Hack for Japan 遠野会場へ行ってきました" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh5.googleusercontent.com/-qI42zu-iufU/Ti3crqGmFgE/AAAAAAAACCk/j_Me6ZNnXcs/s72-c/HackForJapan.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/07/hack-for-japan.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMGRns7eip7ImA9WhZWFkQ.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-2910636315057151207</id><published>2011-05-18T14:57:00.003+09:00</published><updated>2011-05-18T15:00:27.502+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-18T15:00:27.502+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="google-api-java-client" /><category scheme="http://www.blogger.com/atom/ns#" term="android oauth GData" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Google APIs Client Library for JavaのAndroid向けライブラリのソースを公開しました。</title><content type="html">&lt;a href="http://abekatsu.blogspot.com/2011/05/published-my-android-library-to-use.html"&gt;英語版&lt;/a&gt;の日本語版です。&lt;br /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://code.google.com/p/google-api-java-client/"&gt;Google APIs Client Library for Java&lt;/a&gt; &lt;br /&gt;
のAndroid向けライブラリのソースを公開しました。&lt;br /&gt;
(URL は &lt;a href="http://code.google.com/p/android-library-google-api-java/"&gt;http://code.google.com/p/android-library-google-api-java/&lt;/a&gt; です。）&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
単に，Google SpreadSheets に対して，OAuth 1.0a で&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt; 新しいSpreadSheetの作成&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; worksheet entryの追加&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt; セルの更新&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;
ができます。他のサービスについても作成していきますが，なんせあまりいいエンジニアじゃないので，スピードは相当遅いです。JavaDocも何も作成していなくて申し訳ございません。
何か，要望，提案や間違いの指摘，バグレポートがありましたら &lt;a href="http://www.google.com/profiles/katsuhisa.abe"&gt;こちら&lt;/a&gt;よりご連絡ください。 
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-s3OIpiZ57-8/TdNeMWL9EhI/AAAAAAAAB-E/dsVWZv5pj04/s1600/android-library-google-api-java.jpg" imageanchor="1"&gt;&lt;img border="0" height="208" src="http://4.bp.blogspot.com/-s3OIpiZ57-8/TdNeMWL9EhI/AAAAAAAAB-E/dsVWZv5pj04/s320/android-library-google-api-java.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-2910636315057151207?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/d7DN_2EU4Er08pgSGXPCM_eg8Xk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d7DN_2EU4Er08pgSGXPCM_eg8Xk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/d7DN_2EU4Er08pgSGXPCM_eg8Xk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d7DN_2EU4Er08pgSGXPCM_eg8Xk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/UQrXIKfFJkQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/2910636315057151207/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=2910636315057151207" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/2910636315057151207?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/2910636315057151207?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/UQrXIKfFJkQ/google-apis-client-library-for.html" title="Google APIs Client Library for JavaのAndroid向けライブラリのソースを公開しました。" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-s3OIpiZ57-8/TdNeMWL9EhI/AAAAAAAAB-E/dsVWZv5pj04/s72-c/android-library-google-api-java.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/05/google-apis-client-library-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQGQ3o9eCp7ImA9WhZWFkQ.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-6794669148443517799</id><published>2011-05-18T14:50:00.004+09:00</published><updated>2011-05-18T14:58:42.460+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-18T14:58:42.460+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="google-api-java-client" /><category scheme="http://www.blogger.com/atom/ns#" term="android oauth GData" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Published my android library to use Google APIs Client Library for Java</title><content type="html">&lt;p&gt;I upload sources of my android library to use &lt;a href="http://code.google.com/p/google-api-java-client/"&gt;Google APIs Client Library for Java.&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a just sample for Google Spread Sheet, but it can create new spreadsheet and worksheet, rename the title of worksheet entry, and put cells on your worksheet with OAuth1.0a.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
URL is &lt;a href="http://code.google.com/p/android-library-google-api-java/"&gt;http://code.google.com/p/android-library-google-api-java/&lt;/a&gt;.  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
I am preparing JavaDoc and classes for other services. But I am not good engineer, so speed to update migh be very slow. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Please contact &lt;a href="http://www.google.com/profiles/katsuhisa.abe"&gt;me&lt;/a&gt; if you have any requests, suggestions, corrections and bug reports.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-s3OIpiZ57-8/TdNeMWL9EhI/AAAAAAAAB-E/dsVWZv5pj04/s1600/android-library-google-api-java.jpg" imageanchor="1" style=""&gt;&lt;img border="0" height="208" width="320" src="http://4.bp.blogspot.com/-s3OIpiZ57-8/TdNeMWL9EhI/AAAAAAAAB-E/dsVWZv5pj04/s320/android-library-google-api-java.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-6794669148443517799?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ob_akcFx2Y2JfhJliFZ8SrijHI0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ob_akcFx2Y2JfhJliFZ8SrijHI0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ob_akcFx2Y2JfhJliFZ8SrijHI0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ob_akcFx2Y2JfhJliFZ8SrijHI0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/S_yKCRzYltg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/6794669148443517799/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=6794669148443517799" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6794669148443517799?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6794669148443517799?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/S_yKCRzYltg/published-my-android-library-to-use.html" title="Published my android library to use Google APIs Client Library for Java" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-s3OIpiZ57-8/TdNeMWL9EhI/AAAAAAAAB-E/dsVWZv5pj04/s72-c/android-library-google-api-java.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/05/published-my-android-library-to-use.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEECQ3Y_fCp7ImA9WhZXGE8.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-6852715392402987162</id><published>2011-05-08T11:43:00.001+09:00</published><updated>2011-05-08T11:44:22.844+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-08T11:44:22.844+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="google-api-java-client" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Google Spreadsheets を Androidから扱う (5) DataModelの定義</title><content type="html">&lt;p&gt;&lt;a href="http://code.google.com/p/google-api-java-client/"&gt;Google-API-Java-Client&lt;/a&gt;を用いて，Google Docsにアクセスするためには，GData-Java-Clientとは異なり，自分でデータモデルを定義する必要があります。&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;First, you need to invest in writing a custom data model for the Google API. Please read the JavaDoc for the new XML data model in google-api-java-client. &lt;br /&gt;&lt;br /&gt;
参照元 (&lt;a href="http://code.google.com/p/gdata-java-client/wiki/MigratingToGoogleApiJavaClient"&gt;What if I have a larde code base that uses gdata-java-client&lt;/a&gt;)&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
ここでは，次のfeedを表すデータモデルを具体的に定義してみましょう。feed は&lt;br /&gt;
&lt;a href="http://code.google.com/intl/ja/apis/gdata/docs/2.0/reference.html#QueryResponses"&gt;QueryResponses&lt;/a&gt;&lt;br /&gt;
に掲載されているデータを利用しました。&lt;br /&gt;
&lt;br /&gt;
&lt;div id="feed_sample"&gt;&lt;pre class="brush:xml"&gt;&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;feed xmlns:atom="http://www.w3.org/2005/Atom"
        xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/"
        xmlns:gd='http://schemas.google.com/g/2005'
        gd:etag='W/"C0QBRXcycSp7ImA9WxRVFUk."'&gt;
  &lt;id&gt;http://www.example.com/feed/1234.1/posts/full&lt;/id&gt;
  &lt;updated&gt;2005-09-16T00:42:06Z&lt;/updated&gt;
  &lt;title type="text"&gt;Books and Romance with Jo and Liz&lt;/title&gt;
  &lt;link rel="alternate" type="text/html" href="http://www.example.net/"/&gt;
  &lt;link rel="http://schemas.google.com/g/2005#feed"
    type="application/atom+xml"
    href="http://www.example.com/feed/1234.1/posts/full"/&gt;
  &lt;link rel="http://schemas.google.com/g/2005#post"
    type="application/atom+xml"
    href="http://www.example.com/feed/1234.1/posts/full"/&gt;
  &lt;link rel="self" type="application/atom+xml"
    href="http://www.example.com/feed/1234.1/posts/full"/&gt;
  &lt;author&gt;
    &lt;name&gt;Elizabeth Bennet&lt;/name&gt;
    &lt;email&gt;liz@gmail.com&lt;/email&gt;
  &lt;/author&gt;
  &lt;generator version="1.0"
    uri="http://www.example.com"&gt;Example Generator Engine&lt;/generator&gt;
  &lt;openSearch:totalResults&gt;2&lt;/openSearch:totalResults&gt;
  &lt;openSearch:startIndex&gt;0&lt;/openSearch:startIndex&gt;
  &lt;entry gd:etag='W/"C0QBRXcycSp7ImA9WxRVGUo."'&gt;
    &lt;id&gt;http://www.example.com/feed/1234.1/posts/full/4521614025009481151&lt;/id&gt;
    &lt;published&gt;2005-01-09T08:00:00Z&lt;/published&gt;
    &lt;updated&gt;2005-01-09T08:00:00Z&lt;/updated&gt;
    &lt;category scheme="http://www.example.com/type" term="blog.post"/&gt;
    &lt;title type="text"&gt;This is the title of entry 1009&lt;/title&gt;
    &lt;content type="xhtml"&gt;
      &lt;div
        xmlns="http://www.w3.org/1999/xhtml"&gt;This is the entry body of entry 1009&lt;/div&gt;    &lt;/content&gt;
    &lt;link rel="alternate" type="text/html"
      href="http://www.example.com/posturl"/&gt;
    &lt;link rel="edit" type="application/atom+xml"
      href="http://www.example.com/feed/1234.1/posts/full/4521614025009481151"/&gt;
    &lt;author&gt;
      &lt;name&gt;Elizabeth Bennet&lt;/name&gt;
      &lt;email&gt;liz@gmail.com&lt;/email&gt;
    &lt;/author&gt;
  &lt;/entry&gt;
  &lt;entry gd:etag='W/"C0QBRXrurSp7ImA9WxRVGUo."'&gt;
    &lt;id&gt;http://www.example.com/feed/1234.1/posts/full/3067545004648931569&lt;/id&gt;
    &lt;published&gt;2005-01-07T08:00:00Z&lt;/published&gt;
    &lt;updated&gt;2005-01-07T08:02:00Z&lt;/updated&gt;
    &lt;category scheme="http://www.example.com/type" term="blog.post"/&gt;
    &lt;title type="text"&gt;This is the title of entry 1007&lt;/title&gt;
    &lt;content type="xhtml"&gt;
      &lt;div
        xmlns="http://www.w3.org/1999/xhtml"&gt;This is the entry body of entry 1007&lt;/div&gt;    &lt;/content&gt;
    &lt;link rel="alternate" type="text/html"
      href="http://www.example.com/posturl"/&gt;
    &lt;link rel="edit" type="application/atom+xml"
      href="http://www.example.com/feed/1234.1/posts/full/3067545004648931569"/&gt;
    &lt;author&gt;
      &lt;name&gt;Elizabeth Bennet&lt;/name&gt;
      &lt;email&gt;liz@gmail.com&lt;/email&gt;
    &lt;/author&gt;
  &lt;/entry&gt;
&lt;/feed&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
まず，root要素 feed について定義していきます。&lt;br /&gt;
&lt;br /&gt;
&lt;div id="feed_element"&gt;&lt;pre class="brush:java"&gt;public class GoogleDocFeed {
    // TBD
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
feed要素の属性にある名前空間に関係した属性，"xmlns:atom"，"xmlns:openSearch"，"xmlns:gd" は今回扱いません。&lt;br /&gt;
一方，属性 "gd:etag" は今後使うことも考慮して，データモデルを定義します。&lt;br /&gt;
&lt;div id="feed_gd:etag"&gt;&lt;pre class="brush:java"&gt;import com.google.api.client.util.Key;

public class GoogleDocFeed {
    @Key("gd:etag")
    public string gd_etag;
    // TBD
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
つぎに，&amp;lt;id&amp;gt;http://www.example.com/feed/1234.1/posts/full&amp;lt;/id&amp;gt; のように，属性を持たず，かつ内部に子要素を含まない要素の&lt;br /&gt;
データモデルを定義していきます。&lt;br /&gt;
&lt;br /&gt;
&lt;div id="feed_gd:id"&gt;&lt;pre class="brush:java"&gt;    @Key  
    public string id;      // for &lt;id&gt;http://www.example.com/feed/1234.1/posts/full&lt;/id&gt;

    @Key  
    public string updated; // for &lt;updated&gt;2005-09-16T00:42:06Z&lt;/updated&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
つぎに，link要素を定義していきます。feed要素にはlink要素を子要素として複数持つことができますので，&lt;br /&gt;
&lt;br /&gt;
&lt;div id="feed_gd:links"&gt;&lt;pre class="brush:java"&gt;    @Key("link")  
    public List&lt;Link&gt; links;
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
と定義します。class Link は以下のように定義します。&lt;br /&gt;
&lt;br /&gt;
&lt;div id="Links"&gt;&lt;pre class="brush:java"&gt;public class Link {
    // for &lt;link rel="alternate" type="text/html" href="http://www.example.net/"/&gt;
    @Key("@rel")
    public String rel;

    @Key("@type")
    public String type;

    @Key("@href")
    public String href;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
次に，author要素を定義します。&lt;br /&gt;
&lt;div id="Author"&gt;&lt;pre class="brush:java"&gt;public class Author {
    /* for 
     *  &lt;author&gt;
     *    &lt;name&gt;Elizabeth Bennet&lt;/name&gt;
     *    &lt;email&gt;liz@gmail.com&lt;/email&gt;
     *  &lt;/author&gt;
     */

    @Key
    public String name;

    @Key
    public String email;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
その他に，属性と要素の内容にテキストコンテンツが与えられているtitle要素を定義します。&lt;br /&gt;
&lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.0.9-alpha/com/google/api/client/googleapis/xml/atom/package-summary.html"&gt;&lt;br /&gt;
JavaDoc Package com.google.api.client.googleapis.xml.atom&lt;/a&gt;に，&lt;br /&gt;
&lt;blockquote&gt;The optional value parameter of this @Key annotation specifies the XPath name to use to represent the field. For example, an XML attribute a has an XPath name of @a, an XML element &amp;lt;a&amp;gt; has an XPath name of a, and an XML text content has an XPath name of text(). &lt;br /&gt;
&lt;/blockquote&gt;とありますように，@Key("text()") と指定して，テキストコンテンツの内容を表します。&lt;br /&gt;
&lt;br /&gt;
&lt;div id="Title"&gt;&lt;pre class="brush:java"&gt;public class Title {
    /* for 
     *   &lt;title type="text"&gt;This is the title of entry 1007&lt;/title&gt;
     */

    @Key("@type")
    public String type;

    @Key("text()")
    public String context;
}

&lt;/pre&gt;&lt;/div&gt;他の要素も同様にして，上記で与えられている feed 要素を定義するデータモデル GoogleDocFeed が定義できます。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div id="fGoogleDocFeed"&gt;&lt;pre class="brush:java"&gt;import com.google.api.client.util.Key;

public class Category {

    /*  
     *  &lt;category scheme="http://www.example.com/type" term="blog.post"/&gt;
     */

    @Key("@scheme")
    public String scheme;

    @Key("@term")
    public String term;

}

public class Content {

    /*
     *  &lt;content type="xhtml"&gt;
     *    &lt;div
     *     xmlns="http://www.w3.org/1999/xhtml"&gt;This is the entry body of entry 1007&lt;/div&gt;     *  &lt;/content&gt;
     */ 

    @Key("@type")
    public String type;

    @Key("text()")
    public String content;

}

public class Link {

    /*  
     *  &lt;link rel="alternate" type="text/html" href="http://www.example.net/"/&gt;
     */

    @Key("@rel")
    public String rel;

    @Key("@type")
    public String type;

    @Key("@href")
    public String href;
}

public class Author {
    /* for 
     *  &lt;author&gt;
     *    &lt;name&gt;Elizabeth Bennet&lt;/name&gt;
     *    &lt;email&gt;liz@gmail.com&lt;/email&gt;
     *  &lt;/author&gt;
     */

    @Key
    public String name;

    @Key
    public String email;
}

public class Title {
    /* for 
     *   &lt;title type="text"&gt;This is the title of entry 1007&lt;/title&gt;
     */

    @Key("@type")
    public String type;

    @Key("text()")
    public String context;
}

public class GoogleDocEntry {
    @Key  
    public string id;      

    @Key  
    public string published; 

    @Key  
    public string updated; 

    @Key
    public Category category;

    @Key
    public Title title;

    @Key
    public Content content;

    @Key("link")  
    public List&lt;Link&gt; links;

    @Key
    public Author author;

}

public class GoogleDocFeed {
    @Key("gd:etag")
    public string gd_etag;

    @Key  
    public string id;      // for &lt;id&gt;http://www.example.com/feed/1234.1/posts/full&lt;/id&gt;

    @Key  
    public string updated; // for &lt;updated&gt;2005-09-16T00:42:06Z&lt;/updated&gt;

    @Key("link")  
    public List&lt;Link&gt; links;

    @Key
    public Author author;

    @Key
    public Generator generator;

    @Key("openSearch:totalResults")
    public int totalResults;
    
    @Key("openSearch:startIndex")
    public int startIndex;
    
    @Key("entry")  
    public List&lt;GoogleDocEntry&gt; entries;
}
&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
今回は，具体的なコンテントをベースにしてデータモデルを定義しましたが，&lt;br /&gt;
schema は用意されていますので（例 &lt;a href="http://code.google.com/intl/ja/apis/spreadsheets/data/3.0/reference.html"&gt;&lt;br /&gt;
Google Spreadsheets API Reference Guide (v3.0)&lt;/a&gt;），それを参考にして各自でデータモデルを定義できます。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-6852715392402987162?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/joCKwXuTb2O9UzXCqPqF2BnJ5rU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/joCKwXuTb2O9UzXCqPqF2BnJ5rU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/joCKwXuTb2O9UzXCqPqF2BnJ5rU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/joCKwXuTb2O9UzXCqPqF2BnJ5rU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/y8qfsK5IxDI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/6852715392402987162/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=6852715392402987162" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6852715392402987162?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6852715392402987162?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/y8qfsK5IxDI/google-spreadsheets-android-5-datamodel.html" title="Google Spreadsheets を Androidから扱う (5) DataModelの定義" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/05/google-spreadsheets-android-5-datamodel.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUGRX04eyp7ImA9WhZREUk.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-3403108922022391862</id><published>2011-04-07T11:08:00.001+09:00</published><updated>2011-04-07T11:10:24.333+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-07T11:10:24.333+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android oauth GData" /><title>Google Spreadsheets を Androidから扱う (4)</title><content type="html">&lt;a href="http://abekatsu.blogspot.com/2011/04/google-spreadsheets-android-3.html#links"&gt;前回&lt;/a&gt;，access Token と access TokenSecretを取得しました。
これを用いて，自分のアカウントのspread sheet一覧を取得してみます。&lt;br /&gt;

&lt;a href="http://code.google.com/intl/ja/apis/spreadsheets/data/3.0/developers_guide.html#ListingSpreadsheets"&gt;Retrieving a list of spreadsheets&lt;/a&gt;を読みますと，

&lt;pre class="brush:bash"&gt;
https://spreadsheets.google.com/feeds/spreadsheets/private/full
&lt;/pre&gt;

に送信すれば，認証されたユーザのspreadsheetsのfeedを入手することができます。&lt;br /&gt;

具体的なコードは以下の通りです。

&lt;h4&gt;HttpTransporへの署名&lt;/h4&gt;
&lt;div id="content1"&gt;
&lt;pre class="brush:java"&gt;
String token = "your access token";
String tokenSecret = "your access tokenSecret";
HttpTransport transport = new ApacheHttpTransport();
OAuthParameters parameters = createOAuthParameters(token, tokenSecret);
parameters.signRequestsUsingAuthorizationHeader(transport);
getSpreadSheets(transport);
&lt;/pre&gt;
&lt;/div&gt;

各メソッドの内容は以下の通りです。
&lt;h5&gt;createOAuthParameters&lt;/h5&gt;
&lt;div id="content2"&gt;
&lt;pre class="brush:java"&gt;
public OAuthParameters createOAuthParameters(String token, String tokenSecret) {
    OAuthParameters authorizer = new OAuthParameters();
    authorizer.consumerKey = "anonymous";
    authorizer.signer = createOAuthSigner(tokenSecret);
    authorizer.token = token;
    return authorizer;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;h5&gt;createOAuthSigner&lt;/h5&gt;
&lt;div id="content3"&gt;
&lt;pre class="brush:java"&gt;
public OAuthHmacSigner createOAuthSigner(String tokenSecret) {
    OAuthHmacSigner signer = new OAuthHmacSigner();
    if (tokenSecret != null) {
        signer.tokenSharedSecret = tokenSecret;
    }
    signer.clientSharedSecret = "anonymous";
    return signer;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;h5&gt;getSpreadSheet&lt;/h5&gt;
&lt;div id="content4"&gt;
&lt;pre class="brush:java"&gt;
public void getSpreadSheets(HttpTransport transport) {
    // Set AtomParser
    AtomParser parser = new AtomParser();
    XmlNamespaceDictionary dictionary = new XmlNamespaceDictionary();
    dictionary.set("", Atom.ATOM_NAMESPACE);
    dictionary.set("docs", "http://schemas.google.com/docs/2007");
    dictionary.set("batch", "http://schemas.google.com/gdata/batch");
    dictionary.set("gd", "http://schemas.google.com/g/2005");
    dictionary.set("gd:etag", "W/&amp;quot;DEMCQHk7eSt7ImA9WhZSGUw.&amp;quot;");
    dictionary.set("openSearch", "http://a9.com/-/spec/opensearch/1.1/");
    dictionary.set("app", "http://www.w3.org/2007/app");
    parser.namespaceDictionary = dictionary;
    transport.addParser(parser);

    // Set Http Headers
    HttpHeaders headers = transport.defaultHeaders;
    headers.set("User-Agent", appname);
    headers.set("GData-Version", "3.0");

    HttpRequest request = transport.buildGetRequest();
    request.url = new GoogleUrl("https://spreadsheets.google.com/feeds/spreadsheets/private/full");
    try {
        HttpResponse response = request.execute();
        // null chekc していないので注意
        InputStreamReader inr = new InputStreamReader(response.getEntity().getContent()); 
        BufferedReader reader = new BufferedReader(inr, 256);
        while ((str = reader.readLine()) != null) {
            Log.d(TAG, line);
        }
        reader.close();
        inr.close();
    } catch (IOException e) {
        Log.e(TAG, e.getMessage());
        e.printStackTrace();
    }
}
&lt;/pre&gt;
&lt;/div&gt;

これを実行し，正常にHttpResponseが得られますと，以下のようなXML documentが得られます。
&lt;div id="content5"&gt;
&lt;pre class="brush:xml"&gt;
&amp;lt;?xml version='1.0' encoding='UTF-8'?&amp;gt;
&amp;lt;feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearch/1.1/' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/&amp;quot;DEMCQHk7eSt7ImA9WhZSGUw.&amp;quot;'&amp;gt;
  &amp;lt;id&amp;gt;https://spreadsheets.google.com/feeds/spreadsheets/private/full&amp;lt;/id&amp;gt;
  &amp;lt;updated&amp;gt;2011-04-04T11:27:41.701Z&amp;lt;/updated&amp;gt;
  &amp;lt;category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#spreadsheet'/&amp;gt;
  &amp;lt;title&amp;gt;Available Spreadsheets - Maskes(user's email address)&amp;lt;/title&amp;gt;
  &amp;lt;link rel='alternate' type='text/html' href='http://docs.google.com'/&amp;gt;
  &amp;lt;link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/spreadsheets/private/full'/&amp;gt;
  &amp;lt;link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/spreadsheets/private/full'/&amp;gt;
  &amp;lt;openSearch:totalResults&amp;gt;11&amp;lt;/openSearch:totalResults&amp;gt;
  &amp;lt;openSearch:startIndex&amp;gt;1&amp;lt;/openSearch:startIndex&amp;gt;
  &amp;lt;entry gd:etag='&amp;quot;BBQbQxQLQit7ImBr&amp;quot;'&amp;gt;
    &amp;lt;id&amp;gt;https://spreadsheets.google.com/feeds/spreadsheets/tRsAk0wSkUi4wCBZxOJITuw&amp;lt;/id&amp;gt;
    &amp;lt;updated&amp;gt;2011-04-04T04:52:59.849Z&amp;lt;/updated&amp;gt;
    &amp;lt;category scheme='http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#spreadsheet'/&amp;gt;
    &amp;lt;title&amp;gt;Hack For Japan Projects&amp;lt;/title&amp;gt;
    &amp;lt;content type='application/atom+xml;type=feed' src='https://spreadsheets.google.com/feeds/worksheets/tRsAk0wSkUi4wCBZxOJITuw/private/full'/&amp;gt;
    &amp;lt;link rel='http://schemas.google.com/spreadsheets/2006#tablesfeed' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/tRsAk0wSkUi4wCBZxOJITuw/tables'/&amp;gt;
    &amp;lt;link rel='alternate' type='text/html' href='https://spreadsheets.google.com/ccc?key=0Amb6cvTCzTQRdFJzQWswd1NrVWk0d0NCWnhPSklUdXc'/&amp;gt;
    &amp;lt;link rel='self' type='application/atom+xml' href='https://spreadsheets.google.com/feeds/spreadsheets/private/full/tRsAk0wSkUi4wCBZxOJITuw'/&amp;gt;
    &amp;lt;author&amp;gt;
      &amp;lt;name&amp;gt;Masked&amp;lt;/name&amp;gt;
      &amp;lt;email&amp;gt;Masked&amp;lt;/email&amp;gt;
    &amp;lt;/author&amp;gt;
  &amp;lt;/entry&amp;gt;
&amp;lt;/feed&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;

次回は，得られた XML Document の parse を行います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-3403108922022391862?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yCGuATosNc0A1ynyILCi8nPr6XE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yCGuATosNc0A1ynyILCi8nPr6XE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yCGuATosNc0A1ynyILCi8nPr6XE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yCGuATosNc0A1ynyILCi8nPr6XE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/EIHzBwXaI5c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/3403108922022391862/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=3403108922022391862" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/3403108922022391862?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/3403108922022391862?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/EIHzBwXaI5c/access-token-access-tokensecret-spread.html" title="Google Spreadsheets を Androidから扱う (4)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/04/access-token-access-tokensecret-spread.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIDQH8-fyp7ImA9WhZSGUs.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-161574939885575216</id><published>2011-04-05T09:29:00.001+09:00</published><updated>2011-04-05T09:32:51.157+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-05T09:32:51.157+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android oauth" /><title>Google Spreadsheets を Androidから扱う (3)</title><content type="html">&lt;p&gt;
&lt;a href="http://abekatsu.blogspot.com/2011/04/google-spreadsheets-android-2.html#links"&gt;前回&lt;/a&gt;，Appを認証した際に得られるoauth_verifierとoauth_tokenの値が返ってくることまで確認しました。
&lt;/p&gt;
&lt;p&gt;
今回は，これらの値と&lt;a href="http://abekatsu.blogspot.com/2011/03/google-spreadsheets-android-1.html#links"&gt;前々回&lt;/a&gt;，Request Toke取得途中に得られた，OAuthCredentialsResponseの値と一緒に，AccesssTokenを取得します。
&lt;/p&gt;

&lt;h4&gt;oauth_verifier, oauth_tokenの取得&lt;/h4&gt;
&lt;p&gt;
ブラウザからのcallback時に発行されるIntentの中のURIデータを取得し，それをOAuthCallbackUrl に引き渡します。
&lt;/p&gt;
&lt;p&gt;
&lt;div id="content1"&gt;
&lt;pre class="brush:java"&gt;
Uri uri = this.getIntent().getData();
OAuthCallbackUrl callbackUrl;
if (uri != null) {
    Log.d(TAG, "uri: " + uri.toString());
    callbackUrl = new OAuthCallbackUrl(uri.toString());
}
&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;h4&gt;GoogleOAuthGetAccessTokenの作成&lt;/h4&gt;
&lt;p&gt;
上で作成した，OAuthCallbackUrl callbackUrl と，Request Token取得時に得られた
OAuthCredentialsResponse credentials (Request Token)を用いて &lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.3.1-alpha/index.html"&gt;GoogleOAuthGetAccessToken&lt;/a&gt; を作成します。
&lt;/p&gt;
&lt;p&gt;
&lt;div id="content2"&gt;
&lt;pre class="brush:java"&gt;
    HttpTransport transport = new ApacheHttpTransport();
    GoogleOAuthGetAccessToken accessToken = new GoogleOAuthGetAccessToken();
    accessToken.transport = transport;
    accessToken.temporaryToken = callbackUrl.token;
    accessToken.verifier = callbackUrl.verifier;
    accessToken.signer = createOAuthSigner(credentials);
    accessToken.consumerKey = "anonymous";
&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;h4&gt;Access Tokenの取得&lt;/h4&gt;
&lt;p&gt;
GoogleOAuthGetAccessToken accessTokenをexecute()することによって，Access Tokenを取得します。
&lt;/p&gt;
&lt;p&gt;
&lt;div id="content3"&gt;
&lt;pre class="brush:java"&gt;

    OAuthCredentialsResponse response = accessToken.execute();

&lt;/pre&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;
この返り値 OAuthCredentialsResponse response に含まれている，
(access) 
&lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.3.1-alpha/com/google/api/client/auth/oauth/OAuthCredentialsResponse.html#token"&gt;token&lt;/a&gt;
と(access)
&lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.3.1-alpha/com/google/api/client/auth/oauth/OAuthCredentialsResponse.html#tokenSecret"&gt;tokenSecret&lt;/a&gt;
が，今後Spreadsheetsにアクセスするための認可されたHTTP requestを生成する際に必要となります。
&lt;/p&gt;
&lt;p&gt;
次回は，自分のアカウントのSpreadSheet一覧を取得します。
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-161574939885575216?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vXcdGsA_izIEJ2lq7hD9FbSfKGw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vXcdGsA_izIEJ2lq7hD9FbSfKGw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vXcdGsA_izIEJ2lq7hD9FbSfKGw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vXcdGsA_izIEJ2lq7hD9FbSfKGw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/ptEwOxWVjA0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/161574939885575216/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=161574939885575216" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/161574939885575216?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/161574939885575216?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/ptEwOxWVjA0/google-spreadsheets-android-3.html" title="Google Spreadsheets を Androidから扱う (3)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/04/google-spreadsheets-android-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UGQnY5fCp7ImA9WhZSGEo.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-6071642487726015351</id><published>2011-04-04T10:03:00.001+09:00</published><updated>2011-04-04T10:07:03.824+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-04T10:07:03.824+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android oauth GData" /><title>Google Spreadsheets を Androidから扱う (2)</title><content type="html">OAuthの続きです。

&lt;h4&gt;Implict intent&lt;/h4&gt;

&lt;a href="http://developer.android.com/guide/topics/intents/intents-filters.html#ifs"&gt;androidには，intentでactivity, service, broadcastに応答させる昨日があります。&lt;/a&gt;この機能を利用して，Browser上でリンクをクリックして，インストールされているactivityを起動する方法があります。 &lt;br /&gt;

とくに，
&lt;blockquote&gt; 
Consider, for example, what the browser
application does when the user follows a link on a web page. It first
tries to display the data (as it could if the link was to an HTML
page). If it can't display the data, it puts together an implicit
intent with the scheme and data type and tries to start an activity
that can do the job. If there are no takers, it asks the download
manager to download the data. That puts it under the control of a
content provider, so a potentially larger pool of activities (those
with filters that just name a data type) can respond. 
&lt;/blockquote&gt;
とありますように，ブラウザでWebページ上のリンクをクリックして，
データが表示されない場合，該当する暗黙のintentを発行するようになっています。

OAuth認証では，この機能を利用して，callback urlに自分のアプリを起動できるようなurlを指定します。&lt;br /&gt;

&lt;a href="http://code.google.com/p/io2010-buzzjava/"&gt;Google I/O 2010 Buzz Android Sample for Java Client Library for Google API's version 2.2.0-alpha&lt;/a&gt;の実装を参考にして，話を進めていきます。&lt;br /&gt;

&lt;h4&gt;Request Token (Temporary credentials token) の取得&lt;/h4&gt;
&lt;a href="http://abekatsu.blogspot.com/2011/03/google-spreadsheets-android-1.html#links"&gt;前回&lt;/a&gt;，GoogleOAuthAuthorizeTemporaryTokenUrlを作成いたしましたが，その補足です。&lt;br /&gt;
Request Tokenを取得するために，&lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.3.1-alpha/index.html"&gt;GoogleOAuthGetTemporaryToken&lt;/a&gt;を利用します。&lt;br /&gt;
&lt;div id="content1"&gt;
&lt;pre class="brush:java"&gt;
    GoogleOAuthGetTemporaryToken temporaryToken = new GoogleOAuthGetTemporaryToken();
    OAuthHmacsinger signer = new OAuthHmacSigner();
    signer.clientSharedSecret = "anonymous";
    temporaryToken.signer = signer;
    temporaryToken.displayName = appname;
    temporaryToken.consumerKey = "anonymous";
    temporaryToken.scope = "https://spreadsheets.google.com/feeds/";
    temporaryToken.transport = transport;
    temporaryToken.callback = "x-myspreadsheet://com.example.abekatsu/";
&lt;/pre&gt;
&lt;/div&gt;
前回との違いは，callbackの指定です。&lt;a href="http://stackoverflow.com/questions/3469908/make-a-link-in-the-android-browser-start-up-my-app/3472228#3472228"&gt;custom schemeを使うな&lt;/a&gt;という意見がありますが，custom schemeを用いたアプリの起動が広まっている現状を踏まえ，今回は利用します。&lt;br /&gt;
競合を避けるために，host部分をjavaのpackage名のように，自分自身のFQDNをTop levelから書いてみました。&lt;br /&gt;

&lt;h4&gt;GoogleOAuthAuthorizeTemporaryTokenUrlの作成&lt;/h4&gt;
&lt;div id="content2"&gt;
&lt;pre class="brush:java"&gt;
    OAuthCredentialsResponse response = temporaryToken.execute();
    GoogleOAuthAuthorizeTemporaryTokenUrl authorizeUrl = new GoogleOAuthAuthorizeTemporaryTokenUrl();
    authorizeUrl.template = "mobile";
    authorizeUrl.set("scope", scope);
    authorizeUrl.set("domain", "anonymous");
    authorizeUrl.set("xoauth_displayname", appname);
    authorizeUrl.temporaryToken = response.token;
&lt;/pre&gt;
&lt;/div&gt;
この authorizeUrl で得られるURLを引数にしてブラウザを起動します。

&lt;div id="content3"&gt;
&lt;pre class="brush:java"&gt;
     Intent intent = new Intent(Intent.ACTION_VIEW);
     intent.setData(Uri.parse(temporaryTokenUrl.build()));
     startActivity(intent);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-jM6FfsvKvsQ/TZkXXbV_oUI/AAAAAAAAB9o/abKO1hWOJcE/s1600/device_20110331_02.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="320" width="192" src="http://4.bp.blogspot.com/-jM6FfsvKvsQ/TZkXXbV_oUI/AAAAAAAAB9o/abKO1hWOJcE/s320/device_20110331_02.png" /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;br /&gt;
実際に実行しますと，GoogleのAccountページが表示されます。ここで，「Grant access」をクリックすると，上記のcallbackで指定したURLを含む暗黙のIntentが発行されます。
&lt;/p&gt;

&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;


&lt;h4&gt;暗黙のIntentの取得&lt;/h4&gt;
先程のステップで得られた，暗黙のIntentを取得してみましょう。
&lt;h5&gt;AndroidManifest.xml&lt;/h5&gt;
まずは，AndroidManifest.xmlで，このIntentを補足するように指定します。
&lt;div id="content4"&gt;
&lt;pre class="brush:xml"&gt;
    &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;
        &lt;activity android:name=".MyActivity"
                  android:label="@string/app_name"&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.MAIN" /&gt;
                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
            &lt;/intent-filter&gt;
            &lt;!-- 追加部分 --&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.VIEW" /&gt;
                &lt;category android:name="android.intent.category.DEFAULT" /&gt;
                &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
                &lt;data android:scheme="x-myspreadsheet" 
                      android:host="com.example.abekatsu" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;
    &lt;/application&gt;
&lt;/pre&gt;
&lt;/div&gt;
暗黙のIntentでは，カテゴリーが "android.intent.category.DEFAULT" となります。
&lt;h5&gt;Activityの編集&lt;/h5&gt;
ここでは，単純に Intent に含まれているデータを表示させてみます。
&lt;div id="content5"&gt;
&lt;pre class="brush:xml"&gt;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        boolean isViewAction = Intent.ACTION_VIEW.equals(getIntent().getAction());
        if (isViewAction) {
            Uri uri = this.getIntent().getData();
            if (uri != null) {
                Log.d(TAG, "uri: " + uri.toString());
            }
        }
    }
&lt;/pre&gt;
&lt;/div&gt;

実際に，アプリケーションを実行して Grant access すると次のデータを含む
暗黙のIntentが発行されます。

&lt;div id="content5"&gt;
&lt;pre class="brush:bash"&gt;
D/OkodukaiNoteActivity(  235): uri: x-okozukai:///?oauth_verifier=ここにoauth_verifierの文字列&amp;oauth_token=ここにoauth_tokenの文字列
&lt;/pre&gt;
&lt;/div&gt;

次回はこのauth_tokenをGoogleにauthorizeします。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-6071642487726015351?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bWB-dDH4ImvKI2fsMRgq_oQa2fc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bWB-dDH4ImvKI2fsMRgq_oQa2fc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bWB-dDH4ImvKI2fsMRgq_oQa2fc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bWB-dDH4ImvKI2fsMRgq_oQa2fc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/frAfisks2wE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/6071642487726015351/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=6071642487726015351" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6071642487726015351?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6071642487726015351?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/frAfisks2wE/google-spreadsheets-android-2.html" title="Google Spreadsheets を Androidから扱う (2)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-jM6FfsvKvsQ/TZkXXbV_oUI/AAAAAAAAB9o/abKO1hWOJcE/s72-c/device_20110331_02.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/04/google-spreadsheets-android-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEINRX0zeSp7ImA9WhZSGUs.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-623686898553602491</id><published>2011-03-30T15:48:00.001+09:00</published><updated>2011-04-05T09:16:34.381+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-05T09:16:34.381+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android oauth GData" /><title>Google Spreadsheets を Androidから扱う (1)</title><content type="html">&lt;p&gt;
Androidアプリで扱うデータを外部のSpreadsheetに保存することを目的とします。
&lt;h4&gt;library&lt;/h4&gt;
今回は&lt;a href="http://code.google.com/p/google-api-java-client/"&gt;Google API Client Library for Java&lt;/a&gt;の1.3.1-alphaを使ってみます。&lt;br /&gt;
とりあえず，プロジェクトに次の3つのjarファイルを参照するように設定いたしました。
&lt;ul&gt;
  &lt;li&gt;google-api-client-1.3.1-alpha.jar
  &lt;li&gt;google-api-client-googleapis-1.3.1-alpha.jar
  &lt;li&gt;dependencies/guava-r08.jar
&lt;/ul&gt;
google-api-client-extensions-1.3.1-alpha.jarは Google App Engine用なので，今回は含めません。依存関係は試行錯誤の結果です。dependecies以下のjar(soruceは除く)を予め含めた方が今後楽かもしれません。 

&lt;h4&gt;認証&lt;/h4&gt;
Spreadsheetなど扱う前に，アプリケーションへ認証を与えることが必要になります。
ここではOAuthを用いた認証を行います。&lt;br /&gt;

具体的な手順は，&lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.2.0-alpha/com/google/api/client/googleapis/auth/oauth/package-summary.html"&gt;
OAuth 1.0a for Google API's JavaDoc&lt;/a&gt;に記載されています。&lt;br /&gt;

まずは，temporary credentials token ("request token") を入手します。
installed application では signature method に "HMAC-SHA1"，consumerKeyとclientSharedSecretに"anonymos"を使うように求められていますので，それに従います。
&lt;div id="content1"&gt;
&lt;pre class="brush:java"&gt;
    HttpTransport transport = new ApacheHttpTransport();
    GoogleOAuthGetTemporaryToken temporaryToken = new GoogleOAuthGetTemporaryToken();
    OAuthHmacsinger signer = new OAuthHmacSigner();
    signer.clientSharedSecret = "anonymous";
    temporaryToken.signer = signer;
    temporaryToken.displayName = appname;
    temporaryToken.consumerKey = "anonymous";
    temporaryToken.scope = "https://spreadsheets.google.com/feeds/";
    temporaryToken.transport = transport;
&lt;/pre&gt;
&lt;/div&gt;
displayNameには，このアプリケーションの名前(String 型)を入れます。scopeに入るべき値は，&lt;a href="http://code.google.com/intl/ja/apis/gdata/faq.html#AuthScopes"&gt;Google Data Protocol FAQ&lt;/a&gt;を参照してください。 &lt;br /&gt;

それでは，TemporaryTokenの値を入手してみます。
&lt;div id="content2"&gt;
&lt;pre class="brush:java"&gt;
    OAuthCredentialsResponse credentials = temporaryToken.execute();
&lt;/pre&gt;
&lt;/div&gt;

戻り値のtoken値を利用して，&lt;a href="http://javadoc.google-api-java-client.googlecode.com/hg/1.2.0-alpha/index.html?com/google/api/client/googleapis/auth/oauth/GoogleOAuthGetTemporaryToken.html"&gt;GoogleOAuthAuthorizeTemoraryTokenUrl&lt;/a&gt;を作成します。これで，ユーザにアクセスしていただくurlが得られます。
&lt;div id="content3"&gt;
&lt;pre class="brush:java"&gt;
    if (credentials != null) {
        GoogleOAuthAuthorizeTemporaryTokenUrl temporaryTokenUrl = new GoogleOAuthAuthorizeTemporaryTokenUrl();
        temporaryTokenUrl.template = "mobile";
        temporaryTokenUrl.temporaryToken = credentials.token;
        // Uri uri = new Uri(temporaryTokenUrl.build());
        Log.d(TAG, "temoraryTokenUrl: " + temporaryTokenUrl.build());
    }
&lt;/pre&gt;
&lt;/div&gt;

実行すると， temoratyTokenUrl の値として，
&lt;div id="content4"&gt;
&lt;pre class="brush:bash"&gt;
https://www.google.com/accounts/OAuthAuthorizeToken?btmpl=mobile&amp;oauth_token=...some_oauth_token....
&lt;/pre&gt;
&lt;/div&gt;
が得られました。&lt;br /&gt;

この次は，このURLをWebViewに表示させまして，アプリケーションの認証を行います。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-623686898553602491?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vvEEADnqNXE5AWQbklSfDe8ySpc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vvEEADnqNXE5AWQbklSfDe8ySpc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vvEEADnqNXE5AWQbklSfDe8ySpc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vvEEADnqNXE5AWQbklSfDe8ySpc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/4f0tNY2kRIs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/623686898553602491/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=623686898553602491" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/623686898553602491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/623686898553602491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/4f0tNY2kRIs/google-spreadsheets-android-1.html" title="Google Spreadsheets を Androidから扱う (1)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/03/google-spreadsheets-android-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QASXk_fyp7ImA9WhZSEkQ.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-9032555027858034457</id><published>2011-03-28T15:55:00.000+09:00</published><updated>2011-03-28T15:55:48.747+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-28T15:55:48.747+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>ContentProviderのテストの仕方</title><content type="html">&lt;p&gt;
今回，BottomPriceProvider というContentProviderの単体テストを行なう BottomPrivceProviderTest を作成してみましたので，そのメモを記していきます。
&lt;/p&gt;

&lt;h4&gt;クラスの作成&lt;/h4&gt;
&lt;a href="http://developer.android.com/reference/android/test/ProviderTestCase2.html"&gt;ProviderTestCase2&amp;gt;T extends android.content.ContentProvider&amp;lt;&lt;/a&gt;を継承して作成します。 &lt;br /&gt;

&lt;div id='content1'&gt;
&lt;pre class='brush:java'&gt;
public class BottomPriceProviderTest extends ProviderTestCase2&lt;BottomPriceProvider&gt; {
...
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;h4&gt;コンストラクタの生成&lt;/h4&gt;
super class から コンストラクタを自動生成すると，次のようなコードが生成されます。
&lt;div id='content2'&gt;
&lt;pre class='brush:java'&gt;
 public BottomPriceProviderTest(Class&lt;BottomPriceProvider&gt; providerClass,
            String providerAuthority) {
        super(providerClass, providerAuthority);
        // TODO Auto-generated constructor stub
    }
&lt;/pre&gt;
&lt;/div&gt;

面倒なので，引数を指定しない版も作成しておきます。
&lt;div id='content3'&gt;
&lt;pre class='brush:java'&gt;
 public BottomPriceProviderTest() {
        super(BottomPriceProvider.class, BottomPriceProvider.AUTHORITY);
        // TODO Auto-generated constructor stub
    }
&lt;/pre&gt;
&lt;/div&gt;

ここでの，BottomPriceProvider.AUTHORITY は ContentProviderを提供する際に指定するContentのAuthority名です。&lt;br /&gt;

&lt;h4&gt;setUp, tearDown&lt;/h4&gt;
setUpでは，フィールド mMockContext に&lt;a href="http://developer.android.com/reference/android/test/ProviderTestCase2.html#getMockContext()"&gt;getMockContext()&lt;/a&gt;で得られるContextを格納しておきます。 &lt;br /&gt;
tearDownでは特になにもしません。
&lt;div id='content4'&gt;
&lt;pre class='brush:java'&gt;
    private Context mMockContext;
    @Override
    protected void setUp() throws Exception {
        // TODO Auto-generated method stub
        super.setUp();
        mMockContext = getMockContext();
    }

    @Override
    protected void tearDown() throws Exception {
        // TODO Auto-generated method stub
        super.tearDown();
    }
&lt;/pre&gt;    
&lt;/div&gt;

&lt;h4&gt;テスト&lt;/h4&gt;
まずは簡単なところで，insert/query/deleteのテストを書いてみます。
テスト用の&lt;a href="http://developer.android.com/reference/android/content/ContentValues.html"&gt;ContentValues&lt;/a&gt;を挿入，検索し，その検索結果が挿入したContentValuesの内容と一致することを確認し，最後にテスト用ContentValuesを削除します。
&lt;div id='content4'&gt;
&lt;pre class='brush:java'&gt;
    public void testInsertDeleteRecord() {
        final ContentResolver resolver = mMockContext.getContentResolver();
        final Uri uri = BottomPrice.Prices.CONTENT_URI;
        ContentValues cv = new ContentValues();
        int price = 480;
        String jan_code_str = "4901111725133";
        cv.put(BottomPrice.Prices.PRICE, price);
        cv.put(BottomPrice.Prices.JAN_CODE, jan_code_str);
        Uri insertUri = resolver.insert(uri, cv);
        String price_id = insertUri.getPathSegments().get(1);
        
        // Query
        Uri queryUri = Uri.withAppendedPath(uri, price_id);
        String[] projection = new String[] {
                BottomPrice.Prices._ID,
                BottomPrice.Prices.PRICE,
                BottomPrice.Prices.JAN_CODE,
            };
        Cursor c = resolver.query(queryUri, projection, null, null, null);
        assertEquals("query resuult", 1, c.getCount());
        c.moveToFirst();
        assertEquals("Jan Code", jan_code_str, c.getString(c.getColumnIndex(BottomPrice.Prices.JAN_CODE)));
        assertEquals("Price", price, c.getInt(c.getColumnIndex(BottomPrice.Prices.PRICE)));
        c.close();
        
        resolver.delete(queryUri, null, null);
    }
&lt;/pre&gt;
&lt;/div&gt;


&lt;h4&gt;&lt;/h4&gt;
実際にテストを実行してみましょう。

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/--XiJXCypSF4/TZAsAURe2uI/AAAAAAAAB9Y/6fPAG1Qld8A/s1600/screen_2011032801.jpg" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="182" width="320" src="http://2.bp.blogspot.com/--XiJXCypSF4/TZAsAURe2uI/AAAAAAAAB9Y/6fPAG1Qld8A/s320/screen_2011032801.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;



テスト Errorとなり，Failure Trace をみると
&lt;div id='content5'&gt;
&lt;pre class='brush:java'&gt;
android.database.SQLException: Failed to insert row into content://com.damburisoft.android.app.bottomrpice.provider.bottompriceprovider/prices
at com.damburisoft.android.app.bottomrpice.provider.BottomPriceProvider.insert(BottomPriceProvider.java:107)
at android.content.ContentProvider$Transport.insert(ContentProvider.java:150)
at android.content.ContentResolver.insert(ContentResolver.java:629)
at com.damburisoft.android.provider.BottomPriceProviderTest.testInsertDeleteRecord(BottomPriceProviderTest.java:50)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
&lt;/pre&gt;
&lt;/div&gt;

とあるので，これを直していくことによって自分のContentProviderを創り上げていきます。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-9032555027858034457?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/F0GnQ_wXO9Y2aY6eLMic4szAt4c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/F0GnQ_wXO9Y2aY6eLMic4szAt4c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/F0GnQ_wXO9Y2aY6eLMic4szAt4c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/F0GnQ_wXO9Y2aY6eLMic4szAt4c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/i_HTizqgyGo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/9032555027858034457/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=9032555027858034457" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/9032555027858034457?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/9032555027858034457?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/i_HTizqgyGo/contentprovider.html" title="ContentProviderのテストの仕方" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/--XiJXCypSF4/TZAsAURe2uI/AAAAAAAAB9Y/6fPAG1Qld8A/s72-c/screen_2011032801.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/03/contentprovider.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcHQng-eCp7ImA9WhZSEk4.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-7807529704864962732</id><published>2011-03-27T22:20:00.000+09:00</published><updated>2011-03-27T22:20:33.650+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-27T22:20:33.650+09:00</app:edited><title>今後の方針 (Mar/27/2011 version)</title><content type="html">&lt;p&gt;
自分の方針というのを決めていこうと考える。ただ，一度決めた物絶対ということではなく，何度も推敲を重ねていこうと。
&lt;ul&gt;
  &lt;li&gt; ◯◯とITを念頭に。ITの中だけで閉じることに何らかの疑問がある。ITを通して現実の世界にある問題を解決する手助けをしよう。
  &lt;li&gt; 80%の力で&lt;br /&gt; 重要な時に歯を食いしばるのはいいが，常に歯を食いしばっている状況はおかしいはず。全力で90分フルに走れるフットボール選手はいないように，要素要素で力を抜けるように。
  &lt;li&gt; 人は迷惑をかけて生きている。迷惑をかけているかどうか気にしない。自分が無理なく生きていくためにやれることをまず探す。
&lt;/ul&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-7807529704864962732?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Pnab3d7G6sR8BB4RGyLRoMmfbYw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Pnab3d7G6sR8BB4RGyLRoMmfbYw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Pnab3d7G6sR8BB4RGyLRoMmfbYw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Pnab3d7G6sR8BB4RGyLRoMmfbYw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/Ef6D9yZs8Q0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/7807529704864962732/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=7807529704864962732" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7807529704864962732?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7807529704864962732?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/Ef6D9yZs8Q0/mar272011-version.html" title="今後の方針 (Mar/27/2011 version)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/03/mar272011-version.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QGSXc4fSp7ImA9Wx9VE0U.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-7117082585071829405</id><published>2011-01-30T19:50:00.003+09:00</published><updated>2011-01-30T20:02:08.935+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-30T20:02:08.935+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="taintdroid" /><title>taintdroid code reading 3.</title><content type="html">&lt;p&gt;
I read a diff of services/java/com/android/server/LocationManagerService.java. &lt;br /&gt;
It is almost the same as the diff of telephony.
When location update message is received, the location is stored in Taint object as following:
&lt;pre&gt;
&lt;code&gt;
location.setLatitude(Taint.addTaintDouble(location.getLatitude(), tag));
&lt;/code&gt;
&lt;/pre&gt;
But I cannot understand the reason why obtained value is set again, that is, 
why setLatitude is called. &lt;br /&gt;
And the other point I cannot understand is that how to distinguish the values. For example,
the below is a code to store latitude and location.
&lt;pre&gt;
&lt;code&gt;
    location.setLatitude(Taint.addTaintDouble(location.getLatitude(), tag));
    location.setLongitude(Taint.addTaintDouble(location.getLongitude(), tag));
&lt;/code&gt;
&lt;/pre&gt;
where tag is given here as following:
&lt;pre&gt;
&lt;code&gt;
    int tag = Taint.TAINT_LOCATION;
    if (LocationManager.GPS_PROVIDER.equals(provider)) {
        tag |= Taint.TAINT_LOCATION_GPS;
    }
    if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
        tag |= Taint.TAINT_LOCATION_NET;
    }
&lt;/code&gt;
&lt;/pre&gt;
Latitude and Longitude are added by addTaingDouble, but I cannot see how to distinguish latitude and longitude. &lt;br /&gt;

I paste the whole diff below. 
&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index bbb43d7..4a5846a 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -68,6 +68,10 @@ import com.android.internal.location.LocationProviderProxy;
 import com.android.internal.location.MockProvider;
 import com.android.internal.location.GpsNetInitiatedHandler;
 
+// begin WITH_TAINT_TRACKING
+import dalvik.system.Taint;
+// end WITH_TAINT_TRACKING
+
 /**
  * The service class that manages LocationProviders and issues location
  * updates and alerts.
@@ -1526,6 +1530,30 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
                         Location location = (Location) msg.obj;
                         String provider = location.getProvider();
 
+   // begin WITH_TAINT_TRACKING
+   int tag = Taint.TAINT_LOCATION;
+   if (LocationManager.GPS_PROVIDER.equals(provider)) {
+       tag |= Taint.TAINT_LOCATION_GPS;
+   }
+   if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
+       tag |= Taint.TAINT_LOCATION_NET;
+   }
+   location.setLatitude(Taint.addTaintDouble(location.getLatitude(), tag));
+   location.setLongitude(Taint.addTaintDouble(location.getLongitude(), tag));
+   if (location.hasAltitude()) {
+       location.setAltitude(Taint.addTaintDouble(location.getAltitude(), tag));
+   }    
+   if (location.hasSpeed()) {
+       location.setSpeed(Taint.addTaintFloat(location.getSpeed(), tag));
+   }    
+   if (location.hasBearing()) {
+       location.setBearing(Taint.addTaintFloat(location.getBearing(), tag));
+   }    
+   if (location.hasAccuracy()) {
+       location.setAccuracy(Taint.addTaintFloat(location.getAccuracy(), tag));
+   }    
+   // end WITH_TAINT_TRACKING
+
                         // notify other providers of the new location
                         for (int i = mProviders.size() - 1; i &gt;= 0; i--) {
                             LocationProviderProxy proxy = mProviders.get(i);
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;
Also, the diff of location/java/com/android/internal/location/GpsLocationProvider.java is almost the same handling as LocationManagerService.java, that is, when location updated message is received, the values are set in Taint object.
&lt;/p&gt;
&lt;p&gt;
Next, I'll read the diff for media.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-7117082585071829405?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aMJ-BRcA9IYym4r_Bs0CpdgDb68/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aMJ-BRcA9IYym4r_Bs0CpdgDb68/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aMJ-BRcA9IYym4r_Bs0CpdgDb68/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aMJ-BRcA9IYym4r_Bs0CpdgDb68/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/pUkIpVz2w4c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/7117082585071829405/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=7117082585071829405" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7117082585071829405?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7117082585071829405?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/pUkIpVz2w4c/taintdroid-code-reading-3.html" title="taintdroid code reading 3." /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/taintdroid-code-reading-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkMEQnY-cCp7ImA9Wx9VE0o.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-1592707163584701777</id><published>2011-01-30T17:00:00.000+09:00</published><updated>2011-01-30T17:00:03.858+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-30T17:00:03.858+09:00</app:edited><title>taintdroid code reading 2.</title><content type="html">These are diffs for framework/base/telephony.

&lt;pre&gt;
&lt;code&gt;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index a5188ce..78904c5 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -78,6 +78,10 @@ import java.net.Socket;
 import java.util.ArrayList;
 import java.util.List;
 
+// begin WITH_TAINT_TRACKING
+import dalvik.system.Taint;
+// end WITH_TAINT_TRACKING
+
 /**
  * {@hide}
  */
@@ -1276,6 +1280,9 @@ public class GSMPhone extends PhoneBase {
                 }
 
                 mImei = (String)ar.result;
+  // begin WITH_TAINT_TRACKING
+  Taint.addTaintString(mImei, Taint.TAINT_IMEI);
+  // end WITH_TAINT_TRACKING
             break;
 
             case EVENT_GET_IMEISV_DONE:
&lt;/code&gt;
&lt;/pre&gt;

&lt;p&gt;
This diff is to store IMEI number to Taint object.
Taint.addTaintString(mImei, Taint.TAINT_IMEI);&lt;/code&gt; is called in public void setMsisdnNumber(String alphaTag, String number,  Message onComplete).
&lt;/p&gt;

&lt;pre&gt;
&lt;code&gt;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index d711a80..6beee1b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -38,6 +38,9 @@ import com.android.internal.telephony.MccTable;
 
 import java.util.ArrayList;
 
+// begin WITH_TAINT_TRACKING
+import dalvik.system.Taint;
+// end WITH_TAINT_TRACKING
 
 /**
  * {@hide}
@@ -236,6 +239,9 @@ public final class SIMRecords extends IccRecords {
             Message onComplete) {
 
         msisdn = number;
+ // begin WITH_TAINT_TRACKING
+ Taint.addTaintString(msisdn, Taint.TAINT_PHONE_NUMBER);
+ // end WITH_TAINT_TRACKING
         msisdnTag = alphaTag;
 
         if(DBG) log("Set MSISDN: " + msisdnTag +" " + msisdn);
@@ -488,6 +494,11 @@ public final class SIMRecords extends IccRecords {
                 }
 
                 imsi = (String) ar.result;
+  // begin WITH_TAINT_TRACKING
+  //if (imsi != null) {
+      //Taint.addTaintString(imsi, Taint.TAINT_IMSI);
+  //}
+  // end WITH_TAINT_TRACKING
 
                 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
                 // than 15 (and usually 15).
@@ -617,6 +628,9 @@ public final class SIMRecords extends IccRecords {
                 adn = (AdnRecord)ar.result;
 
                 msisdn = adn.getNumber();
+  // begin WITH_TAINT_TRACKING
+  Taint.addTaintString(msisdn, Taint.TAINT_PHONE_NUMBER);
+  // end WITH_TAINT_TRACKING
                 msisdnTag = adn.getAlphaTag();
&lt;/code&gt;
&lt;/pre&gt;

&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;
These changes stores IMEI, Phone number (ISDN) and ICCID in Taint object
&lt;/p&gt;

&lt;h3&gt;Quesion&lt;/h3&gt;
&lt;p&gt;
When are these values stored in Taint object?
&lt;/p&gt;

&lt;p&gt;
Next, I'll read services/java/com/android/server/LocationManagerService.java.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-1592707163584701777?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jmOxEGmpnrHeDiwthBDUxajrQEI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jmOxEGmpnrHeDiwthBDUxajrQEI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jmOxEGmpnrHeDiwthBDUxajrQEI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jmOxEGmpnrHeDiwthBDUxajrQEI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/4rrssTPiLRE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/1592707163584701777/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=1592707163584701777" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/1592707163584701777?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/1592707163584701777?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/4rrssTPiLRE/taintdroid-code-reading-2.html" title="taintdroid code reading 2." /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/taintdroid-code-reading-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYFQn47cCp7ImA9Wx9VE0s.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-1757820598902230374</id><published>2011-01-30T13:35:00.000+09:00</published><updated>2011-01-30T13:35:13.008+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-30T13:35:13.008+09:00</app:edited><title>taintdroid code reading 1.</title><content type="html">&lt;p&gt;
I am curious how &lt;a href="http://www.appanalysis.org/"&gt;taintdroid&lt;/a&gt; track apps which use senseitive information.&lt;br /&gt;
Firstly, I check the diff between taintdroid and android. &lt;br /&gt;
According to &lt;a href="http://appanalysis.org/download.html"&gt;TaintDroid Build Instructions&lt;/a&gt;, it modifies the source under dalvik/ and frameworks/base.
&lt;/p&gt;

&lt;p&gt;
We can obtain the list of modified files by:
&lt;pre&gt;
  git diff --name-only 0e9d568ec6b946e77bc0ec1903acac1ef916e6d1
&lt;/pre&gt;
for dalvik/, and
&lt;pre&gt;
  git diff --name-only 562ac30bddb37b8bebeedfb035111dda41187332.
&lt;/pre&gt;
for framework/base.
&lt;/p&gt;

&lt;p&gt;
The list for dalvik is too huge, is 456 files, so firstly we check one for framework/base.
&lt;blockquote&gt;
&lt;pre&gt;
&lt;code&gt;
README_TAINTDROID.txt
api/current.xml
cmds/servicemanager/Android.mk
cmds/servicemanager/binder.c
core/java/android/hardware/Camera.java
core/java/android/hardware/SensorManager.java
core/java/android/os/Parcel.java
core/jni/Android.mk
core/jni/android_util_Binder.cpp
include/binder/Parcel.h
libs/binder/Android.mk
libs/binder/Parcel.cpp
location/java/com/android/internal/location/GpsLocationProvider.java
media/java/android/media/AudioRecord.java
media/java/android/media/MediaRecorder.java
media/jni/Android.mk
media/jni/android_media_MediaRecorder.cpp
services/java/com/android/server/LocationManagerService.java
telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
&lt;/code&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
Next, I'll check what changes were made in services and telephont.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-1757820598902230374?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/laA8JKdAnnOS-Tofb5rr9IQYOoQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/laA8JKdAnnOS-Tofb5rr9IQYOoQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/laA8JKdAnnOS-Tofb5rr9IQYOoQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/laA8JKdAnnOS-Tofb5rr9IQYOoQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/9vQ4VNB9bqE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/1757820598902230374/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=1757820598902230374" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/1757820598902230374?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/1757820598902230374?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/9vQ4VNB9bqE/taintdroid-code-reading-1.html" title="taintdroid code reading 1." /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/taintdroid-code-reading-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYDQ3k4eyp7ImA9Wx9VE0g.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-916123273785385193</id><published>2011-01-30T11:09:00.001+09:00</published><updated>2011-01-30T11:22:52.733+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-30T11:22:52.733+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>repackage? android app</title><content type="html">&lt;p&gt;
&lt;a href="http://abekatsu.blogspot.com/2011/01/android-app.html#links"&gt;先日のblog article&lt;/a&gt;で署名を突破できないという指摘を受けました。当然の指摘です。署名を検証するアプリケーション配布サイトですと問題はないのでしょう。&lt;br /&gt;

結局は自分が浅はかであることを実感してソースコードがないandroid アプリをいじることができるかどうか，試してみました。ただ，既に知られている情報をただ単に追っただけなので，新規情報量はないです。&lt;br /&gt;

&lt;h4&gt;参考&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://kanatoko.wordpress.com/2011/01/21/android%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%83%AA%E3%83%90%E3%83%BC%E3%82%B9%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0/"&gt;Androidアプリケーションのリバースエンジニアリング&lt;/a&gt;
  &lt;li&gt;&lt;a href="http://code.google.com/p/smali/"&gt;smali - An assembler/disassembler for Android's dex format&lt;/a&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;
まずは，"Push Me"というボタンを押すと，Toastで"Hello World"というmessageを表示するアプリケーションを用意しました。

&lt;pre&gt;
&lt;code&gt;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b = (Button)findViewById(R.id.Button01);
    }

    private class ButtonOnClickListener implements View.OnClickListener {

        @Override
        public void onClick(View v) {
            if (v.getId() == R.id.Button01) {
                Toast.makeText(getApplicationContext(), "Hello World!", Toast.LENGTH_LONG).show();
            }
            
        }
    }
&lt;/code&gt;
&lt;/pre&gt;

一方，"Push Me"というボタンを押すと，Toastで"Hello World"というmessageを表示すると同時に，call_log を読むアプリケーションを用意しました。同様に，キーとなるコード部分を下に記しておきます。

&lt;pre&gt;
&lt;code&gt;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button b = (Button)findViewById(R.id.Button01);
        b.setOnClickListener(new ButtonOnClickListener());
    }

    private class ButtonOnClickListener implements View.OnClickListener {

        @Override
        public void onClick(View v) {
            if (v.getId() == R.id.Button01) {
                Toast.makeText(getApplicationContext(), "Hello World!", Toast.LENGTH_LONG).show();
                queryContentProvidersInfo();
            }
            
        }

        private void queryContentProvidersInfo() {
            String[] projections = new String[] {
                    CallLog.Calls._ID,
                    CallLog.Calls.NUMBER,
                    CallLog.Calls.TYPE,
                    CallLog.Calls.DURATION,
                    CallLog.Calls.DATE,
                    CallLog.Calls.CACHED_NAME,
            };
            
            Uri calls = CallLog.Calls.CONTENT_URI;
            ContentResolver cr = getContentResolver();
            Cursor c = cr.query(calls, projections, null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
            if (c != null) {
                getColumnData(c);
                c.close();
            }
        }

        private void getColumnData(Cursor c) {
            if (c.moveToFirst()) {
                String number;
                int numberColumn = c.getColumnIndex(CallLog.Calls.NUMBER);
                String cashed_name;
                int cashed_nameColumn = c.getColumnIndex(CallLog.Calls.NUMBER);
                do {
                    number = c.getString(numberColumn);
                    cashed_name = c.getString(cashed_nameColumn);
                    Log.d(TAG, "number: " + number);
                    if (cashed_name != null) {
                        Log.d(TAG, "cashed_name: " + cashed_name);
                    }
                } while (c.moveToNext());
            }
        }
    }
&lt;/code&gt;
&lt;/pre&gt;

apkから&lt;a href="http://code.google.com/p/smali/"&gt;baksmali&lt;/a&gt;を用いて，この部分の処理をdiassembleしたsmali型式コードを以下に貼り付けます。

単にmessageを表示する箇所。
&lt;pre&gt;
&lt;code&gt;
# virtual methods
.method public final onClick(Landroid/view/View;)V
    .registers 5

    invoke-virtual {p1}, Landroid/view/View;-&gt;getId()I

    move-result v0

    const/high16 v1, 0x7f05

    if-ne v0, v1, :cond_9b

    iget-object v0, p0, Lcom/damburisoft/app/android/helloworld/a;-&gt;a:Lcom/damburisoft/app/android/helloworld/HelloWorldActivity;

    invoke-virtual {v0}, Lcom/damburisoft/app/android/helloworld/HelloWorldActivity;-&gt;getApplicationContext()Landroid/content/Context;

    move-result-object v0

    const-string v1, "Hello World!"

    const/4 v2, 0x1

    invoke-static {v0, v1, v2}, Landroid/widget/Toast;-&gt;makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;-&gt;show()V

    :cond_9b
    return-void
.end method
&lt;/code&gt;
&lt;/pre&gt;

call_logを読む箇所。
&lt;pre&gt;
&lt;code&gt;
# virtual methods
.method public final onClick(Landroid/view/View;)V
    .registers 10

    const/4 v3, 0x0

    const/4 v4, 0x1

    const-string v7, "ReadInfo"

    const-string v6, "number"

    invoke-virtual {p1}, Landroid/view/View;-&gt;getId()I

    move-result v0

    const/high16 v1, 0x7f05

    if-ne v0, v1, :cond_9b

    iget-object v0, p0, Lcom/damburisoft/android/app/readinfo/a;-&gt;a:Lcom/damburisoft/android/app/readinfo/ReadInfo;

    invoke-virtual {v0}, Lcom/damburisoft/android/app/readinfo/ReadInfo;-&gt;getApplicationContext()Landroid/content/Context;

    move-result-object v0

    const-string v1, "Hello World!"

    invoke-static {v0, v1, v4}, Landroid/widget/Toast;-&gt;makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;-&gt;show()V

    const/4 v0, 0x6

    new-array v2, v0, [Ljava/lang/String;

    const/4 v0, 0x0

    const-string v1, "_id"

    aput-object v1, v2, v0

    const-string v0, "number"

    aput-object v6, v2, v4

    const/4 v0, 0x2

    const-string v1, "type"

    aput-object v1, v2, v0

    const/4 v0, 0x3

    const-string v1, "duration"

    aput-object v1, v2, v0

    const/4 v0, 0x4

    const-string v1, "date"

    aput-object v1, v2, v0

    const/4 v0, 0x5

    const-string v1, "name"

    aput-object v1, v2, v0

    sget-object v1, Landroid/provider/CallLog$Calls;-&gt;CONTENT_URI:Landroid/net/Uri;

    iget-object v0, p0, Lcom/damburisoft/android/app/readinfo/a;-&gt;a:Lcom/damburisoft/android/app/readinfo/ReadInfo;

    invoke-virtual {v0}, Lcom/damburisoft/android/app/readinfo/ReadInfo;-&gt;getContentResolver()Landroid/content/ContentResolver;

    move-result-object v0

    const-string v5, "date DESC"

    move-object v4, v3

    invoke-virtual/range {v0 .. v5}, Landroid/content/ContentResolver;-&gt;query(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;

    move-result-object v0

    if-eqz v0, :cond_9b

    invoke-interface {v0}, Landroid/database/Cursor;-&gt;moveToFirst()Z

    move-result v1

    if-eqz v1, :cond_98

    const-string v1, "number"

    invoke-interface {v0, v6}, Landroid/database/Cursor;-&gt;getColumnIndex(Ljava/lang/String;)I

    move-result v1

    const-string v2, "number"

    invoke-interface {v0, v6}, Landroid/database/Cursor;-&gt;getColumnIndex(Ljava/lang/String;)I

    move-result v2

    :cond_60
    invoke-interface {v0, v1}, Landroid/database/Cursor;-&gt;getString(I)Ljava/lang/String;

    move-result-object v3

    invoke-interface {v0, v2}, Landroid/database/Cursor;-&gt;getString(I)Ljava/lang/String;

    move-result-object v4

    const-string v5, "ReadInfo"

    new-instance v5, Ljava/lang/StringBuilder;

    const-string v6, "number: "

    invoke-direct {v5, v6}, Ljava/lang/StringBuilder;-&gt;&lt;init&gt;(Ljava/lang/String;)V

    invoke-virtual {v5, v3}, Ljava/lang/StringBuilder;-&gt;append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    invoke-virtual {v3}, Ljava/lang/StringBuilder;-&gt;toString()Ljava/lang/String;

    move-result-object v3

    invoke-static {v7, v3}, Landroid/util/Log;-&gt;d(Ljava/lang/String;Ljava/lang/String;)I

    if-eqz v4, :cond_92

    const-string v3, "ReadInfo"

    new-instance v3, Ljava/lang/StringBuilder;

    const-string v5, "cashed_name: "

    invoke-direct {v3, v5}, Ljava/lang/StringBuilder;-&gt;&lt;init&gt;(Ljava/lang/String;)V

    invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;-&gt;append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    invoke-virtual {v3}, Ljava/lang/StringBuilder;-&gt;toString()Ljava/lang/String;

    move-result-object v3

    invoke-static {v7, v3}, Landroid/util/Log;-&gt;d(Ljava/lang/String;Ljava/lang/String;)I

    :cond_92
    invoke-interface {v0}, Landroid/database/Cursor;-&gt;moveToNext()Z

    move-result v3

    if-nez v3, :cond_60

    :cond_98
    invoke-interface {v0}, Landroid/database/Cursor;-&gt;close()V

    :cond_9b
    return-void
.end method
&lt;/code&gt;
&lt;/pre&gt;

上記のsmali型式のコードを比較して，call_logの内容を読む処理を前者の単にToastでmessageを表示するアプリケーションに追加してみます。追加した結果のsmali型式ファイルは以下の通りです。

&lt;pre&gt;
&lt;code&gt;
# virtual methods
.method public final onClick(Landroid/view/View;)V
    .registers 10

    const/4 v3, 0x0

    const/4 v4, 0x1

    const-string v7, "ReadInfo"

    const-string v6, "number"

    invoke-virtual {p1}, Landroid/view/View;-&gt;getId()I

    move-result v0

    const/high16 v1, 0x7f05

    if-ne v0, v1, :cond_1b

    iget-object v0, p0, Lcom/damburisoft/app/android/helloworld/a;-&gt;a:Lcom/damburisoft/app/android/helloworld/HelloWorldActivity;

    invoke-virtual {v0}, Lcom/damburisoft/app/android/helloworld/HelloWorldActivity;-&gt;getApplicationContext()Landroid/content/Context;

    move-result-object v0

    const-string v1, "Hello World!"

    const/4 v2, 0x1

    invoke-static {v0, v1, v2}, Landroid/widget/Toast;-&gt;makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v0

    invoke-virtual {v0}, Landroid/widget/Toast;-&gt;show()V

    const/4 v0, 0x6

    new-array v2, v0, [Ljava/lang/String;

    const/4 v0, 0x0

    const-string v1, "_id"

    aput-object v1, v2, v0

    const-string v0, "number"

    aput-object v6, v2, v4

    const/4 v0, 0x2

    const-string v1, "type"

    aput-object v1, v2, v0

    const/4 v0, 0x3

    const-string v1, "duration"

    aput-object v1, v2, v0

    const/4 v0, 0x4

    const-string v1, "date"

    aput-object v1, v2, v0

    const/4 v0, 0x5

    const-string v1, "name"

    aput-object v1, v2, v0

    sget-object v1, Landroid/provider/CallLog$Calls;-&gt;CONTENT_URI:Landroid/net/Uri;

    iget-object v0, p0, Lcom/damburisoft/app/android/helloworld/a;-&gt;a:Lcom/damburisoft/app/android/helloworld/HelloWorldActivity;

    invoke-virtual {v0}, Lcom/damburisoft/app/android/helloworld/HelloWorldActivity;-&gt;getContentResolver()Landroid/content/ContentResolver;

    move-result-object v0

    const-string v5, "date DESC"

    move-object v4, v3

    invoke-virtual/range {v0 .. v5}, Landroid/content/ContentResolver;-&gt;query(Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;

    move-result-object v0

    if-eqz v0, :cond_1b

    invoke-interface {v0}, Landroid/database/Cursor;-&gt;moveToFirst()Z

    move-result v1

    if-eqz v1, :cond_18

    const-string v1, "number"

    invoke-interface {v0, v6}, Landroid/database/Cursor;-&gt;getColumnIndex(Ljava/lang/String;)I

    move-result v1

    const-string v2, "number"

    invoke-interface {v0, v6}, Landroid/database/Cursor;-&gt;getColumnIndex(Ljava/lang/String;)I

    move-result v2

    :cond_60
    invoke-interface {v0, v1}, Landroid/database/Cursor;-&gt;getString(I)Ljava/lang/String;

    move-result-object v3

    invoke-interface {v0, v2}, Landroid/database/Cursor;-&gt;getString(I)Ljava/lang/String;

    move-result-object v4

    const-string v5, "ReadInfo"

    new-instance v5, Ljava/lang/StringBuilder;

    const-string v6, "number: "

    invoke-direct {v5, v6}, Ljava/lang/StringBuilder;-&gt;&lt;init&gt;(Ljava/lang/String;)V

    invoke-virtual {v5, v3}, Ljava/lang/StringBuilder;-&gt;append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    invoke-virtual {v3}, Ljava/lang/StringBuilder;-&gt;toString()Ljava/lang/String;

    move-result-object v3

    invoke-static {v7, v3}, Landroid/util/Log;-&gt;d(Ljava/lang/String;Ljava/lang/String;)I

    if-eqz v4, :cond_92

    const-string v3, "ReadInfo"

    new-instance v3, Ljava/lang/StringBuilder;

    const-string v5, "cashed_name: "

    invoke-direct {v3, v5}, Ljava/lang/StringBuilder;-&gt;&lt;init&gt;(Ljava/lang/String;)V

    invoke-virtual {v3, v4}, Ljava/lang/StringBuilder;-&gt;append(Ljava/lang/String;)Ljava/lang/StringBuilder;

    move-result-object v3

    invoke-virtual {v3}, Ljava/lang/StringBuilder;-&gt;toString()Ljava/lang/String;

    move-result-object v3

    invoke-static {v7, v3}, Landroid/util/Log;-&gt;d(Ljava/lang/String;Ljava/lang/String;)I

    :cond_92
    invoke-interface {v0}, Landroid/database/Cursor;-&gt;moveToNext()Z

    move-result v3

    if-nez v3, :cond_60

    :cond_18
    invoke-interface {v0}, Landroid/database/Cursor;-&gt;close()V

    :cond_1b
    return-void
.end method
&lt;/code&gt;
&lt;/pre&gt;

さて，この編集した.smaliファイルでclasses.dexをアセンブルして，HelloWorld.apkのclasses.dexに入れ替えます。
&lt;pre&gt;
% java -Xmx1G -jar ~/lib/smali-1.2.6.jar -o classes.dex out
% zip ~/HelloWorldApp.apk classes.dex
&lt;/pre&gt;

classed.dexを入れ替えたHelloWorld.apkをもう一度署名しなおして，emulatorにインストールしてみました。実行した結果，SecurityExceptionが発生しました。
&lt;pre&gt;
&lt;code&gt;
E/AndroidRuntime(  251): java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.CallLogProvider uri content://call_log/calls from pid=251, uid=10041 requires android.permission.READ_CONTACTS
E/AndroidRuntime(  251):  at android.os.Parcel.readException(Parcel.java:1247)
E/AndroidRuntime(  251):  at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:160)
E/AndroidRuntime(  251):  at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)
E/AndroidRuntime(  251):  at android.content.ContentProviderProxy.bulkQueryInternal(ContentProviderNative.java:330)
E/AndroidRuntime(  251):  at android.content.ContentProviderProxy.query(ContentProviderNative.java:366)
E/AndroidRuntime(  251):  at android.content.ContentResolver.query(ContentResolver.java:245)
E/AndroidRuntime(  251):  at com.damburisoft.app.android.helloworld.a.onClick(Unknown Source)
E/AndroidRuntime(  251):  at android.view.View.performClick(View.java:2408)
E/AndroidRuntime(  251):  at android.view.View$PerformClick.run(View.java:8816)
E/AndroidRuntime(  251):  at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime(  251):  at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(  251):  at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  251):  at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime(  251):  at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  251):  at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(  251):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime(  251):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime(  251):  at dalvik.system.NativeStart.main(Native Method)
&lt;/code&gt;
&lt;/pre&gt;
AndroidManifest.xmlを編集していませんので，当然の結果です。ただ，Content Provider CallLogs.Callにアクセスする機能を追加できたのではないかと思われます。&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
今回は，パッケージに入っているクラスをsmali型式のファイルを通して編集することによって，動作を変更いたしましたが，編集ではなく新規にクラスを追加して実行させることも可能ではないのでしょうか。
いろいろと検索してみますと，disassembleしてアプリをハックする方法がいろいろとありますので，そんな難しいことではないのかもしれません。
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-916123273785385193?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/sMQH7zQ6lKeA3C8ohCyHkC7U5Wg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sMQH7zQ6lKeA3C8ohCyHkC7U5Wg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/sMQH7zQ6lKeA3C8ohCyHkC7U5Wg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/sMQH7zQ6lKeA3C8ohCyHkC7U5Wg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/vaiVTFSXckQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/916123273785385193/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=916123273785385193" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/916123273785385193?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/916123273785385193?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/vaiVTFSXckQ/blog-article-android-android-smali.html" title="repackage? android app" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/blog-article-android-android-smali.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEABQX4-eip7ImA9Wx9VEU0.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-7053332781274323347</id><published>2011-01-27T14:39:00.000+09:00</published><updated>2011-01-27T14:39:10.052+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-27T14:39:10.052+09:00</app:edited><title>どのように，偽のandroid appをつくるのか?</title><content type="html">&lt;p&gt;
GeiminiというAndroid OSを標的とした，Trojanの報告がある。&lt;br /&gt;
&lt;a href="http://blog.mylookout.com/2010/12/geinimi_trojan/"&gt;Lookout社のGeimini発見のレポート(Blog)&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
このTrojanは，として，第三者が運営するアプリ配布サイトで配布されている正規アプリの海賊版と一緒になって配布されている。&lt;br /&gt;
ここでは正規アプリの海賊版を簡単に作成できるかどうか考察してみたい。
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://kanatoko.wordpress.com/2011/01/21/android%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%83%AA%E3%83%90%E3%83%BC%E3%82%B9%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%83%AA%E3%83%B3%E3%82%B0/"&gt;Androidアプリケーションのリバースエンジニアリング&lt;/a&gt;より引用すると，&lt;br /&gt;

&lt;blockquote&gt;
Androidアプリケーションのリバースエンジニアリングをする場合には、目的として「解析だけしたい」場合と、「解析した上で、さらに動作を自分好みに変更する」、つまりアプリケーションの改造までを行いたい場合があるだろう。前者の場合、JDによるJavaソースコード形式への（ときに不完全な）変換で十分な場合もあるだろう。この場合、読みにくいsmali形式のファイルと格闘する必要がないかもしれない。しかし後者、つまり改造までを行いたい場合、アプリケーション内の目的の箇所を自分の意図を達成するように書き換え、ふたたびAndroidアプリケーションとして動作するよう、正しくアセンブルしなおす必要がある。smaliはこれを可能にしてくれる。非常に精度が高いディスアセンブル・アセンブルが可能なので、classes.dex -&gt; smali -&gt; classes.dexという変換が可能なのだ。
&lt;/blockquote&gt;

つまり，既に apk ファイルから，classを解析して(dex2jar)，ディスアセンブル(smali)して，再びclasses.dexを作成するツールが存在することを示している。&lt;br /&gt;
そこで，今回次のようなデモシナリオを提案する。
&lt;dl&gt;
  &lt;li&gt; ボタンを押したら Toast Messageを表示するAndroid Appを作成する。
  &lt;li&gt; ボタンをクリックしたとき，その裏で，Identifyを読み取るコードを埋め込む。
  &lt;li&gt; 再びアセンブルしてパッケージを作成する。
&lt;/dl&gt;
この作業がどれだけ簡単かどうかは，後日考察してみたい。
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-7053332781274323347?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/10gCAojO6B7ji12U2ZohL1G1oVY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/10gCAojO6B7ji12U2ZohL1G1oVY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/10gCAojO6B7ji12U2ZohL1G1oVY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/10gCAojO6B7ji12U2ZohL1G1oVY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/JjJRkH_8hJ4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/7053332781274323347/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=7053332781274323347" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7053332781274323347?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7053332781274323347?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/JjJRkH_8hJ4/android-app.html" title="どのように，偽のandroid appをつくるのか?" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/android-app.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUBSXk_fip7ImA9Wx9WEko.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-521569561653977331</id><published>2011-01-17T21:54:00.002+09:00</published><updated>2011-01-17T22:50:58.746+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-17T22:50:58.746+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android app" /><title>Update PutYourMind to 1.2</title><content type="html">&lt;p&gt;
Update &lt;a href="http://abekatsu.blogspot.com/2011/01/putyourmind-android-app.html"&gt;PutYourMind&lt;/a&gt; to version 1.2
&lt;dl&gt;
&lt;dt&gt;new feature&lt;/dt&gt;
&lt;dd&gt;add webpage title with url to your readitlater list.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://abekatsu.blogspot.com/2011/01/putyourmind-android-app.html"&gt;PutYourMind&lt;/a&gt;を1.2に更新いたしました。
&lt;dl&gt;
&lt;dt&gt;新規機能&lt;/dt&gt;
&lt;dd&gt;WebPageのURLをReadItLaterリストに追加する際に，そのページのtitleも一緒に登録するようにしました。&lt;/dd&gt;
&lt;/dl&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-521569561653977331?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LC0g5mZwbzkVWgUFXka_DYaxBLo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LC0g5mZwbzkVWgUFXka_DYaxBLo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LC0g5mZwbzkVWgUFXka_DYaxBLo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LC0g5mZwbzkVWgUFXka_DYaxBLo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/0GMdqSJx8Nk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/521569561653977331/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=521569561653977331" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/521569561653977331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/521569561653977331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/0GMdqSJx8Nk/update-putyourmind-to-12.html" title="Update PutYourMind to 1.2" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/update-putyourmind-to-12.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEEHQHs8fSp7ImA9Wx9WEUo.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-1430866132577873511</id><published>2011-01-16T20:17:00.000+09:00</published><updated>2011-01-16T20:17:11.575+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-16T20:17:11.575+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>PackageManager (ApplicationInfo)</title><content type="html">&lt;p&gt;
Android SDKには，
&lt;a href="http://developer.android.com/reference/android/content/pm/PackageManager.html"&gt;PacageManager&lt;/a&gt;という，デバイス上にインストールされたアプリケーションパッケージに関する情報を扱うクラスが提供されております。&lt;br /&gt;
これで，どんな情報が取得できるか，試してみました。
&lt;/p&gt;

&lt;p&gt;
最初は，
&lt;a href="http://developer.android.com/reference/android/content/pm/PackageManager.html#getInstalledApplications(int)"&gt;public abstract List&lt;ApplicationInfo&gt; getInstalledApplications (int flags)&lt;/a&gt;で得られるApplicationInfoにどんな情報が含まれているかについて調べてみました。

&lt;pre&gt;
&lt;code&gt;
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        mPackageManager = getPackageManager();
        getApplicationInfoList();
    }

    private void getApplicationInfoList() {
        List&lt;ApplicationInfo&gt; installedAppList = mPackageManager
                .getInstalledApplications(PackageManager.GET_META_DATA | 
                        PackageManager.GET_SHARED_LIBRARY_FILES | 
                        PackageManager.GET_UNINSTALLED_PACKAGES);
        showApplicationInfos(installedAppList);
    }

    private void showApplicationInfos(List&lt;ApplicationInfo&gt; infos) {
        if (infos != null) {
            for (ApplicationInfo info : infos) {
                showApplicationInfo(info);
            }
        }
    }

    private void showApplicationInfo(ApplicationInfo info) {
        if (info != null) {
            Log.d(TAG, "showApplicationInfo");
            Log.d(TAG, "className: " + info.className);
            Log.d(TAG, "packagename: " + info.packageName);
            Log.d(TAG, "name: " + info.name);
        }
    }

&lt;/code&gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
結果は，こんな感じです。
&lt;pre&gt;
D/PkgInfoSampleAppActivity(20363): showApplicationInfo
D/PkgInfoSampleAppActivity(20363): className: null
D/PkgInfoSampleAppActivity(20363): packagename: com.sonyericsson.android.contentmanager.contentprovider.webmedia
D/PkgInfoSampleAppActivity(20363): name: null
D/PkgInfoSampleAppActivity(20363): showApplicationInfo
D/PkgInfoSampleAppActivity(20363): className: null
D/PkgInfoSampleAppActivity(20363): packagename: com.noshufou.android.su
D/PkgInfoSampleAppActivity(20363): name: null
D/PkgInfoSampleAppActivity(20363): showApplicationInfo
D/PkgInfoSampleAppActivity(20363): className: null
D/PkgInfoSampleAppActivity(20363): packagename: com.damburisoft.android.app.showmyicon
D/PkgInfoSampleAppActivity(20363): name: null
&lt;/pre&gt;
packagename は得られましたが，nameやclassNameはなぜかnullです。もっと詳細な情報を得るにはどうしたらいいか，引き続き課題です。 
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-1430866132577873511?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kM88cZWm89nHf0Lbe9riH_Uol2g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kM88cZWm89nHf0Lbe9riH_Uol2g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kM88cZWm89nHf0Lbe9riH_Uol2g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kM88cZWm89nHf0Lbe9riH_Uol2g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/_g9Tur2HZJI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/1430866132577873511/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=1430866132577873511" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/1430866132577873511?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/1430866132577873511?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/_g9Tur2HZJI/packagemanager-applicationinfo.html" title="PackageManager (ApplicationInfo)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/packagemanager-applicationinfo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUABQ3c9eCp7ImA9Wx9XF0g.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-7560416882049323589</id><published>2011-01-11T22:49:00.000+09:00</published><updated>2011-01-11T22:49:12.960+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-11T22:49:12.960+09:00</app:edited><title>Update PutYourMind to 1.1</title><content type="html">Update &lt;a href="http://abekatsu.blogspot.com/2011/01/putyourmind-android-app.html"&gt;PutYourMind&lt;/a&gt; to version 1.1&lt;br /&gt;
&lt;p&gt;
&lt;dl&gt;
  &lt;dt&gt;new feature&lt;/dt&gt;&lt;dd&gt;add webpage title with url to your readitlater list.&lt;/dd&gt;
&lt;/dl&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;a href="http://abekatsu.blogspot.com/2011/01/putyourmind-android-app.html"&gt;PutYourMind&lt;/a&gt;を1.1に更新いたしました。&lt;br&gt;
&lt;dl&gt;
  &lt;dt&gt;新規機能&lt;/dt&gt;&lt;dd&gt;WebPageのURLをReadItLaterリストに追加する際に，そのページのtitleも一緒に登録するようにしました。&lt;/dd&gt;
&lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-7560416882049323589?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-cGj52h3GrJc2vVvRAsoY6POTPc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-cGj52h3GrJc2vVvRAsoY6POTPc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-cGj52h3GrJc2vVvRAsoY6POTPc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-cGj52h3GrJc2vVvRAsoY6POTPc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/W9MAa0Wr9uk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/7560416882049323589/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=7560416882049323589" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7560416882049323589?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/7560416882049323589?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/W9MAa0Wr9uk/update-putyourmind-to-11.html" title="Update PutYourMind to 1.1" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/update-putyourmind-to-11.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkACR3YzfSp7ImA9Wx9XFUg.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-3954068290440089407</id><published>2011-01-09T14:26:00.000+09:00</published><updated>2011-01-09T14:26:06.885+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-09T14:26:06.885+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android app" /><title>PutYourMind (android app)</title><content type="html">&lt;p&gt;
The 2nd. Android application made breaking out.
&lt;/p&gt;

&lt;p&gt;
This application catches an implicit intent, which data has a uri data. And put its uri data to your readitlater list. &lt;br /&gt;
This application requires your readitlater account.
&lt;/p&gt;

&lt;p&gt;
Please search it on Android Market by &lt;a htef="market://search?q=pname:com.damburisoft.android.app.putyourmind"&gt;PutYourMind&lt;/a&gt;, or use the following QR code.
&lt;/p&gt;

&lt;p&gt;
突発的に作成したアンドロイドアプリ第２弾。
&lt;/p&gt;
&lt;p&gt;
URIデータを含む暗黙的なインテントをキャッチして，そのデータをReadItLaterに追加します。
&lt;/p&gt;

&lt;p&gt;
Android Marketに公開しましたので，
&lt;a htef="market://search?q=pname:com.damburisoft.android.app.putyourmind"&gt;PutYourMind&lt;/a&gt;で検索するか，QRコードからダウンロードしてみてください。
&lt;/p&gt;

&lt;p&gt;
&lt;img src="http://chart.apis.google.com/chart?cht=qr&amp;chs=230x230&amp;chl=market%3A%2F%2Fsearch%3Fq%3Dpname%3Acom.damburisoft.android.app.putyourmind" /&gt;&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;
アイコンとアプリ名，なんかいいのがないかどうか募集です。
&lt;/p&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TSlGf6hiAyI/AAAAAAAAB7A/cZXBYpZ33fs/s1600/device_2011010901.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="192" src="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TSlGf6hiAyI/AAAAAAAAB7A/cZXBYpZ33fs/s320/device_2011010901.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/_ZRDIhGXbmEw/TSlGltTCzEI/AAAAAAAAB7I/w3cXxEZLHbQ/s1600/device_2011010902.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="192" src="http://4.bp.blogspot.com/_ZRDIhGXbmEw/TSlGltTCzEI/AAAAAAAAB7I/w3cXxEZLHbQ/s320/device_2011010902.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TSlGw2t7KvI/AAAAAAAAB7Q/SOb95bpR4lA/s1600/device_2011010903.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="192" src="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TSlGw2t7KvI/AAAAAAAAB7Q/SOb95bpR4lA/s320/device_2011010903.png" /&gt;&lt;/a&gt;&lt;/div&gt;

&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TSlGxGKB2hI/AAAAAAAAB7Y/GfEP12vgwq8/s1600/device_2011010904.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="192" src="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TSlGxGKB2hI/AAAAAAAAB7Y/GfEP12vgwq8/s320/device_2011010904.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-3954068290440089407?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cl-Fw3ETkzDYSmtIjNZKovGtGfY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cl-Fw3ETkzDYSmtIjNZKovGtGfY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cl-Fw3ETkzDYSmtIjNZKovGtGfY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cl-Fw3ETkzDYSmtIjNZKovGtGfY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/59AIf3Ntjfo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/3954068290440089407/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=3954068290440089407" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/3954068290440089407?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/3954068290440089407?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/59AIf3Ntjfo/putyourmind-android-app.html" title="PutYourMind (android app)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TSlGf6hiAyI/AAAAAAAAB7A/cZXBYpZ33fs/s72-c/device_2011010901.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/putyourmind-android-app.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DE8EQ3wzcSp7ImA9Wx9XFE8.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-5693951783213675331</id><published>2011-01-08T04:00:00.001+09:00</published><updated>2011-01-08T04:00:02.289+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-08T04:00:02.289+09:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="android app" /><title>ShowMyIcon (Android Application)</title><content type="html">&lt;p&gt;
When I went to a twitter off-line party, 
who present are a fan of Vegalta Sendai, it was a time to introduce oneself.
Someone used a mobile phone to show her/his twitter's icon image to attendees.
Though I used an Android phone, I didn't prepare my icon image to show them.
So I create a simple application, ShowMyIcon, to show my twitter icon on Android phone.
&lt;/p&gt;

&lt;p&gt;
&lt;div class="separator" style="clear: both; "&gt;
&lt;a href="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TScHBkj2mQI/AAAAAAAAB6w/-iYXIcdpKGg/s1600/device_2011010701.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="180" src="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TScHBkj2mQI/AAAAAAAAB6w/-iYXIcdpKGg/s320/device_2011010701.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; "&gt;
&lt;a href="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TScHB1Rwk9I/AAAAAAAAB64/toORZsw6z10/s1600/device_2011010702.png" imageanchor="1" style=""&gt;&lt;img border="0" height="320" width="180" src="http://1.bp.blogspot.com/_ZRDIhGXbmEw/TScHB1Rwk9I/AAAAAAAAB64/toORZsw6z10/s320/device_2011010702.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;

&lt;p&gt;
Just put your twitter's name.&lt;br /&gt;
Then this application downloads your icon image file and stores it inside.
Once you download, you can show it in without internet connections. 
&lt;/p&gt;

&lt;p&gt;
This application does not require user authorization. 
So it is possible for spoofing.
&lt;/p&gt;

&lt;p&gt;
This application, ShowMyIcon is available from an android market. &lt;br /&gt;
Please search by "ShowMyIcon" or access the following QR code: &lt;br /&gt;
&lt;img src="http://chart.apis.google.com/chart?cht=qr&amp;chs=230x230&amp;chl=market%3A%2F%2Fsearch%3Fq%3Dpname%3Acom.damburisoft.android.app.showmyicon" /&gt;

&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-5693951783213675331?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WP3IslAhVNXtzeVu6QsKasvkJFE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WP3IslAhVNXtzeVu6QsKasvkJFE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WP3IslAhVNXtzeVu6QsKasvkJFE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WP3IslAhVNXtzeVu6QsKasvkJFE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/ol6tYuIBqiM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/5693951783213675331/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=5693951783213675331" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/5693951783213675331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/5693951783213675331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/ol6tYuIBqiM/showmyicon-android-application.html" title="ShowMyIcon (Android Application)" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TScHBkj2mQI/AAAAAAAAB6w/-iYXIcdpKGg/s72-c/device_2011010701.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2011/01/showmyicon-android-application.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08ARno9fyp7ImA9Wx9SEUQ.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-6376586377195307520</id><published>2010-12-01T17:24:00.000+09:00</published><updated>2010-12-01T17:24:07.467+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-12-01T17:24:07.467+09:00</app:edited><title>Redmineに関する雑多メモ</title><content type="html">本格的にバグトラックをしたいのだけど，2点懸念事項がある。その懸念に対する解決策が既にあるようなのでメモです。
ありがとうございます。

Q: 何も考えずにSQLite3でDBを運用した場合，パフォーマンスに問題はないの？

A:
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://blog.redmine.jp/articles/change-database/"&gt;Redmineで使うデータベースを変更する&lt;/a&gt;
  &lt;li&gt;&lt;a href="http://garin.jp/doc/Ruby/Redmine/sqlite3tomysql"&gt;Redmine(Rails) の DB を SQLite3 から MySQL に移行する&lt;/a&gt;
&lt;/ul&gt;

Q: ユーザー管理は面倒だ。Google Appsのアカウントは使えないの？
A: &lt;a href="http://www.ana-kutsu.com/mt/mt-search.cgi?tag=Google%20Apps&amp;blog_id=1&amp;IncludeBlogs=1"&gt;Redmineをセットアップしてみた&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-6376586377195307520?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fNObZfh1-Z0uRL8qz-fX-PyCFtI/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fNObZfh1-Z0uRL8qz-fX-PyCFtI/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fNObZfh1-Z0uRL8qz-fX-PyCFtI/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fNObZfh1-Z0uRL8qz-fX-PyCFtI/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/O6FMulE2eis" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/6376586377195307520/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=6376586377195307520" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6376586377195307520?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6376586377195307520?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/O6FMulE2eis/redmine.html" title="Redmineに関する雑多メモ" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2010/12/redmine.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak8GRXoyeyp7ImA9Wx5SGUk.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-2822275586408658918</id><published>2010-08-16T17:53:00.000+09:00</published><updated>2010-08-16T17:53:44.493+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-16T17:53:44.493+09:00</app:edited><title>textsize, sp and dp</title><content type="html">androidのdimension type, "sp" (scaled-pixels) や "dp" (density-independent pixel)　のことがよくわからなかったので，適当にTextViewを作成してみた。画面サイズは，QVGA，HVGA，WVGA800，WVGA854。画面内のテキストのサイズには最初から10pt，14pt，18pt，10dp，14dp，18dp，10sp，14sp，18spと指定してみた。
&lt;br /&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj3uYrG_II/AAAAAAAAB4E/29CNMhv_5-E/s1600/QVGA1_spdp.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj3uYrG_II/AAAAAAAAB4E/29CNMhv_5-E/s200/QVGA1_spdp.png" width="150" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;QVGA&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj4G-xBKLI/AAAAAAAAB4U/kwmo6ZOhZgg/s1600/HVGA_spdp.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj4G-xBKLI/AAAAAAAAB4U/kwmo6ZOhZgg/s200/HVGA_spdp.png" width="133" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;HVGA&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TGj722F7BBI/AAAAAAAAB4k/vQDpXcW989k/s200/WVGA800_spdp.png" style="margin-left: auto; margin-right: auto;" width="120" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;WVGA800&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj4EUQqCyI/AAAAAAAAB4Q/u5QqgqxZCAM/s1600/WVGA854_spdp.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="200" src="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj4EUQqCyI/AAAAAAAAB4Q/u5QqgqxZCAM/s200/WVGA854_spdp.png" width="111" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;WVGA854&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/_ZRDIhGXbmEw/TGj722F7BBI/AAAAAAAAB4k/vQDpXcW989k/s1600/WVGA800_spdp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none; color: black;"&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-2822275586408658918?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/eVnslZ2EddNR5_pHvdfsRKAkhjw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eVnslZ2EddNR5_pHvdfsRKAkhjw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/eVnslZ2EddNR5_pHvdfsRKAkhjw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/eVnslZ2EddNR5_pHvdfsRKAkhjw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/9qGN8aGlguo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/2822275586408658918/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=2822275586408658918" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/2822275586408658918?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/2822275586408658918?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/9qGN8aGlguo/textsize-sp-and-dp.html" title="textsize, sp and dp" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_ZRDIhGXbmEw/TGj3uYrG_II/AAAAAAAAB4E/29CNMhv_5-E/s72-c/QVGA1_spdp.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2010/08/textsize-sp-and-dp.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkMEQHg7eip7ImA9WxBUFU4.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-8228956899207602896</id><published>2010-03-02T20:46:00.000+09:00</published><updated>2010-03-02T20:46:41.602+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T20:46:41.602+09:00</app:edited><title>自分の無能さを晒す 2 Google Dev Fest 2010 の Quiz パッチワーク版</title><content type="html">&lt;p&gt;
まずは，6時間かかったバージョン。
&lt;pre&gt;
#!/opt/local/bin/ruby

# read file and create array.
$basearea = []
$hascheckedarea = []
$max_x_size = 0
$max_y_size = 0

open(ARGV[0]) do |file|
  while l = file.gets
    $max_y_size += 1
    l.chomp!
    add_array = []
    add_check_array = []
    for i in 0 .. l.size - 1
      add_array += [l[i].chr]
      add_check_array += [false]
    end
    $basearea &lt;&lt; add_array
    if ($max_x_size &lt; add_array.size) 
      $max_x_size = add_array.size
    end
    $hascheckedarea &lt;&lt; add_check_array
  end
end


# main routine

def clear_has_checked_array
  for x in 0 .. ($hascheckedarea.size - 1)
    for y in 0 .. $hascheckedarea[x].size - 1
      $hascheckedarea[x][y] = false
    end
  end
end

def is_equal_char_forpoint(compare_char, point_x, point_y)
  # debug_str = "checking (x, y) = (" + point_x.to_s + ", " + point_y.to_s + ")"
  if point_x &lt; 0 || point_y &lt; 0 || point_x &gt;= $max_x_size || point_y &gt;= $max_y_size
    return false
  end
  # p debug_str
  retvalue = false 
  if $basearea[point_x][point_y]
    if $hascheckedarea[point_x][point_y] == true
      # debug_str += (" has been checked ") 
    else
      $hascheckedarea[point_x][point_y] = true
      # debug_str += (" is " + $basearea[point_x][point_y])
      if compare_char == $basearea[point_x][point_y]
        retvalue = true
      else
        retvalue = false
      end
      # debug_str += (retvalue == true) ? "result is true" : "result is false"
    end
  end
  # debug_str += " for ( " + point_x.to_s + ", " +  point_y.to_s + ")"
  # p debug_str
  retvalue
end

def measure_continuous_area(base_char, start_point_x, start_point_y)
  # debug_str = "searching (" + (start_point_x).to_s + ", " + (start_point_y).to_s + ")"
  # p debug_str
  retvalue = 1
  $hascheckedarea[start_point_x][start_point_y] = true
  if is_equal_char_forpoint(base_char, start_point_x - 1, start_point_y)
    retvalue += measure_continuous_area(base_char, 
                                        start_point_x - 1, start_point_y)
  end
  if is_equal_char_forpoint(base_char, start_point_x, start_point_y - 1)
    retvalue += measure_continuous_area(base_char,
                                        start_point_x, start_point_y -1)
  end

  if is_equal_char_forpoint(base_char, start_point_x + 1, start_point_y)
    retvalue += measure_continuous_area(base_char,
                                        start_point_x + 1, start_point_y)
  end

  if is_equal_char_forpoint(base_char, start_point_x, start_point_y + 1)
    retvalue += measure_continuous_area(base_char,
                                        start_point_x, start_point_y + 1)
  end
  retvalue
end

x_axis = 0
y_axis = 0
conarea_size =[]
for x_axis in 0 .. $basearea.size - 1
  line_size = []
  for y_axis in 0 .. $basearea[x_axis].size - 1
    #p $basearea[x_axis][y_axis]
    clear_has_checked_array()
    line_size += [measure_continuous_area($basearea[x_axis][y_axis], x_axis, y_axis)]
  end
  conarea_size &lt;&lt; line_size;
end

$basearea.each do |array|
  p array
end

#conarea_size.each do |array|
#  p array
#end

max_area_size = 0

conarea_size.each do |x_array|
  p x_array
  x_array.each do |value|
    if max_area_size &lt; value
      max_area_size = value
    end
  end
end

#debug_str = "max area size " + max_area_size.to_s
#p debug_str

conarea_size.each do |x_array|
  count = 0
  x_array.each do |value|
    if max_area_size == value
      count += 1
    end
  end
  p count
end
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
何がまずいか。
&lt;ul&gt;
  &lt;li&gt;各点ごとに最大連結エリアサイズを求めようとしている。
  &lt;li&gt;エリアサイズを求める際に，境界を記録しておく配列 $hascheckedarea (サイズ 600×600)を用意していたが，各点のエリア計算時にクリアしている。
&lt;/ul&gt;
各点ごとに計算しているので，例えば
&lt;pre&gt;
AAB
BAA
BBA
&lt;/pre&gt;
を例にしたとき，A全ての点でおいて最大連結エリアサイズを求めている。この場合，点(0,0)のAの最大連結エリアサイズが判れば，他の点で計算する必要はない。しかも，$hascheckedarea を各点の計算毎にクリアしているので，とんでもない無駄な計算をしてしまった。
&lt;/p&gt;
&lt;p&gt;
回答終了後，&lt;a href="http://d.hatena.ne.jp/hagino_3000/20100226/devfest_quiz"&gt;DevFest Quizパッチワーク問題の回答 CommonJS編 (電脳戦士ハラキリ -SE道とは死ぬ事と見つけたり)&lt;/a&gt;を見て，最大連結エリアを構成する部分集合のうちの1点だけを記録して，最後に答となる点から連結するエリアを塗りつぶせばいいということと(リンク先の配列  maxScoreCells[]と関数 fill()に注目)，チェックした領域を1点ごとにクリアしてはいけない ($hascheckedareaを利用しない。そのかわり，$scoreMapで記録する。このscoreMapは全ての点において正しい最大連結エリアの値を保存しているとは限らない) ということを理解して，改訂しました。
&lt;pre&gt;
#!/opt/local/bin/ruby

# read file and create array.
$basearea = []
$scoreMap = []

$max_x_size = 0
$max_y_size = 0

# 問題ファイルを読みこみ，元となる配列 $basearea を作成
open(ARGV[0]) do |file|
  while l = file.gets
    $max_y_size += 1
    l.chomp!
    add_array = []
    add_check_array = []
    for i in 0 .. l.size - 1
      add_array += [l[i].chr]
      add_check_array += [-1]
    end
    $basearea &lt;&lt; add_array
    if ($max_x_size &lt; add_array.size) 
      $max_x_size = add_array.size
    end
    $scoreMap &lt;&lt; add_check_array
  end
end


def is_equal_char_forpoint(compare_char, point_x, point_y)
  # debug_str = "checking (x, y) = (" + point_x.to_s + ", " + point_y.to_s + ")"
  if point_x &lt; 0 || point_y &lt; 0 || point_x &gt;= $max_x_size || point_y &gt;= $max_y_size
    return false
  end

  if $scoreMap[point_x][point_y] != -1
    return false # this point has been already checked
  end
  # p debug_str
  retvalue = false
  if $basearea[point_x][point_y]
    if compare_char == $basearea[point_x][point_y]
      retvalue = true
    else
      retvalue = false
    end
  end
  # debug_str += " for ( " + point_x.to_s + ", " +  point_y.to_s + ")"
  # p debug_str
  retvalue
end

def measure_continuous_area(base_char, start_point_x, start_point_y)
  # debug_str = "searching (" + (start_point_x).to_s + ", " + (start_point_y).to_s + ")"
  # p debug_str
  if $scoreMap[start_point_x][start_point_y] != -1
    retvalue = 0 # チェック済みなので計算させない
  end

  $scoreMap[start_point_x][start_point_y] = 0 # この作業で点 (start_point_x, start_point_y) はチェック済みであることを表す。

  if (base_char == $basearea[start_point_x][start_point_y])
    retvalue = 1
  end

  if is_equal_char_forpoint(base_char, start_point_x - 1, start_point_y)
    retvalue += measure_continuous_area(base_char, 
                                        start_point_x - 1, start_point_y)
  end
  if is_equal_char_forpoint(base_char, start_point_x, start_point_y - 1)
    retvalue += measure_continuous_area(base_char,
                                        start_point_x, start_point_y -1)
  end

  if is_equal_char_forpoint(base_char, start_point_x + 1, start_point_y)
    retvalue += measure_continuous_area(base_char,
                                        start_point_x + 1, start_point_y)
  end

  if is_equal_char_forpoint(base_char, start_point_x, start_point_y + 1)
    retvalue += measure_continuous_area(base_char,
                                        start_point_x, start_point_y + 1)
  end
  retvalue
end

x_axis = 0
y_axis = 0
maxScore = 0
maxScorePoint = []

for x in 0 .. $basearea.size - 1
  for y in 0 .. $basearea[x_axis].size - 1
    #p $basearea[x_axis][y_axis]
    # clear_has_checked_array()
    score = measure_continuous_area($basearea[x][y], x, y)
    if (maxScore &lt; score)  
      maxScore = score
      maxScorePoint = [[x, y]]
    elsif (maxScore == score)
        maxScorePoint += [[x, y]]
    end
  end
end

$basearea.each do |array|
  p array
end

def fill(x, y, chr)
  if ($basearea[x][y] != chr)
    return
  end

  $basearea[x][y] = '_'
  fill(x+1, y, chr)
  fill(x, y+1, chr)
  fill(x-1, y, chr)
  fill(x, y-1, chr)

end

maxScorePoint.each do |point|
  x = point[0]
  y = point[1]
  fill(x, y, $basearea[x][y])
end

$basearea.each do |array|
  p array
end

$basearea.each do |array|
  cnt = 0
  array.each do |chr|
    if chr == '_'
      cnt += 1
    end
  end
  p cnt
end
&lt;/pre&gt;
結果，10秒程度で実行完了。自分の無能さを実感した日でした。
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-8228956899207602896?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hGjO9CcvHphV2fi2kkyAia_LifQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hGjO9CcvHphV2fi2kkyAia_LifQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hGjO9CcvHphV2fi2kkyAia_LifQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hGjO9CcvHphV2fi2kkyAia_LifQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/Db5EpYNONYw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/8228956899207602896/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=8228956899207602896" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/8228956899207602896?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/8228956899207602896?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/Db5EpYNONYw/2-google-dev-fest-2010-quiz.html" title="自分の無能さを晒す 2 Google Dev Fest 2010 の Quiz パッチワーク版" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2010/03/2-google-dev-fest-2010-quiz.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QHQ3c5cSp7ImA9WxBUFU8.&quot;"><id>tag:blogger.com,1999:blog-14443318.post-6451106950386209470</id><published>2010-03-02T20:28:00.000+09:00</published><updated>2010-03-02T20:28:52.929+09:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-02T20:28:52.929+09:00</app:edited><title>自分の無能さを晒す 1 Google Dev Fest 2010 の Quiz 漢字変換サーバ版</title><content type="html">&lt;p&gt;
あー，自分でWebサーバ持っていないし，GAEにアプリ登録したこともないから，この問題にはチャレンジできないなと思っていましたが，回答締切6時間前に，別に自分で簡易ウェブサーバ立ちあげればいいんじゃないと思い，急遽やってみました。&lt;br /&gt;
幸いなことに，&lt;a href="http://abekatsu.blogspot.com/2010/02/chromeemacs.html"&gt;EmacsをChrome上で利用するためにWEBrickを利用したHTTPサーバのスクリプトを読んだこと（ChromeとEmacsを愛するもの達へ 【編集あり】）&lt;/a&gt;を思いだしたのが幸いでした。
&lt;/p&gt;

&lt;p&gt;
方針は，
&lt;ul&gt;
  &lt;li&gt;特殊ケース 0 の場合は 零(H) を返す
  &lt;li&gt;兆の位の4桁，億の位の4桁，万の位の4桁，一の位？の4桁を抽出して，漢数字に変換する。0や1千の扱い時に注意する。
&lt;/ul&gt;
です。
&lt;pre&gt;
def trans_4digit_kansuzi(num)
  digit_1st_array = ['', 'G', 'B', 'S', 'A', 'Q', 'Z', 'P', 'C', 'Y'] # 零 一 二 三 四 五 六 七 八 九
  digit_other_array = ['', '', 'B', 'S', 'A', 'Q', 'Z', 'P', 'C', 'Y'] # 零 一 二 三 四 五 六 七 八 九
  unit_array = ['N', 'M', 'J', ''] # 千 百 十 零

  is_top_digit_zero = true
  ret_str = ""
  for i in 0 .. unit_array.size - 1
    tmp_num = (num % (10 ** (unit_array.size - i))) / (10 ** (unit_array.size - 1 -i))
    if tmp_num &gt; 0 || is_top_digit_zero == false
      is_top_digit_zero = false
      if tmp_num != 0
        if i == (unit_array.size - 1)
          ret_str += (digit_1st_array[tmp_num] + unit_array[i])
        else
          ret_str += (digit_other_array[tmp_num] + unit_array[i])
        end
      end
    end
  end

  return ret_str
end

def trans_kansuzi(num)
  if num == 0
    return 'H' # 零
  end

  unit_array = ['T', 'D', 'K', ''] # 兆 億 万 零 

  ret_str = ""
  is_top_digit_zero = true
  for i in 0 .. unit_array.size - 1
    tmp_num = (num % (10000 ** (unit_array.size - i))) / (10000 ** (unit_array.size - 1 - i))
    debug_str = i.to_s + " " + tmp_num.to_s
    p debug_str
    if tmp_num &gt; 0 || is_top_digit_zero == false
      is_top_digit_zero = false
      if tmp_num != 0
        ret_str += (trans_4digit_kansuzi(tmp_num) + unit_array[i])
      end
    end
  end
  return ret_str
end

p trans_kansuzi(ARGV[0].to_i)
&lt;/pre&gt;

本当は
&lt;pre&gt;
tmp_num = (num % (10000 ** (unit_array.size - i))) / (10000 ** (unit_array.size - 1 - i))
&lt;/pre&gt;
のように上位桁から検証してしまったが，
&lt;pre&gt;
tmp_num = num % 10000 # 下4桁の値を得る
# tmp_num 文字列生成処理
num = num / (10000 ** i) # 右4桁移動する。
&lt;/pre&gt;
のように，下位桁から検証した方が綺麗。(テストはしていない)
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/14443318-6451106950386209470?l=abekatsu.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/G4P-8CSVwQfuGb_kXKGjy-WeB84/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/G4P-8CSVwQfuGb_kXKGjy-WeB84/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/G4P-8CSVwQfuGb_kXKGjy-WeB84/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/G4P-8CSVwQfuGb_kXKGjy-WeB84/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhatHappensToday/~4/hP6MrtWnxpY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://abekatsu.blogspot.com/feeds/6451106950386209470/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=14443318&amp;postID=6451106950386209470" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6451106950386209470?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/14443318/posts/default/6451106950386209470?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhatHappensToday/~3/hP6MrtWnxpY/1-google-dev-fest-2010-quiz.html" title="自分の無能さを晒す 1 Google Dev Fest 2010 の Quiz 漢字変換サーバ版" /><author><name>Katsuhisa Abe</name><uri>https://profiles.google.com/118076810680900413139</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh4.googleusercontent.com/-N5zN4Kp1A5w/AAAAAAAAAAI/AAAAAAAACFE/yNOljzZMKHI/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://abekatsu.blogspot.com/2010/03/1-google-dev-fest-2010-quiz.html</feedburner:origLink></entry></feed>

