例によって、マニュアルを読むと解決することが半分。
ソース落として中身をしっかり見れば解決するであろうことが半分。
とりあえず後者に関する内容です。
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 件のコメント:
コメントを投稿