开启服务和绑定服务

普通服务

编写普通服务的步骤

  1. 定义一个类这个类继承Service

  2. 在清单文件中的节点下添加一个节点,里面的内容和配置activity时类似

  3. 启动这个service,用startService(content,xxxservice.class)

普通服务的生命周期

  • 完整的生命周期

onCreate【创建】—onStartCommand(onStart已经过时了)【启动】—onDestory【销毁】

  • 多次启动服务

多次启动服务并不会调用多次onCreate方法,但是会执行多次onStartCommand方法

  • 多次停止服务

服务一旦被停止,再次停止服务将不会有任何效果.

直接启动服务的缺陷

无法与服务进行通讯 ,没办法调用服务中的方法

所以服务还有另外一种启动方式,绑定服务,用来解决上面的问题

绑定服务

编写绑定服务的步骤:

绑定服务的步骤

  1. 定义服务
    public class ServcieDemo extends Service {}
  2. 注册服务

    <service android:name="com.itheima.bind.ServcieDemo"></service>
    
  3. 编写服务的方法

    /**
         * 录取通知书 
         * 服务中的内部方法
         */
        public void methodInService(String name , int money){
            if(money <= 100000){
                Toast.makeText(this, name+",你的钱不够.", 0).show();
            }else{
                Toast.makeText(this,name+"先生,您的中国人民大学本科录取通知书已经办妥了..", 0).show();
            }
        }
    
  4. 定义一个内部类

    /**
         * 内部招生老师,内部代理对象
         */
        class MyBinder extends Binder{
            /**
             * 内部人员中固有的方法,它的作用就让别人来访问它,然后它自己去访问服务中的方法。
             * 通过迂回的手段达到从外部类调用服务中的方法效果。
             * @param name
             * @param money
             */
             public void callMethodInService(String name , int money){
                 methodInService(name , money);
             }
        }
    
  5. 服务绑定后返回内部代理对象

    /**
         * 如果服务成功绑定上了,那么就返回一个通讯频道,
         * 返回一个内部人员,内部代理对象
         */
        @Override
        public IBinder onBind(Intent intent) {
            System.out.println("onBind");
            //返回内部代理对象
            return new MyBinder();
        }
    
  6. 在activity绑定服务

    //绑定服务
        public void bind(View v) {
            Intent service = new Intent(this , ServcieDemo.class);
            /**
             * 第一个参数:intent对象
             * 第二个参数:servcieConnection  用于监听服务当前的状态
             * 第三个参数:BIND_AUTO_CREATE 服务自动创建,然后绑定。
             */
            bindService(service, new MyConn(),  BIND_AUTO_CREATE);
        }
    
  7. 在onServcieConnected方法中获取到内部代理对象

    /**
         * 监听服务的状态,服务是启动还是停止都会收到信息。
         */
        class MyConn implements ServiceConnection{
            /**
             * 如果服务能够成功绑定上,那么这个方法将会调用,启动的参数service就是服务返回的内部对象 MyBinder
             */
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //获取到服务内部返回的代理对象 ,用binder承接起来
                binder = (MyBinder) service;
    
            }
            @Override
            public void onServiceDisconnected(ComponentName name) {}
        }
    
  8. 在其他地方调用内部对象中的方法

    //调用服务的方法
        public void call(View v) {
            //通过内部代理对象,调用内部 类中的方法,实际上是调用了服务中的方法
            binder.callMethodInService("张三丰", 1000000);
        }
    

绑定服务的生命周期

  • 完整的生命周期

onCreate【创建】—onBind【绑定】 –onUnBind【解除绑定】–onDesotry【销毁】

  • 多次绑定服务

不会调用任何服务中生命周期方法

  • 多次解绑

将会抛出服务没有注册的异常,因为服务的绑定和解绑是根据conn对象来解析的。

  • 多次绑定,一次解绑

将会抛出服务没有注册的异常

建议:服务绑定一次,解绑一次。

两种启动服务的区别

  • startService

生命周期: onCreate—onStartCommand—onDestory

与服务的通讯: 无法与服务进行直接通讯

与开启者的关系: 服务一旦开启与开启者(activity)将没有什么联系了,就算开启者销毁了,服务依然存活。

在设置界面中有显示

  • binderSerivce

生命周期: onCreate–onBind–onUnBind–onDestory

与服务通讯: 通过内部代理对象间接调用服务的方法

与开启者的关系: 一旦开启者销毁了,那么服务也将随之销毁。

