2010年1月23日土曜日

Android用のTwitterクライアントを作ってみる3

以前作った機能をほぼそのままServiceが管理するように作成
その上で

  • 一定時間毎に hometimeline を取得
  • ステータスバーへの通知
  • サービスからのコールバック
みたいな機能をつけました。


一定時間毎に hometimelineを取得
 private static final int GET_TWITTER_HOME_TIMELINE = 1;
 Handler mHandler = new Handler(){
 public void dispatchMessage(Message msg) {
  switch( msg.what){
  case GET_TWITTER_HOME_TIMELINE:
   mHandler.removeMessages(GET_TWITTER_HOME_TIMELINE);
   mHandler.sendEmptyMessageDelayed(GET_TWITTER_HOME_TIMELINE, intervaltime);
   // TODO
  }
 };

至って単純です。
mHandler.sendEmptyMessageDelayedで適当な時間後に自分自身を呼び出すだけです。


ステータスバーへの通知
 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 Notification notification = new Notification(R.drawable.icon, getString(R.string.Service_message1), System.currentTimeMillis());
 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, 呼び出すアクティビティ名.class), 0);
 // 第二引数がアイコン横の太字
 // 第三引数が通知内容(?)
 notification.setLatestEventInfo(this, getString(R.string.app_name), getString(R.string.Service_message1), contentIntent);
 notification.flags = Notification.FLAG_AUTO_CANCEL; // 通知を一度使用したらステータスバーから自動的に消える
 // 第一引数は通知ID
 manager.notify(R.string.app_name, notification); // ステータスバーへの通知

詳細はTaosoftwareさんのブログとか
http://www.taosoftware.co.jp/blog/2009/04/android_notification.html
こちらAndroidの受託開発とかやってるみたいですね。
うちの会社と規模も良く似てるwww
でもAndroid特化(?)というのは羨ましいような・・・。


サービスからのコールバック
 //*** ICallbackListener を宣言するaidlファイル
 interface ICallbackListener {
  void receiveMessage(String message);
 }
 //*** サービス側ソース
 //コールバックアクティビティの管理リスト
 private RemoteCallbackList listeners = new RemoteCallbackList();
 //リスナーの追加
 public void addListener(ICallbackListener listener) throws RemoteException {
  listeners.register(listener);
  //削除はunregister で
 }
 //コールバック内容
 int numListeners = listeners.beginBroadcast(); //listeners.finishBroadcast();までスレッドセーフ
 for( int i = 0; i < numListeners; i++){
  try {
   listeners.getBroadcastItem(i).receiveMessage( "コールバック内容");
  } catch (RemoteException e) {
   Log.e("CallbackService", e.getMessage(), e);
  }
 }
 listeners.finishBroadcast();
 //*** コールバックを受け取るアクティビティのソース
 private ICallbackListener listener = new ICallbackListener.Stub() {
  public void receiveMessage(String message) throws RemoteException {
  // TODO メッセージに対する処理
  }
 };

え~、あ~
あくまで備忘録なんで、足りない部分は脳内補完してください。
コピペだけじゃ動きません。


と、まあこんな感じで作ると
twitter に新着があると

  • アクティビティが起動してない場合は通知バーへ通知
  • アクティビティが起動してたらコールバックを使用して直接描画
みたいなことができます。
ちなみに新着はhometimelineの一番上の発言内容が、以前と異なるかどうかで判断w
なにかいい方法あればいいんですが。
API制限を考えるとhometimelineの取得間隔はそれなりに考えものです。

マニフェスト情報

・サービスを別プロセスにする
<service android:name="クラス名" android:process=":適当な名称">
ちなみにコロンは必須のようです。
ぶっちゃけ別プロセスにしなくても動きますが、本曰くアクティビティと異なるプロセスで動作させることで、
『アクティビティのみを停止させることができ、メモリの節約が期待できます。』
とのことです。
まあ、なんか別プロセスの方がサービスぽいですしね。


新着があると通知が


開くとこんな感じ


通知バーから起動


アクティビティが起動しているあいだは、新着があってもステータスバーへの通知はなし



アイコンがノーマルってのが悲しいですね。
ここまで来るとアイコンを作成する能力が少しでも欲しい・・・。
ちなみに実機で動作させると、認証とかに意外と時間がかかります。
認証中とかに「通信中・・・」みたいなダイアログ出したり、発言が反映したことをアクティビティに伝えるetc細かい機能が欲しくなります。


参考 「Android プログラミング入門」

  • 第二部 3.5.2 ノーティフィケーションを使ってBMIの計算結果を通知する
  • 第二部 第4章 サービス


追記
上記で別プロセスの場合コロンは必須と書きましたが(ていうか本にそう書いてあったが)、正しくは

  • 「同一パッケージ内のコンポーネントしか実行できないプライベートなプロセスとして」別プロセスを作る場合
というような感じのときにはコロンを頭において適当な名前を付けるようです。(と別の章で書いてありました)
プライベートなプロセスとグローバルなプロセスを、アプリによっては使い分ける必要があるんでしょうが、とりあえずそんな高度(?)なアプリはまだ作らないんでその辺は曖昧で( ^ω^)・・・
参考 「Android プログラミング入門」
  • 第四部 1.2.1 プロセスの共有

0 件のコメント:

コメントを投稿