アクティビティからサービスに情報を送りたい
バインドというしくみを使うと、サービスに情報を渡すことができます。
「Serviceの実行状態を監視するテスト」のコードを改造していきます。
まず、Serviceの「MyServiceS1.java」に、以下のように書き加えます。
「public IBinder onBind(Intent arg0) {〜」の戻り値を忘れるとエラーになりますので、注意しましょう。
private final IBinder mBinder = new LocalBinder();
public class MyLocalBinder extends Binder {
MyServiceS1 getService() {
return MyServiceS1.this;
}
}
| |
@Override
public IBinder onBind(Intent arg0) {
// TODO 自動生成されたメソッド・スタブ
//(注意)必ず戻り値を指定すること
return mBinder;
}
| |
以上が必要な記述で、
こちらは、サービス側が情報を受け取ったことを確認するためのテスト用コードです。
public void TestMessage1(String message1) {
//トースト表示
Toast.makeText( getBaseContext(), message1, Toast.LENGTH_LONG).show();
}
| |
MyServiceS1.java
package com.example.test23;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class MyServiceS1 extends Service {
private final IBinder mBinder = new LocalBinder();
public class MyLocalBinder extends Binder {
MyServiceS1 getService() {
return MyServiceS1.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public IBinder onBind(Intent arg0) {
// TODO 自動生成されたメソッド・スタブ
//(注意)必ず戻り値を指定すること
return mBinder;
}
public void TestMessage1(String message1) {
//トースト表示
Toast.makeText( getBaseContext(), message1, Toast.LENGTH_LONG).show();
}
}
| |
バインドを設定する
「MainActivity」にて、以下の記述を追加します。
private MyServiceS1 mMyService1;
private ServiceConnection mMyServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//サービスと接続する手続き
MyServiceS1.MyLocalBinder binder = (MyServiceS1.MyLocalBinder)service;
mMyService1 = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
//サービスと切断したとき
}
};
| |
バインドと接続するための記述。
Intent intent = new Intent(getApplicationContext(), MyServiceS1.class);
bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);
| |
バインドと接続解除するための記述。
unbindService(mMyServiceConnection);
| |
バインドに情報を送るテストのための記述。
mMyService1.TestMessage1("BIND情報伝達成功");
| |
実験用に、バインド用のボタンとかを追加します。
「onClick」の中で、上記の命令を呼び出します。
MainActivity.java
package com.example.test24;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Color;
public class MainActivity extends Activity {
private MyServiceS1 mMyService1; //バインド
private static final String ServiceName1 = MyServiceS1.class.getCanonicalName();
ListView setlistvw ;
private Timer mainTimer;
private MainTimerTask mainTimerTask;
private TextView countText1;
private int count1 = 0;
private Handler Handler1 = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//--------------------------------------------------
//レイアウトを作る
LinearLayout layout1 = new LinearLayout(this);
layout1.setOrientation(LinearLayout.HORIZONTAL); //横に並べる
//レイアウトの背景を緑にする
layout1.setBackgroundColor(Color.argb(128, 0, 255, 0));
//-----------------------------------------
//新しいボタンを作る
Button button1 = new Button(this);
button1.setText("OPEN");
layout1.addView(button1);
Button button2 = new Button(this);
button2.setText("CLOSE");
layout1.addView(button2);
//----------------------------
//新しいボタンを作る
Button button4 = new Button(this);
//ボタンに文字を表示
button4.setText("BIND");
button4.setTextSize(10.0f);
//ボタンをレイアウトに追加
layout1.addView(button4);
//新しいボタンを作る
Button button5 = new Button(this);
//ボタンに文字を表示
button5.setText("START");
button5.setTextSize(10.0f);
//ボタンをレイアウトに追加
layout1.addView(button5);
//新しいボタンを作る
Button button6 = new Button(this);
//ボタンに文字を表示
button6.setText("STOP");
button6.setTextSize(10.0f);
//ボタンをレイアウトに追加
layout1.addView(button6);
//----------------------------
Button button3 = new Button(this);
button3.setText("END");
//ボタンをレイアウトに追加
layout1.addView(button3);
//-----------------------------------------
//OPENボタンが押されたかどうか監視する
button1.setOnClickListener( new OnClickListener() {
//ボタンが押されたら何かする
@Override
public void onClick(View v) {
//サービスを呼び出す
startService(new Intent(MainActivity.this,MyServiceS1.class));
}
});
//-----------------------------------------
//CLOSEボタンが押されたかどうか監視する
button2.setOnClickListener( new OnClickListener() {
//ボタンが押されたら何かする
@Override
public void onClick(View v) {
//サービスを終了させる
stopService(new Intent(MainActivity.this, MyServiceS1.class));
}
});
//-----------------------------------------
//ENDボタンが押されたかどうか監視する
button3.setOnClickListener( new OnClickListener() {
//ボタンが押されたら何かする
@Override
public void onClick(View v) {
//自分を終了させる
finish();
}
});
//-----------------------------------------
//BINDボタンが押されたかどうか監視する
button4.setOnClickListener( new OnClickListener() {
//ボタンが押されたら何かする
@Override
public void onClick(View v) {
//サービスに送信する
mMyService1.TestMessage1("BIND情報伝達成功");
}
});
//-----------------------------------------
//STARTボタンが押されたかどうか監視する
button5.setOnClickListener( new OnClickListener() {
//ボタンが押されたら何かする
@Override
public void onClick(View v) {
//バインド開始
Intent intent = new Intent(getApplicationContext(), MyServiceS1.class);
bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);
}
});
//-----------------------------------------
//STOPボタンが押されたかどうか監視する
button6.setOnClickListener( new OnClickListener() {
//ボタンが押されたら何かする
@Override
public void onClick(View v) {
//バインド終了
unbindService(mMyServiceConnection);
}
});
//-----------------------------------------
//リストビュー
setlistvw = new ListView(this);
LinearLayout layout2 = new LinearLayout(this);
layout2.setOrientation(LinearLayout.VERTICAL); //縦に並べる
countText1 = new TextView(this);
layout2.addView(countText1);
layout2.addView(layout1);
layout2.addView(setlistvw);
setContentView(layout2);
//--------------------------------
//タイマー
this.mainTimer = new Timer();
this.mainTimerTask = new MainTimerTask();
this.mainTimer.schedule(mainTimerTask, 0,100);
//-----------------------------------------
}
//「ServiceName1」(MyServiceS1)のサービスが実行されてるかチェックする
private boolean CheckServiceRunning() {
checkServiceList1();
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List services = activityManager.getRunningServices(Integer.MAX_VALUE);
for (RunningServiceInfo info : services) {
if (ServiceName1.equals(info.service.getClassName())) {
return true;
}
}
return false;
}
@Override
protected void onResume() {
super.onResume();
CheckServiceRunning();
}
public void checkServiceList1(){
ArrayList serviceList = new ArrayList();
ActivityManager activityManager = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
// 起動中のサービス情報を取得
List runningService = activityManager.getRunningServices(100);
if(runningService != null) {
for(RunningServiceInfo srvInfo : runningService) {
serviceList.add(srvInfo.service.getShortClassName());
}
}
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, serviceList);
setlistvw.setAdapter(adapter);
}
public class MainTimerTask extends TimerTask {
@Override
public void run() {
Handler1.post( new Runnable() {
public void run() {
count1 += 1;
countText1.setText(String.valueOf(count1) + " <" + ServiceName1 + "> " + CheckServiceRunning());
}
});
}
}
//------------------------------------------------------------------
//バインド
private ServiceConnection mMyServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//サービスと接続する手続き
MyServiceS1.MyLocalBinder binder = (MyServiceS1.MyLocalBinder)service;
mMyService1 = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
//サービスと切断したとき
}
};
}
| |
バインドの使用上の注意
「OPEN」サービスを開始
「CLOSE」サービスを終了
「BIND」バインドでサービスに情報を送る
「START」バインドを開始
「STOP」バインドを解除
「END」アプリを終了
……と、なっていますが、むやみにボタンを押すと高い確率でエラーになります。
基本的に、「START」で、バインドを接続してない状態で、バインドを何かしようとすると落ちます。
「OPEN」でサービスを開始した場合、「START」でバインドを接続します。
「START」で、バインドを開始した場合は、
「bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE); 」が実行され、
「BIND_AUTO_CREATE」が指定されていることによって、自動的にサービスが開始され、バインドされます。
また、「START」で、サービス開始した場合は「STOP」で、サービスが終了します。
「OPEN」で、サービス開始した場合は「CLOSE」で、サービスが終了します。
それぞれ、サービスを呼ぶメソッドが違っているからです。
サービスのライフサイクルも違います。
「OPEN」の場合、「startService(new Intent(MainActivity.this,MyServiceS1.class));」
「START」の場合、「bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);」
「CLOSE」の場合、「stopService(new Intent(MainActivity.this, MyServiceS1.class)); 」
「STOP」の場合、「unbindService(mMyServiceConnection); 」
「BIND」で、サービスのメソッドを呼べます。「mMyService1.TestMessage1("BIND情報伝達成功");」