Serviceとバインドするテスト


2014年4月23日現在、私が理解している内容です。
間違っている場合があります。


アクティビティからサービスに情報を送りたい

バインドというしくみを使うと、サービスに情報を渡すことができます。
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<RunningServiceInfo> 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<String> serviceList = new ArrayList<String>(); ActivityManager activityManager = (ActivityManager)getSystemService(ACTIVITY_SERVICE); // 起動中のサービス情報を取得 List<RunningServiceInfo> runningService = activityManager.getRunningServices(100); if(runningService != null) { for(RunningServiceInfo srvInfo : runningService) { serviceList.add(srvInfo.service.getShortClassName()); } } ArrayAdapter<String> adapter = new ArrayAdapter<String>(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情報伝達成功");」

















戻る