Android三种绑定Service方式的demo

Android的Service提供给我们强大的后台处理能力,并可以用其进行IPC,鄙人看了看官方文档,总结了下文档提到的三种绑定Service的方式,并根据提供的样例整合写了自己的一个demo,来试试自己对基本使用的掌握。

好了,就废话这些,下面切入我的小demo,界面如下——Android三种绑定Service方式的demo_第1张图片

1、bindlocal按钮式绑定一个本地服务,即在同一进程、同一个app内的Service,calculate按钮调用绑定的本地服务,把最上面两个edittext的用户输入数字得到做计算;

2、bindremote(Messenger)按钮绑定一个远程服务(即不在同一个进程内),但是是线程不安全的,所有的调用都是以消息队列形式发出,who R U是绑定后调用这个远程服务;

3、bindremote(AIDL)按钮是用aid机制l绑定一个远程服务,这样是线程安全的,绑定完成后立即调用了该服务的两个方法;


这样看来,这个demo就有两个工程,一个包括三种服务的客户端及本地服务,另一个包括两个远程服务(没有界面);

对了,这里我嫌每次写Toast麻烦,定义了

public void T(String txt) {
		Toast.makeText(this, txt, Toast.LENGTH_SHORT).show();
	}


下面先看第一组功能——本地服务:

服务的源码如下,注意千万不要忘了在Manifest中声明

public class CalcService extends Service {

	private final IBinder calcBinder=new CalcBinder();
	public class CalcBinder extends Binder{
		public CalcService getService(){
			return CalcService.this;
		}
	}
	@Override
	public IBinder onBind(Intent intent) {
		return calcBinder;
	}
	
	public int sum(int a,int b){
		return a+b;
	}

}
 

在Activity中绑定的方法如下:

public void bindLocal(View v) {
		Intent bind = new Intent(this, CalcService.class);
		connection = new ServiceConnection() {
			@Override
			public void onServiceDisconnected(ComponentName name) {
				T("local binder disconnected");
			}

			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {
				T("local binder connected");
				localServie = ((CalcBinder) service).getService();
			}
		};
		bindService(bind, connection, Context.BIND_AUTO_CREATE);
	}

绑定完成调用的方法如下,这里et1和et2就是最上面两个edittext啦:

public void calc(View v) {
		try {
			int a = Integer.parseInt(et1.getText().toString());
			int b = Integer.parseInt(et2.getText().toString());
			T("result:" + localServie.sum(a, b));
		} catch (NumberFormatException e) {
			T("illegal format");
			e.printStackTrace();
		}
	}

这样就完成了,当然一般最好用完解绑——

public void unbind(View v) {
		if (connection != null)
			unbindService(connection);
	}



好了,下面看第二组功能,这个和平时我们处理UI线程与普通线程交互的操作很像,先是服务端,这个是在demo2,是另一个应用!

也就是说要重建一个新的Android工程,写个Service,代码如下:

package com.lttclaw.servicedemo2;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.widget.Toast;

public class RemoteServiceCalc extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		return new Messenger(new IncomingHandler()).getBinder();
	}

	class IncomingHandler extends Handler{
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case 0:
				Toast.makeText(getApplicationContext(), "I am far away ", Toast.LENGTH_LONG).show();
				break;
			default:
				break;
			}
			super.handleMessage(msg);
		}
	}
}

别忘了加Manifest里哦!

 


然后客户端,即demo1,绑定服务的方法是这样的,当然如果你嫌显示调用麻烦,可以给远程Service加一个Action,然后用action调用
public void bindMessenger(View v) {
		Intent messengerbinder = new Intent();
		messengerbinder.setComponent(new ComponentName(
				"com.lttclaw.servicedemo2",
				"com.lttclaw.servicedemo2.RemoteServiceCalc"));
		connection = new ServiceConnection() {
			@Override
			public void onServiceDisconnected(ComponentName name) {
				T("messenger binder disconnected");
			}

			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {
				T("messenger binder connected");
				messenger = new Messenger(service);
			}
		};
		bindService(messengerbinder, connection, Context.BIND_AUTO_CREATE);
	}
调用服务的方法是这样的

public void who(View v) {
		if (messenger == null)
			return;
		Message msg = Message.obtain();
		msg.what = 0;
		try {
			messenger.send(msg);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}



最要紧的,是第三组功能,做这个折磨了我一个多小时,文档有些地方写得并不清楚,这里我也不知道能不能讲明白。

最重要的一点是要写一个.aidl的文件,并且这个文件在客户端和服务端(在我这儿就是demo1和demo2中放在同一个路径下),我贴个图说明

Android三种绑定Service方式的demo_第2张图片

好了,先写服务端,即demo2的aidl文件,这里aidl有些类型规范什么的想了解的可以查资料,我就不说详细的了(其实我不会……)写了个很简单的接口文件,长这个样子

package com.lttclaw.aidl;
interface RemoteAIDL{
int factorial(int a);
void introduce();
}

写好后编译器会在gen下面生成一个对应的java文件,有兴趣可以看看,反正我是看得一头雾水~_~  然后我们来写一下这个接口的实现,这里真名叫RemoteAIDLImpl其实是个Service,代码如下:

package com.lttclaw.aidl;

import com.lttclaw.aidl.RemoteAIDL.Stub;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.Toast;

public class RomoteAIDLImpl extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	private final RemoteAIDL.Stub mBinder=new Stub() {
		
		@Override
		public void introduce() throws RemoteException {
			Toast.makeText(getApplicationContext(), "aidl", Toast.LENGTH_LONG).show();
		}
		
		@Override
		public int factorial(int a) throws RemoteException {
			if(a<1) return 0;
			int result;
			for(result=1;a>1;a--)
				result*=a;
			return result;
		}
	};
}
主要就是实现那个aidl的stub并将一个实例丢给onBind返回值。记得Manifest哟!

 
            
                
                
            
        
这里我不胜其烦,为其加上了action,以方便跨进程调用

好啦,再回到客户端,也就是demo1中,先把刚才的.aidl文件复制到一个一样的包路径下,见示例图,然后就会在gen下面也生成一个对应的java文件了,然后我们看绑定服务 的方法:

public void bindAIDL(View v) {
		Intent bindaidl=new Intent();
		bindaidl.setAction("com.lttclaw.aidl");
		connection=new ServiceConnection() {
			@Override
			public void onServiceDisconnected(ComponentName name) {
				
			}
			
			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {
				T("aidl bind");
				RemoteAIDL serviceAidl=RemoteAIDL.Stub.asInterface(service);
				try {
					T("result:"+serviceAidl.factorial(8));
					serviceAidl.introduce();
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
		};
		bindService(bindaidl, connection, Context.BIND_AUTO_CREATE);
		
	}

这里我犯懒了,不想把调用单独写方法了,绑定成功后直接调用了他的两个方法~~好了,这对犯二的例子就这么多,希望你能有所收获,不过话说回来,不管你有没有收获,反正我是有的,呵呵~





你可能感兴趣的:(android,service)