AndroidのServiceについて
2015/04/25 23:50:32Noranekoです。
『これから英語は必要だ!』とか、
『これからは国際社会、海外に目を向けろ!』とか言う人に限って、
海外滞在とか全くなくて、パスポートすら持ってないのが現実だょ^ω^
でファストフードマスターの私に言わせれば、
IN-N-OUTしか認めません!
今秋に『Carl's Jr.』も来るみたいだけど、また行列するんだろうな・・・
でもCarl's Jr.はメニューが多くて、LAで滞在してた近くにあったので、
しょっちゅう行ってました^ω^
一応タバコと比較してます。
ということで、アメリカのファストフードとかのお話はまた今度にしましょう。
前回のお話の続きになります。
バックグラウンドで常駐させたい
↓
いつのまにか死んでる
↓
Serviceにすればいいよ!
と、ここまで理解してて、その後サンプルソースから大改造してみました。
できました。
重要なところをまとめてみます。
①Activity等からServiceを起動させる為にAIDLを作成する。
②Serviceからの戻り値をBroadcastReceiverで取得する。
③BroadcastReceiverからさらにActivityへ値を戻す。
①について、前回ほんのり書いてますが、
ActivityからServiceを独立させて呼び出す為に、AIDLファイルという物を作って
そこからServiceを呼びます。
下準備として、
MainService.java
public class MainService extends Service{
}
}
IService.aidl
interface IService {
}
}
AndroidManifest.xml
<service android:name=".MainService">
<intent-filter>
<action android:name="net.hoge.IService" />
</intent-filter>
</service>
<intent-filter>
<action android:name="net.hoge.IService" />
</intent-filter>
</service>
自分の目的では、Activityが死んでもServiceを継続させたい為、
『onStartCommand』を使います。
直接使えないので、下記のようにします。
public class Hoge extends Activity{
public void test(){
// Serviceを実行
Intent intent = new Intent(IService.class.getName());
startService(intent);
}
}
public void test(){
// Serviceを実行
Intent intent = new Intent(IService.class.getName());
startService(intent);
}
}
もう一つのやり方は、
『ServiceConnection』を用いて、『bindService』を使うやり方です。
public class Hoge extends Activity{
private IService service = null;
private ServiceConnection con = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = IService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName className) {
}
 };
 public void test(){
  // サービス実行
  Intent intent = new Intent(IService.class.getName());
  // バインド
  bindService(intent, con, Service.BIND_AUTO_CREATE);
 }
}
private IService service = null;
private ServiceConnection con = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mService = IService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName className) {
}
 };
 public void test(){
  // サービス実行
  Intent intent = new Intent(IService.class.getName());
  // バインド
  bindService(intent, con, Service.BIND_AUTO_CREATE);
 }
}
後者は、Activityが死ぬとServiceも死んでしまいます。
ただ、サービスのいろいろなメソッドにアクセスできるので、
前者とは異なる使い方が可能です。
多分ここまでで???の方も多いと思いますが、
実行したいサービス(MainService.java)
と
実行したいサービスを起動するためのインターフェイス(IService.aidl)
があって、Activityから2パターンの呼び出しが可能で、
呼び出し方によりできることとできないことに分かれます。
うむ。
これは難しい。
とりあえず先に進もう。
②について、これは①の後者を選択してバインドした人には
あまり意味がないのかもしれません。
public class MainReceiver extends BroadcastReceiver{
}
}
MainReceiver.java
<receiver
android:name=".MainReceiver"
android:exported="false">
< /receiver>
AndroidManifest.xml
例によってこれを前提とします。
先程の①の前者を
public class Hoge extends Activity{
private MainReceiver receiver = null;
public void test(){
// Serviceを実行
Intent intent = new Intent(IService.class.getName());
startService(intent);
// レシーバ―登録
IntentFilter filter = new IntentFilter("hoge");
receiver = new MainReceiver();
registerReceiver(receiver, filter);
}
}
private MainReceiver receiver = null;
public void test(){
// Serviceを実行
Intent intent = new Intent(IService.class.getName());
startService(intent);
// レシーバ―登録
IntentFilter filter = new IntentFilter("hoge");
receiver = new MainReceiver();
registerReceiver(receiver, filter);
}
}
これだけです。
次に、MainServiceの何かを返すメソッドに
public void payBack(){
Intent intent = new Intent("hoge");
intent.putExtra("test", "test");
intent.putExtra("suji", 99);
sendBroadcast(intent);
}
Intent intent = new Intent("hoge");
intent.putExtra("test", "test");
intent.putExtra("suji", 99);
sendBroadcast(intent);
}
最後にMainReceiverに
public class MainReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent){
// 値を取得
String s = intent.getStringExtra("test")
int i = intent.getIntExtra("suji", 0)
System.out.println("this is broadcast @" + s + "@" + String.valueOf(i));
}
}
public void onReceive(Context context, Intent intent){
// 値を取得
String s = intent.getStringExtra("test")
int i = intent.getIntExtra("suji", 0)
System.out.println("this is broadcast @" + s + "@" + String.valueOf(i));
}
}
比較的わかりやすいですね。
③ここで悩みました。みんな②でToastで表示して終了が多いです!
ではなくて、私みたいにActivityに返したい人の方が多いはずです!
で、どっかのブログがひっかかり、無事、事なきを得ました。
先程のMainReceiverを改造します。
public class MainReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent){
// コンテキストを取得
HogeActivity activity = (HogeActivity) context;
// メソッドに渡す
activity.getValue(
intent.getStringExtra("test"),
intent.getIntExtra("suji", 0)
)
}
}
public void onReceive(Context context, Intent intent){
// コンテキストを取得
HogeActivity activity = (HogeActivity) context;
// メソッドに渡す
activity.getValue(
intent.getStringExtra("test"),
intent.getIntExtra("suji", 0)
)
}
}
なるほど。
流れを掴めば理解できると思いますが、やりたいこと以外の情報が多すぎるのと、
その先の情報がぶちぶち切れてて、結構時間がかかりました。
またServiceは生きたままでActivityが死んで、
再度アプリを立ち上げた際のロジックも考えて作らないと、
データに不整合が出る可能性もあるので、
結構頭を使います。
てことでちょっとテストしてみて、大丈夫ならGW中に更新したいと思っております!
気に入ったら押してね
~こんなアプリ出してます~