2011年2月27日日曜日

RSSのパースとか


AndroidにおけるRSSのパースに関しては、実はIBMのサイトで詳しく解説されている。
リンクで上げたページでは、パースの方法をいろいろ説明するためにFactoryを作っているけど
自分はandroid.sax.*を利用して実装した。
パースする前にHTTP GETするわけだけど、そのときに
httpget.setHeader("User-Agent", "Mozilla/5.0");
をセットし忘れないようにしないと、レスポンスがUTF-8で来てくれない。もっとも今はこれで平気だけど、何時ダメになるかわからないんですがね。。。

以前のエントリのようにAsyncTaskを利用して、HTTP GETして、
レスポンスを
 protected List<message> doInBackground(String... params) {
  String query;
  query = "https://www.google.com/history/find?output=rss"+"&q="+params[0];
  HttpGet httpget = new HttpGet(query);
  httpget.setHeader("User-Agent", "Mozilla/5.0");
  HttpResponse response;
  List<message> messages = null;
  
  try {
   response = _HttpClient.execute(httpget);
   
   int status_code = response.getStatusLine().getStatusCode();
   if (status_code < 400){
    InputStream istream = response.getEntity().getContent();
    FeedParser parser = new AndroidSaxFeedParser(istream);
    messages = parser.parse();
    istream.close();
   }
  } catch (ClientProtocolException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   // TODO finalize
  }
  return messages;
 }
のようにして取得する。(エラー処理とかははずしてしまったが。。。) messagesには各RSSのアイテムが入っているので、 それぞれ値を取得してリストに表示させてやればいい。

今回は欲しい情報を得るのに、認証が必要でその処理がCookieを利用していた。 あんまりいい方法じゃないかもしれないが、一度認証済みのHttpClientを他のActivityでも使いまわしたいな。。。と思ったので、"android データ Activity"でググッたら出てくる出てくる。 簡単に言うとApplicationのインスタンスにデータを保持させて全体からそれを覗く。ということだ。 準備は
public class SingleConnectApp extends Application {
 private DefaultHttpClient _HttpClient = null;
 
 public void setHttpClient(DefaultHttpClient client) {
  _HttpClient = client;
 }
 
 public DefaultHttpClient getHttpClient() {
  return _HttpClient;
 }
}
こんなクラスを作ってmanifestのapplicationタグを <application android:icon="@drawable/gfoot_icon" android:label="@string/app_name" android:name="SingleConnectApp"> のようにして、onCreate内とかで
SingleConnectApp app = (SingleConnectApp)this.getApplication();
  DefaultHttpClient client = app.getHttpClient();
のようにすればActivity間でインスタンスを共有できる。
よくよく考えるとDefaultHttpClientを拡張してsingletonのクラス作れば同じこと出来んじゃね?てかソッチのが良いな。とか思ったけど、Applicationクラスにデータを持たしてみたかったのでそのまま進めた。

2011年2月19日土曜日

leanbackとYouTube Remote


