スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Android Serviceで困ったこと



例によって、マニュアルを読むと解決することが半分。
ソース落として中身をしっかり見れば解決するであろうことが半分。
とりあえず後者に関する内容です。


bindService() 直後にはサービスを利用できない。


具体例としては以下のようなやつはNG


private IService service;
private ServiceConnection conn = new ServiceConnection() {

	public void onServiceConnected(ComponentName arg0, IBinder arg1) {
		// TODO 自動生成されたメソッド・スタブ
		service = IService.Stub.asInterface(arg1);
	}

	public void onServiceDisconnected(ComponentName arg0) {
		// TODO 自動生成されたメソッド・スタブ
		service = null;
	}
};


private void onChk1(){
	Intent intent = new Intent(IService.class.getName());
	bindService(intent, conn, BIND_AUTO_CREATE);
	service.serviceAPI(); // ここで落ちます
}

ようはbindService を呼んですぐにonServiceConnected() まで到達しないということです。
上記のような場合、onChk1 を完全に抜けてからでないと絶対に到達しませんでした。
以下NG集



private void onChk2(){
	Intent intent = new Intent(IService.class.getName());
	bindService(intent, conn, BIND_AUTO_CREATE);
	
	while( service != null){ // 無限ループに陥る
		wait(1000);
	}
	service.serviceAPI(); 
}


private void onChk3(){
	Intent intent = new Intent(IService.class.getName());
	bindService(intent, conn, BIND_AUTO_CREATE);
	
	new Thread(){ // スレッド化しても無駄
		@Override
		public void run() {
			while( service != null){ // 無限ループに陥る
				wait(1000);
			}
			service.serviceAPI();
		}
	}.start();
}

ちなみにbindService と service.serviceAPI を別関数化し、スレッド化して呼んでもダメなものはダメでした。
もちろんonChk3 のようなスレッドの作り方が良くないのかもしれませんが。
その辺、javaに詳しい人なら即座に解決策がでるんでしょうか?


では、なんでこんなことをしようと思ったかと言うと、
・onCreate / onResume 時に サービスから初期値を取得したい
という状況が発生したからです。
一応以下の方法でそれっぽくなりますが、なんかもっと簡単な方法ないものでしょうか。
完全解決という感じではないし。
自分でメッセージループ管理しだすと、VCチックな感じも・・・。
ただ、この面倒な感じは、BREWアプリを想像させるような・・・。
まあBREWなんかと比較したら失礼ですね。あれはマジ終わってる。


onCreate でサービスをバインドし、初期値もサービスから取得っぽく実装


private IService service;
private ServiceConnection conn = new ServiceConnection() {
	// 略
};

private static final int _MY_BIND_SERVICE = 1;
private static final int _MY_INIT_DATA = 2;
private Handler mHandler = new Handler(){
	@Override
	public void dispatchMessage(Message msg) {
		// TODO 自動生成されたメソッド・スタブ
		switch( msg.what){
		case _MY_BIND_SERVICE:
			removeMessages(_MY_BIND_SERVICE);
			_bind();
			break;
		case _MY_INIT_DATA:
			removeMessages(_MY_INIT_DATA);
			_init_data();
			break;
		default:
			super.dispatchMessage(msg);
		}
	}
};


public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	mHandler.sendEmptyMessage(_MY_BIND_SERVICE);
	mHandler.sendEmptyMessage(_MY_INIT_DATA);
}

private void _bind(){
	if( service != null){
		return;
	}
	Intent intent = new Intent(IService.class.getName());
	bindService(intent, conn, BIND_AUTO_CREATE);
}

private void _init_data(){
	if(service == null){
		mHandler.sendEmptyMessage(_MY_BIND_SERVICE);
		mHandler.sendEmptyMessageDelayed(_MY_INIT_DATA, 500);
		return;
	}
	service.serviceAPI(...);
	// 略
}

	

・・・。
改めて書くとなんと強引な・・・。
しかもあくまで「onCreate内でやってるっぽい」だけで、普通にonCreateそのものは終わってますから。
そういう意味では完全解決ではありませんね。
removeMessagesを読んでいるのは、処理が重複しないように念のために呼んでいるだけです。


関連記事

テーマ : グーグルモバイル
ジャンル : 携帯電話・PHS

tag : android サンプルソース

コメントの投稿

非公開コメント

プロフィール

駄猫

Author:駄猫

Twitter
その他
最新記事
カテゴリ
月別アーカイブ
検索フォーム
RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。