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

如有转载,请申明:

转载至 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);

 

最后是解除绑定。

你可能感兴趣的:(android开发)