ServiceからActivityへ情報を渡す

実際には、直接叩く(アクセス)するのではなくて、カスタムしたレシーバーを使って行う方法について書きます。以下のコードを試すときは、ServiceクラスをManifestファイルに追記することをお忘れなく…。

動作確認したコードをコピペしたので、問題なく動作するはずです。

ポイントとしては…

  • DO_ACTION、の文字列は、独自レシーバーの判別に使うものです。オリジナルで構いません。
  • カスタムしたレシーバー(以下ではUpdateReceiver)は、別ファイルでも構いません。
  • message、という文字列に紐付けて、文字列を渡すサンプルになっています。文字列に限らず、booleanやintなども渡せますが、その例は省きます。
  • 本サンプルは、ボタンを押すと「こんにちは」をToastするだけですから、これ自体は単純にServiceに実装しても表面上は同じ動きをします。このサンプルのミソは、Service側でいろんな処理をしていて、ある条件+タイミングでActivity側にトリガーをかけたいときの手段の1つとして考えてもらえればいいと思います。
  • 自分で書いているコードでは、Service側の動作状態をテキストファイルに書き込んでいるのですが、書き込んだらActivityに通知を出して(本サンプルの構造を利用)ListView内部のTextViewを更新する、ということをやっています。

Activity

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout ll = new LinearLayout(this);
        Button btn = new Button(this);
        btn.setText("start");
        ll.addView(btn);
        setContentView(ll);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent service = new Intent(getApplicationContext(), TestService.class);
                startService(service);
            }
        });
        // receiver
        UpdateReceiver receiver = new UpdateReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("DO_ACTION");
        registerReceiver(receiver, filter);
    }
    protected class UpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent){
            Bundle extras = intent.getExtras();
            String msg = extras.getString("message");
            Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
        }
    }
}

Service

NullableはAndroidStudioが自動で入れたものなので、気にしないでください。

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class TestService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    public int onStartCommand(Intent intent, int flags, int startId){
        sendMessage("こんにちは");
        stopSelf();
        return START_NOT_STICKY;
    }
    protected void sendMessage(String msg){
        Intent broadcast = new Intent();
        broadcast.putExtra("message", msg);
        broadcast.setAction("DO_ACTION");
        getBaseContext().sendBroadcast(broadcast);
    }
}