ActivityからServiceへのアクセス

先日Kindleで購入したAndroid本で、気になる内容があったので整理しておきたいと思います。

単純にServiceクラスを実装して実行した時、Serviceクラス内のメソッドには通常アクセスできません。一応、static定義したメソッドならアクセスできないこともないですが、それは言語的には推奨ではないみたいで。

以下に示したのは、ActivityとしてMainActivity、ServiceとしてTestSeriveというクラスを定義したときに、最低限実装する内容を示しています。この実装を行った状態においては、Serviceクラス内に定義したメソッドにActivityからアクセスできるようになります。

以下の例では、onPause内でインスタンス経由でServiceを停止させ、その後Bindを解除するという記述になっていますが、ここのところは個々のアプリケーションの仕様に依存する部分ですので、真似なくていいと思います。よくわからなければ真似ておいていいですが、真似ると、onPauseに入るとServiceを停止させてしまうため、ずっとServiceを動かしておくアプリケーションでは困りますよね。この辺はご注意ください。

以下のコードは、Android Studioに書いたコードをコピペしているので、そのようなフォント、色分けになっています。

MainActivity.java

public class MainActivity extends Activity {
    private TestService mServiceBinder;
    private ServiceConnection myConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            mServiceBinder = ((TestService.MyBinder) binder).getService();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mServiceBinder = null;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void doBindService(){
        Intent intent = new Intent(this, TestService.class);
        bindService(intent, myConnection, Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onResume(){
        super.onResume();
        if(mServiceBinder==null){
            doBindService();
        }
        startService(new Intent(getApplicationContext(), TestService.class));
    }
    @Override
    protected void onPause(){
        super.onPause();
        if(mServiceBinder != null){
            //mServiceBinder.stopSelf();
        }
        unbindService(myConnection);
        mServiceBinder = null;
    }
}

TestService.java

public class TestService extends Service {
    private static final String TAG = TestService.class.getSimpleName();  //What is this?
    private final IBinder mBinder = new MyBinder();
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
    public class MyBinder extends Binder {
        TestService getService() {
            return TestService.this;
        }
    }
    @Override
    public void onCreate(){
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        Toast.makeText(getApplicationContext(), "Service enabled", Toast.LENGTH_SHORT).show();
        Log.d("DBG", "Service running OK");
        return START_NOT_STICKY;
    }
}