Androidで面白いのを見つけたので紹介。
youtubeのleanbackをリモートコントロールするソフトだ。
そもそもleanback自体があまり知られていない。
自分はIT企業に勤めているけど、そこでも知っている人のほうが少ないようだ。
youtubeのURLの後ろにleanbackと打つだけで、TVっぽいUIのページ(http://www.youtube.com/leanback)に飛ぶ(たぶんFlash)。
基本的に十字キーだけでコントロールできるように設計されている。

youtubeにログインして、leanbackのページをPCで表示させてから
これを起動すると、
Androidからleanbackの表示コンテンツがコントロールできる。
スゲー。
レスも速いし。
firefoxでleanbackのページを全画面表示にするとほんとにテレビっぽい。

youtubeに上げてみた。

2011年2月9日水曜日

AndroidでGoogle Web履歴をHTTP GET


Gfootというアプリをマーケットにリリースした。
アプリをリリースしたけど、何をやったのか?調べたのか?
書き残しておかないと忘れてしまいそうなので、
そろそろまとめてみる。
・ブラウザを利用しないでCookieを解決する
・RSSのパース
がメインかな?

GoogleのWeb履歴を見る際のCookieの扱いについては、ここを参照しました。
このサイトによると、履歴を見るためにログインするわけだが、そのためのCookieをログイン画面の
HTMLをGETで取得することで、解決していることがわかる。
また、ログインする際にformの情報をPOSTするわけだが、その情報も同時に取得している。
ただ、これだけだとAndroid上でどうやってログイン処理すればよいのかが
具体的にはわからないので、ここを参考にしてみた。
上記二つのサイトを参考に組み合わせてAndroidからGoogle Web履歴にアクセスしている。
以下は、説明に要らない部分など削っているので、変なところもあるかと思うが、
基本的には下記で得られた_HttpClient(DefaultHttpClientクラス)を利用すれば、履歴の取得が可能だ。
ちなみにHTMLをパースしてinput部分を取得するために
jericho-html-3.1.jarを利用しています。(LGPLなので使うだけならソースの公開義務はないはず。)
それと当然ですが、ネットワーク系の処理をするときにUIスレッドで処理すると
操作性が悪くなるので、AsyncTaskを利用してます。

@Override
  protected DefaultHttpClient doInBackground(String... params) {
   String email = params[0];
   String passwd = params[1];
   
   _HttpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
   _HttpClient.getParams().setParameter("http.connection.timeout", 5000);
   _HttpClient.getParams().setParameter("http.socket.timeout", 3000);
   
   HttpGet httpget = new HttpGet(https://www.google.com/accounts/ServiceLogin?hl=ja&nui=1&service=hist);
   HttpResponse response;
   String result = null;
   try {
    response = _HttpClient.execute(httpget);
    int status_code = response.getStatusLine().getStatusCode();
    Log.v("Gfoot","status_code="+status_code);
    if (status_code < 400){
     InputStream istream = response.getEntity().getContent();
     InputStreamReader reader = new InputStreamReader(istream);
     BufferedReader objBuf = new BufferedReader(reader);
     StringBuilder builder = new StringBuilder();
     String sLine;
     while((sLine = objBuf.readLine()) != null){
      builder.append(sLine);
     }
     result = builder.toString();
     istream.close();
    } else {
     _HttpClient = null;
    }
   } catch (ClientProtocolException e) {
    _HttpClient = null;
    e.printStackTrace();
   } catch (IOException e) {
    _HttpClient = null;
    e.printStackTrace();
   }
   if (result == null) {
    return null;
   }
   
   
   String name;
   String value;
   Source source = new Source(result);
   List linkElements = source.getAllElements(HTMLElementName.INPUT);
   int count = linkElements.size();
   List nameValuePair = new ArrayList(count);
   for (Element linkElement : linkElements) { 
    name = linkElement.getAttributeValue("name");
    value = linkElement.getAttributeValue("value");
    if ("Email".equals(name)) {
     value = email;
    }
    if ("Passwd".equals(name)) {
     value = passwd;
    }
    nameValuePair.add(new BasicNameValuePair(name, value));
   }
   // この段階でPOSTするために必要な情報は、nameValuePairに含まれている。
   
   HttpPost httppost = new HttpPost(https://www.google.com/accounts/ServiceLoginAuth?service=hist);
   try {
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePair));
    response = _HttpClient.execute(httppost);
   } catch (UnsupportedEncodingException e) {
    _HttpClient = null;
    e.printStackTrace();
   } catch (ClientProtocolException e) {
    _HttpClient = null;
    e.printStackTrace();
   } catch (IOException e) {
    _HttpClient = null;
    e.printStackTrace();
   }
   
   return _HttpClient;
  }

ここでログインの際に
https://www.google.com/accounts/ServiceLogin?service=hist
というのを利用して、ログインのためのCookieを取得しているが、
これはどうやって知るのか?履歴以外はどうなのか?
気になるところだと思う。
このサイトがかなりいろいろな情報をもたらしてくれる。
service=histは履歴をさしているわけだ。

次回は、履歴やBookmarkをRSS形式で取得する部分と
パースについて。
また、おまけでアプリケーション全体において永続的なデータを作る方法。

2011年2月6日日曜日

Androidマーケットに初登録


アンドロイドマーケットに初めて登録しました。
マーケットへのリンク
いろいろ調べたことは、また後日に書こうかと思います。

2011年1月27日木曜日

Google Bookmarks API 。。。は無いらしい


Google Bookmarksが便利だし、履歴も含めたアプリ作れないものかと思って少し調べてみた。
結論としては、公式にはAPIはない模様。。。

ただし。XML形式でデータは取れる。

https://www.google.com/bookmarks/lookup?start=25&output=xml
lookup → リストを取得の意

https://www.google.com/bookmarks/find?q=maps.google.com&start=25&output=xml
find → 検索の意
q=maps.google.com → キーワード"maps.google,com"で検索
start=25 → 25個目から取得
utput=xml → XML形式で取得


本当に欲しかったのは履歴なので、それは後日調べることにする。

以下追記
履歴は
https://www.google.com/history/find?output=rss&st=maps&q=
で、RSS形式でデータが取れる模様。
BookmarkもRSS形式で取得可能だった。
st=maps → google mapsのデータを取得している。
st部分を変更すれば、他の種類のデータが取れそう。
ただ、wgetは出来なそう。
ここを見たけど、ブラウザのCookieをりようすれば可能との事。

2011年1月18日火曜日

Google Bookmarksを共有


最近知ったんだけど、
Google Bookmarksを旅行での写真や動画を共有するのにちょうどいい。

写真→picasaへアップロード
動画→youtubeとかほかの動画サイトへアップ

で、ばらばらなものを一つにまとめる。
かつ、プライバシーの観点から閲覧を許可制にする。
これのためのGoogle Bookmarks
https://www.google.com/bookmarks/l
にアクセスすと英語表記のページになる。(最後の「l」が大事)
label等で分けたりしたBookmarkにチェックをつけて、
Copy to listを選択して、リスト作成したり、すでにあるリストに追加したり。

作ったリストは、左上の「My lists」から見られる。
リストを共有したい場合は、リストを表示した状態で、
Shareを選択すると表示されるポップアップで、
「People with access」タブの「Invite people」に
見せても良い人のGmailのアドレスを打ち込んでinviteでOK。

visibilityはprivateにするのをお忘れなく。

結構便利。

2011年1月5日水曜日

android build on 32bit (froyo/gingerbread)


froyo(2.2)から、Androidのソースをbuildしようとしても
64bitじゃないからムリー。みたいな事をいわれてビルドできなかった。
しばらく放置してたけど、もう一度調べてみたら、
出来たのでメモをとっておく。

1)
$ repo init -u git://android.git.kernel.org/platform/manifest.git -b froyo
もしくは、
$ repo init -u git://android.git.kernel.org/platform/manifest.git -b gingerbread
でソースコード取得。

