Android - 绑定服务调用服务里面的方法,start/bind开启服务的比较,混合方式开启服务,本地服务,远程服务,系统服务,录音API

转载请注明出处:https://blog.csdn.net/mythmayor/article/details/72876756

1.服务

  • startService()

    缺陷: 我们不可以调用服务的方法, 不可以与服务进行通信.

  • bindService() 绑定服务

    可以间接的调用到服务里面的方法, 可以与服务进行通信.

2.为什么不能通过new Service()来调用服务里面的方法

服务是系统new出来的,系统new出来之后会把上下文为什么准备好,我们自己去new的Service和系统new的Service不是同一个对象,拿不到上下文

3.通过什么方式来调用服务里的方法

Android中提供了调用服务里的方法的解决方案,就是要获取到服务的代理

4.服务返回其代理

  1. 服务通过onBind()方法返回代理,其返回值是一个IBinder的实现类

    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("服务被绑定了, 返回IBinder的中间人");
        return new MyBinder();
    }
    
  2. 创建一个IBinder的实现类,IBinder是一个接口,实现该接口我们需要实现里面所有的方法,非常不方便,系统为我们提供了一个方便的实现类Binder,让该类继承Binder,我们就可以提供代理方法了

    public class MyBinder extends Binder{
    
        public void callMethodInService(String name){
            methodInService(name);
        }
    
    }
    

5.绑定服务获得其代理,调用服务里的方法

public class MainActivity extends Activity {

    //代理人
    private MyBinder myBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //绑定服务获取中间人
    public void bind(View view){
        //2. 要绑定哪个Service
        Intent intent = new Intent(this,TestService.class);

        //1. 绑定Service
        //intent 要绑定哪个Service
        //conn 通讯频道,通过该conn来获取服务的代理
        //BIND_AUTO_CREATE如果服务不存在,会把服务创建出来.
        bindService(intent, new MyConn(), BIND_AUTO_CREATE);
    }

    //3. 创建通讯频道
    private class MyConn implements ServiceConnection{

        //当服务被成功连接的时候调用的方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //4. 成功连接后,得到了服务的代理对象
            myBinder = (MyBinder) service;
        }

        //当服务失去连接的时候调用的方法.
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    //通过中间人调用服务里面的方法
    public void call(View view){
        //5. 通过得到的代理对象,调用服务里的方法
        myBinder.callMethodInService("小华华", 250);
    }
}

6.绑定服务调用服务方法的步骤

  1. 编写服务代码

    public IBinder onBind(Intent intent) {}
    
  2. 在服务内部定义一个代理人对象 MyBinder

    代理人对象有一个方法可以间接的调用服务内部的方法
    
  3. 在onbind方法里面返回代理人对象

  4. 在Activity代码采用绑定的方式连接到服务

    bindService(intent, new MyConn(),  BIND_AUTO_CREATE);
    
  5. 在serviceConnection的实现类里面有一个方法,获取到服务返回的代理人对象

    public void onServiceConnected(ComponentName name, IBinder service)
    
  6. 强制类型转换IBinder转化成 MyBinder类型

    myBinder = (MyBinder) service;
    
  7. 调用代理人对象的方法–间接调用了服务里面的方法.

7.绑定方式开启服务的生命周期

  • 绑定的方式开启服务,如果服务不存在, oncreate—>onbind
  • 服务的onstart和onstartcommand方法不会被执行.
  • 解除绑定服务 onunbind()—>ondetroy()
  • 多次绑定服务,服务只会被创建一次,oncreate方法只会被执行一次
  • 多次绑定服务,onbind方法不会被重复调用.
  • 在实际开发的时候,如果需要调用服务的方法,就绑定服务,只能绑定一次
  • 服务只可以被解绑一次,如果用同一个conn对象多次解绑,服务会抛出一次.

8.通过接口隐藏代码内部实现的细节

  • 学习一种代码的设计方式,如果一个内部类有多个方法,我只想暴露出其中的一部分方法时,可以通过接口将想要暴露的方法暴露出去。
  • 如果将内部类设置为public,则所有方法都暴露出去了,如果将内部类设置为private,则所有方法其他人都不能调用了
  • 具体实现方式:设置内部类为private的,将想要暴露出去的方法抽取到一个public的接口中

