猫型iPS細胞研究所

Windows、Linux、iOS、DB、Network

Android

バインドを利用したservice

投稿日:2013年3月8日 更新日:

バインドを利用しないserviceもありますが、serviceは勝手に動き続けるか、自動的に停止するようにするかになります。
実際にはバインドを利用してserviceが起動している時にもアクションを連携できるようにしないと使い道は少なくなってしまいます。

アクティビティとsrvcie間で利用するにはaidlファイルを作成し、インターフェイスを記載しておく必要があります。

バインドするまでの流れ

1.(アクティビティ)bindServiceメソッドを実行
   ※BIND_AUTO_CREATEを設定

2.(service)onCreate実行

3.(service)onBind実行で、serviceのAIDLオブジェクトをリターン。

4.(アクティビティ)onServiceConnected実行。
   引数にあるIBinderから、serviceのAIDLオブジェクトが取得でき、serviceにアクセスできるようになります。

5.(アクティビティ)serviceのAIDLインターフェイスで作成したstartService実行しアクティビティのAIDLオブジェクトを渡す。

6.(serivce)アクティビティのAIDLオブジェクトを受け取り、アクティビティにアクセスできるようになる。

・・・(任意のやりとり)・・・

7.(アクティビティ)serviceのAIDLインターフェイスで作成したendService実行し、servcieの終了処理実行。

8.(アクティビティ)unbindService実行でバインドも終了。

ServiceConnectionインターフェイスを実装したコネクションを、アクティビティからservcieにbindServiceメソッドで渡します。serviceではonBindでservcieのAIDLオブジェクトを返します。その後アクティビティではserviceのAIDLオブジェクトを利用して、アクティビティのAIDLオブジェクトを渡します。

2重のやりとりが行われた後に初めて相互に連携するので、ややこしくてしかたありません。

サービスにはAndroidManifest.xmの登録が必要です。

ソース

com/neko/mytimer/MytimerActivity.java