在设置界面无显示

能不能让服务长期运行在后台,并且还能与服务进行通讯

  • startService : 让服务长期运行在后台,但是无法与服务进行通讯

  • bindServcie : 可以与服务进行通讯,但是无法长期运行在后台

混合开启服务,用来解决长期运行在后台,并与服务器进行通讯

  1. startService 启动服务
  2. bindService 绑定服务
  3. 调用服务的方法
  4. unBindService 解除绑定服务
  5. stopService 停止服务

注意:要混合的开启服务,就要严格的遵循上面的那些步骤,不然就会开启失败

上面的绑定属于本地服务,要开启远程服务,开启方式是基于绑定服务操作方式如下:

aidl远程服务调用(也就是跨进程服务)

编写本地服务类,编写步骤如下:
  1. 定义一个类,继承service

    public class RemoteService extends Service {...}
    
  2. 去注册这个Service,这次注册要用隐式注册,不能像本地访问服务那样注册了

    <service android:name="com.liuwen.remote.RemoteService">
        <intent-filter >
            <action android:name="com.liuwen.remote.action.HEIMAPAY"/>
        </intent-filter>
    </service>
    
  3. 定义你要在服务中运行的逻辑代码

    /**
     * 
    * @param name
    * @param password
    * @param money
    * @return 返回的是状态码,500:说明余额不足,404:账号或者密码 错误;200:支付成功
    */
    private int heiMaPay(String name,String password,int money){
        if(money>500){
        return 500;//说明余额不足
        }else if(!"张三".equals(name)||!"12345".equals(password)){
        return 404;//说明账号或者密码错误
    }
        return 200;//说明支付成功
    }
    
  4. 定义一个内部类,我们把这个类里面的方法通过一个自定义的接口暴露出去,然后隐藏这个内部类的实现细节,这个接口中定义的方法也就是我们想让外界访问的方法,然后我们再通过这些方法去调用外部类的方法,让最后来调用这个服务的类间接的可以访问服务里面的方法了.让这个内部类去继承Binder,实现自定义接口IService,

    //定义一个内部代理
    //定义一个接口,把这个类的方法给抽取出来,把这个类的实现给隐藏了
    class MyBind extends Binder implements IService{
        public int callHeimaPay(String name,String password,int money){
        //调用外部来的方法
        return heiMaPay(name, password, money);
        }
    }
    ---------------------------------------------
    //自定义的接口里面的方法
    public interface IService {
    public int callHeimaPay(String name,String password,int money);
    }
    
  5. 把这个自定义的接口的后缀名修改为aidl,然后会报错,我们把接口中的 public去掉即可

    interface IService {
    int callHeimaPay(String name,String password,int money);
    }
    
  6. aidl文件生成好了,现在需要修改内部类了,让这个内部类去继承IService.Stub,这个类你在资源文件中能够找到,Stub这个类是随着aidl文件自动生成的

    class MyBind extends IService.Stub{
        public int callHeimaPay(String name,String password,int money){
        //调用外部来的方法
        return heiMaPay(name, password, money);
        }
    }
    

    到这里服务端就已经完成了,接下来就是调用端了

我们要调用上面的这个服务的操作步骤

  1. 在我们的项目中新建一个和把上面那个服务端的aidl文件所在的包一样的包名,再把这个aidl文件拷贝到这个包里
  2. 在我们的想要调用服务的地方绑定那个远程服务即可

    bindService(service, conn, flags)
    

    但这个绑定服务有三个参数,这三个参数的写法如下

    1.第一个参数
    // 绑定远程支付服务
    Intent service = new Intent();
    service.setAction("com.liuwen.remote.action.HEIMAPAY");
    

    第二个参数,这个参数就是这个内部类对象
    // 定义一个内部类实现ServiceConnection
    private class MyConn implements ServiceConnection {

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // 把远程返回的结果对象通过aidl里面的方法转换
        binder = IService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
    }

第三个参数就好写,只是Service类中的一个静态常量,我们一般用这个
Service.BIND_AUTO_CREATE

3. 我们通过上面,内部类中返回的 binder对象,他是一个IService对象
通过它就可以调用我们刚才自定义接口IService的方法了,实际上也就是调用远程服务中的方法

到这里为止,一个简单的远程服务调用就完成了,一个简单的aidl调用流程就是这样的,注意点就是,由于我们是跨进程调用,所以我们设置意图对象的时候要用隐式调用,也就是要设置action

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值