9.两种开启服务方式的比较

  • start的方式开启服务

    服务一旦开启,长期后台运行,服务和开启者(Activity)没有任何的关系,开启者退出了,服务还是继续在后台长期运行, 开启者(Activity)不可以调用服务里面的方法. 在系统设置界面里面可以观察到

  • bind的方式开启服务

    不求同时生,但求同时死. 如果开启者(Activity)退出了, 服务也会跟着挂掉.
    开启者(Activity)可以间接的利用中间人调用服务里面的方法.在系统设置界面看不到的.

服务如果被开启同时被绑定,服务就停不掉了.必须解除绑定服务才可以停止服务.

10.混合的方式开启服务.

  • 为了保证服务又能长期后台运行,又能调用到服务里面的方法.
  • 采用混合的方式开启服务.

请严格按照步骤编写代码:

  1. start的方式开启服务 (保证服务长期后台运行)
  2. bind的方式绑定服务 (调用服务的方法)
  3. unbind的方式解除绑定服务
  4. stop的方式停止服务

11.本地服务和远程服务

  • 本地服务 local service

    服务的代码在当前应用程序的内部

  • 远程服务 remote service

    服务的代码在另外一个应用程序里面

12.重要概念

  • 进程

    操作系统分配的独立的内存空间.

  • IPC

    inter process communication 进程间通讯

  • aidl

    android interface definition language 安卓接口定义语言

13.绑定远程服务调用服务方法的流程

  • 服务提供者

    1. 跟本地服务的代码编写是一样
    2. 远程服务的接口定义文件,将.java的后缀名修改为 —> .aidl
    3. 把接口定义文件的访问修饰符全部删除,如public、private。系统会在gen文件夹下自动为我们生成.java文件
    4. 原来代理人MyBinder,由extend Binder implemet IService修改为 –> extends IService.Stub
  • 使用服务者

    1. 先把远程服务的.aidl文件拷贝到本地应用程序的工程目录里面,包名必须一致,系统会在gen文件夹下自动为我们生成.java文件
    2. 获取到代理的iBinder对象后,通过iService = IService.Stub.asInterface(service)得到远程服务的代理对象
    3. 通过代理对象调用远程服务的方法

14.系统服务了解

  1. 系统开启后,就会开启大量的常用服务,以后其他应用想使用系统服务的时候,可以通过context.getSystemService(String 服务名)方法获取到对应的系统服务

15.监听通话状态

  1. 获取系统服务,设置通话状态监听器

    tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    listener = new MyPhoneListener();
    tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
    
  2. 创建通话状态监听器

    private class MyPhoneListener extends PhoneStateListener {
    
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
            case TelephonyManager.CALL_STATE_IDLE: // 空闲状态,代表当前没有电话
                System.out.println("停止录音");
                break;
            case TelephonyManager.CALL_STATE_RINGING:// 响铃状态
    
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:// 通话状态
                System.out.println("通话状态,开启录音机,录音.");
                break;
            }
        }
    
    }
    
  3. 不使用的时候注销掉监听器,释放资源

    tm.listen(listener, PhoneStateListener.LISTEN_NONE);
    

16.录音API

  1. 开始录音

    mRecorder = new MediaRecorder();
    
    //从麦克风录音,VOICE_CALL可录双向的,但是法律不允许
    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    //输出格式
    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    //文件存放位置
    mRecorder.setOutputFile("/mnt/sdcard/"+SystemClock.uptimeMillis()+".3gp");
    //音频编码方式
    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
    
    try {
        mRecorder.prepare();
    } catch (Exception e) {
       System.out.println("prepare() failed");
    }
    
    mRecorder.start();
    
  2. 停止录音

    mRecorder.stop();
    mRecorder.release();
    mRecorder = null;
    

17.serviceMethod

搜狗截图20160527172805.jpg

18.总结

  1. 服务(Service)
    1. 通过什么方式调用服务中的方法
    2. 创建服务的代理,将服务中的方法暴露出去
    3. 绑定服务,调用服务中的方法
    4. 通过接口隐藏代码内部实现细节
    5. 绑定服务的生命周期
    6. startService和bindService两种开启服务方式的区别
    7. 如何保证服务又能长期后台运行,又能调用到服务里面的方法
    8. 本地服务和远程服务的区别
    9. 进程、IPC、AIDL
    10. 绑定远程服务,调用服务中的方法
    11. 系统服务了解,如何使用系统提供的服务
    12. 使用系统服务的案例——监听通话状态,进行录音
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值