如有转载,请申明:
转载至 http://blog.csdn.net/qq_35064774/article/details/52578933
安卓的Service有两种启动方式,startService的方式非常简单,但相应的不能调用Service中的方法;而bindService的方式虽然复杂,但可以方便的调用Service中的方法。下面我们来介绍一下如何实现。
要开启服务,首先需要创建一个Service类。
下面是具体的Service实现类,看起来很多,但理解清楚后,发现还是很简单。
public class QuickStartService extends Service {
/**
* 绑定服务的时候会调用
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return new Agent();
}
/**
* 服务创建时调用
*/
@Override
public void onCreate() {
super.onCreate();
System.out.println("service onCreate");
}
/**
* 通过startService启动服务时调用
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("service onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
/**
* 服务销毁时调用
*/
@Override
public void onDestroy() {
super.onDestroy();
System.out.println("service onDestroy");
}
/**
* 自己编写的服务中的方法,我们需要在启动服务后,特定时间调用
* @param name
*/
public void serviceMethod(String name) {
System.out.println("service serviceMethod");
Toast.makeText(QuickStartService.this, name + "你好,你的证已经办好了", Toast.LENGTH_SHORT).show();
}
/**
* 对外公开的服务方法调用接口
*/
public interface IService {
void callServiceMethod(String name, int money);
}
/**
* 服务类中私有的代理类,可以直接与服务类相互调用的类,但同时实现了IService接口,所以把该对象传递给外部时,外部看起来就是一个IService的实现类
* 使用的是双接口的java技巧实现 对外公开部分方法
*/
private class Agent extends Binder implements IService{
@Override
public void callServiceMethod(String name, int money) {
if(money < 150) {
Toast.makeText(QuickStartService.this, "对不起 " + name + ",您不符合要求", Toast.LENGTH_SHORT).show();
return;
}
serviceMethod(name);
}
}
}
首先onBind方法是继承Service后必须实现的抽象方法。这个方法的职责也很简单,就是把代理对象暴露给外界。
然后是Service的生命周期方法onCreate onStartCommand onDestroy
这几个方法里面,基本算是空实现,如果不清楚Service生命周期,可以看我另外的一篇专门介绍了。
除了上述方法,最后还剩下一个自己编写的serviceMethod方法,这个方法也很简单,就是Toast提示用户证已经办好了。
但是到这里还没结束,既然我们要调用自己编写的serviceMethod,而外界又拿不到启动后的服务的引用,我们只能通过“秘书”来实现了。
上面代码中的Agent 类就是这样一个“秘书”,它继承了Binder类,因此可以在onBind方法中返回Agent对象。并且还实现了IService,这样外界拿到Agent后,只能当作一个IService来使用,因为Agent是服务的内部私有类。而这里的IService接口的作用就不言而喻了。
到这里,服务类编写完成。我们还需要一个外部类来绑定服务,调用服务中的方法。(相应的xml就不贴了,就三个Button)
public class ServiceQuickStartActivity extends AppCompatActivity implements View.OnClickListener {
private QuickStartService.IService agent;
private MyConnection connection;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_quick_start);
init();
}
/**
* 控件事件绑定
*/
private void init() {
findViewById(R.id.btn_bind_service).setOnClickListener(this);
findViewById(R.id.btn_call_service_method).setOnClickListener(this);
findViewById(R.id.btn_unbind_service).setOnClickListener(this);
}
/**
* 控件点击事件
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_bind_service:
bindService();
break;
case R.id.btn_call_service_method:
callServiceMethod();
break;
case R.id.btn_unbind_service:
unbindService();
break;
}
}
/**
* 调用服务中的方法,注意,需要先绑定服务
*/
private void callServiceMethod() {
if(null == agent) {
Toast.makeText(ServiceQuickStartActivity.this, "请先绑定服务", Toast.LENGTH_SHORT).show();
return;
}
agent.callServiceMethod("小明", 180);
}
/**
* 绑定服务,根据参数设置,可以在绑定时开启服务
*/
private void bindService() {
if(null != connection) {
Toast.makeText(ServiceQuickStartActivity.this, "您已经绑定了服务,请勿重复绑定", Toast.LENGTH_SHORT).show();
return;
}
connection = new MyConnection();
Intent intent = new Intent(this, QuickStartService.class);
if (bindService(intent, connection, Context.BIND_AUTO_CREATE))
Toast.makeText(ServiceQuickStartActivity.this, "绑定服务并开启成功", Toast.LENGTH_SHORT).show();
else
Toast.makeText(ServiceQuickStartActivity.this, "绑定服务失败", Toast.LENGTH_SHORT).show();
}
/**
* 取消绑定服务
*/
private void unbindService() {
if(null == connection) {
Toast.makeText(ServiceQuickStartActivity.this, "服务还未绑定", Toast.LENGTH_SHORT).show();
return;
}
unbindService(connection);
connection = null;
// 由于connection中的onServiceDisconnected方法只有在连接异常中断时才会调用,所以在解绑的时候,也要把代理对象置空
if(null != agent) {
agent = null;
}
Toast.makeText(ServiceQuickStartActivity.this, "取消绑定服务成功", Toast.LENGTH_SHORT).show();
}
/**
* 绑定服务的连接类
*/
private class MyConnection implements ServiceConnection {
/**
* 当与服务连接的调用
* @param name
* @param service
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 连接成功后,会把代理人传递过来
agent = (QuickStartService.IService) service;
System.out.println("onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name) {
agent = null;
System.out.println("onServiceConnected");
}
}
}
这个类看起来也有点多,但其实核心的是三个方法bindService callServiceMethod unbindService和一个类 MyConnection。
首先,为了能够绑定服务,我们需要一个连接类MyConnection ,这里的方法是实现ServiceConnection接口的方法,onServiceConnected是当连接成功的时候,回调的方法,它负责把内部传递的代理类保存起来,onServiceDisconnected则是当连接断开时回调的。
有了连接类,我们就可以在bindService方法中绑定服务了,bindService(intent, connection, Context.BIND_AUTO_CREATE);调用这么一个api,就可以绑定服务,并自动开启。
剩下的是调用服务中的方法callServiceMethod,这个方法其实只是调用了保存的代理类对象的方法agent.callServiceMethod("小明", 180);
最后是解除绑定。