package com.neko.mytimer;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MytimerActivity extends Activity {
	
	private MyServiceAIDL bindserviceIf = null;
	private MyConnection conn =null;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button btnstart = (Button)findViewById(R.id.btnstart);
        btnstart.setOnClickListener(new startListener());
        
        Button btnend = (Button)findViewById(R.id.btnend);
        btnend.setOnClickListener(new endListener());
    }
    
    class startListener implements OnClickListener{

		public void onClick(View v) {
			Intent intent = new Intent(MyServiceAIDL.class.getName());
			conn=new MyConnection();
			//1.バインド
			bindService(intent, conn, BIND_AUTO_CREATE);
		}
    }
    
    class endListener implements OnClickListener{
		public void onClick(View v) {
			try {
				bindserviceIf.endService(bindactibityIf);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			unbindService(conn);
		}
    	
    }
    
    //ServiceConnectionの実装
    class MyConnection implements ServiceConnection{
		//4.onServiceConnected
		public void onServiceConnected(ComponentName arg0, IBinder arg1) {
			bindserviceIf = MyServiceAIDL.Stub.asInterface(arg1);
			try {
				//5.サービスのADILオブジェクトを使ってアクティビティのAIDLオブジェクトを渡す
				bindserviceIf.startService(bindactibityIf);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}

		public void onServiceDisconnected(ComponentName arg0) {
			try {
				bindserviceIf.endService(bindactibityIf);
			} catch (RemoteException e) {
				e.printStackTrace();
			}
			bindserviceIf = null;
		}
    }
    
    //アクティビティのADILオブジェクトの実装
    private MytimerActivityAIDL bindactibityIf = new MytimerActivityAIDL.Stub() {
		public void displayTime(String spantime) throws RemoteException {
			handler.sendMessage(Message.obtain(handler,0,spantime));
		}
	};
	//スレッドなのでhanlderを使用
	private Handler handler = new  Handler(){
		public void handleMessage(Message msg){
			TextView tv =(TextView)findViewById(R.id.textview1);
			tv.setText((String)msg.obj);
		}
	};
	
	
}

com/neko/mytimer/MytimerActivityAIDL.aidl

package com.neko.mytimer;

interface MytimerActivityAIDL {
	void displayTime(String spantime);
}

com/neko/mytimer/MyService.java

package com.neko.mytimer;

import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class MyService extends Service{
	
	private Timer timer=null;
	private MytimerActivityAIDL callback =null;
	private int counter = 0;

	//2.onCreateはonBindの前に呼ばれる
	@Override
	public void onCreate(){
		super.onCreate();
		
		timer = new Timer();
		timer.schedule(task,1000,1000);
	}
	
	//3.onBindで、servcieのAIDLオブジェクトをリターンしている。
	@Override
	public IBinder onBind(Intent intent) {
		if(MyServiceAIDL.class.getName().equals(intent.getAction())){
			return serviceIf;
		}
		return null;
	}
	
	@Override
	public boolean onUnbind(Intent intent){
		timer.cancel();
		timer.purge();
		return super.onUnbind(intent);
	}
	
	//serviceのAIDLの実装
	private MyServiceAIDL.Stub serviceIf = new MyServiceAIDL.Stub() {
		//6.startServiceの引数でアクティビティのAIDLオブジェクトを受信
		public void startService(MytimerActivityAIDL callback)
				throws RemoteException {
			MyService.this.callback = callback;
		}
		
		public void endService(MytimerActivityAIDL callback) throws RemoteException {
			MyService.this.callback=null;
		}
	};
	
	private TimerTask task = new TimerTask() {
		
		@Override
		public void run() {
			counter += 1;
			try {
				//アクティビティのADILオブジェクトを使っている
				callback.displayTime(counter+"秒");
			} catch (RemoteException e) {
				e.printStackTrace();
			}
		}
	};

}

com/neko/mytimer/MyServiceAIDL.aidl

package com.neko.mytimer;

import com.neko.mytimer.MytimerActivityAIDL;

interface MyServiceAIDL {
	void startService(MytimerActivityAIDL callback);
	void endService(MytimerActivityAIDL callback);
}

main.xml(レイアウト)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView 
        android:id="@+id/textview1"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:text="0"
        android:textSize="46px"
        />
    <LinearLayout 
        android:orientation="horizontal" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        >
    <Button 
        android:id="@+id/btnstart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btnstart"
        />
    <Button 
        android:id="@+id/btnend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btnend"
        />
    </LinearLayout>
</LinearLayout>

AndroidMAnifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.neko.mytimer"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".MytimerActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        
        <service android:name="MyService">
            <intent-filter>
                <action 
                    android:name="com.neko.mytimer.MyServiceAIDL"/>
            </intent-filter>
            
        </service>
    </application>

</manifest>

Gooleアドセンス用336

Gooleアドセンス用336

-Android
-

執筆者:

関連記事

match_parentとwrap_content

wrap_contentは幅を自動調整します。 match_parentは画面いっぱいに表示させます。 match_parentはAndroid2.2(API Label 8)以降で、fill_par …

アクティビティ間の画面遷移

アクティビティから別のアクティビティを呼びだすと、新しいアクティビティは上に重ねられた状態になり、今まで使用していたアクティビティは停止します。 そして新しいアクティビティが終了すると、元のアクティビ …

Micro USB の充電用とデータ転送用

以前 「SonyEricssonXPERIA SO-01Bのドライバのインストール」 というものを書きました。 このどうしようもない端末は、MicroUSBにも問題があります。 しかもこの端末、古すぎ …

SonyEricssonXPERIA SO-01Bのドライバのインストール

二度とこの古い機種を接続することはないと思うのですが、 それだけに貴重な情報と思いメモしておきます :x002: adb で確認するとどうしても認識されません。 >adb devices Lis …

ListView(2行)

ListViewの各行に2行表示させるには、ListActivityをextendします。 また、かくリストのデータはmapで設定します。 TestActivity.java package com. …