例によって、マニュアルを読むと解決することが半分。
ソース落として中身をしっかり見れば解決するであろうことが半分。
とりあえず後者に関する内容です。
bindService() 直後にはサービスを利用できない。
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 を完全に抜けてからでないと絶対に到達しませんでした。
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なんかと比較したら失礼ですね。あれはマジ終わってる。
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を読んでいるのは、処理が重複しないように念のために呼んでいるだけです。
0 件のコメント:
コメントを投稿