安卓Service绑定方式启动服务并调用服务中的方法

来源:互联网 发布:联通数据卡流量查询 编辑:程序博客网 时间:2024/04/30 09:04

如有转载,请申明:

转载至 http://blog.csdn.net/qq_35064774/article/details/52578933


安卓的Service有两种启动方式,startService的方式非常简单,但相应的不能调用Service中的方法;而bindService的方式虽然复杂,但可以方便的调用Service中的方法。下面我们来介绍一下如何实现。

 

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接口的作用就不言而喻了。

 

 

绑定的Activity

到这里,服务类编写完成。我们还需要一个外部类来绑定服务,调用服务中的方法。(相应的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);

 

最后是解除绑定。

1 0
原创粉丝点击