2)
$ repo sync

3)
64bitの記述があるところを修正
32-bit support in froyo/2.2を参考にすればいける。

./build/core/main.mk
の以下のように編集
ifeq ($(BUILD_OS),linux)
build_arch := $(shell uname -m)
-ifneq (64,$(findstring 64,$(build_arch))) ←コメントアウトしたり削除したり
+ifneq (i686,$(findstring i686,$(build_arch))) ←追加するコード
$(warning ************************************************************)
$(warning You are attempting to build on a 32-bit system.)

4)
以下の4つの中に
./external/clearsilver/cgi/Android.mk
./external/clearsilver/java-jni/Android.mk
./external/clearsilver/util/Android.mk
./external/clearsilver/cs/Android.mk

LOCAL_CFLAGS += -m64
LOCAL_LDFLAGS += -m64
という記述があるので、コメントアウトするか
LOCAL_CFLAGS += -m32
LOCAL_LDFLAGS += -m32
のように32bitに書き換える。

5)
$ make -j2
で、コンパイル開始。
コアの数や作業状況によっては、-j4としたほうがコンパイルは早くなる。


手順4)を抜かしてみたけど自分の環境では、
64bit用のヘッダーがないよー。みたいなエラーが出たので、
ダメみたいです。

最後は、以下を実行すればemulatorが立ち上がる。
./out/host/linux-x86/bin/emulator -kernel ./prebuilt/android-arm/kernel/kernel-qemu -system ./out/target/product/generic -ramdisk ./out/target/product/generic/ramdisk.img -data ./out/target/product/generic/userdata.img -skindir ./sdk/emulator/skins/ -skin HVGA


froyoでもgingerbreadでも同じ手順でbuild出来ました。