安卓中的四大组件_Service

来源:互联网 发布:淘宝新开的店铺发货慢 编辑:程序博客网 时间:2024/05/17 16:56
  • 服务是一个没有界面的Activity.
  • 特点:长期在后台运行, 不关乎界面的一些操作.比如: 网易新闻服务, 每隔1分钟服务会去请求网络,是否有最新新闻.

  • 进程中运行着线程, Android应用程序刚启动都会开启一个进程给这个程序来使用.

  • 和Thread有点相似. 但是不适用线程的原因是,使用Thread不安全, 不严谨 在Android中,一个应用程序把所有的界面关闭时, 进程这时还没有被销毁, 现在处于的是空进程状态. 而安卓中空进程是很容易被结束掉的(详细见进程的回收机制)。

  • 进程的回收进制.

    • 五种进程, 从低到高

      1. Foreground process 前台进程

      2. Visible process 可视进程, 可以看见, 但不可以交互.

      3. Service process 服务进程

      4. Background process 后台进程

      5. Empty process 空进程 当程序退出时, 进程没有被销毁, 而是变成了空进程.

    • 回收的顺序: 从低到高

      • 当系统内存不够用时, 就会把空进程回收了( 一个一个回收掉空进程,直到系统内存够用).
      • 当系统回收完所有的空进程还是不够用时, 则会继续向上回收后台进程, 依次类推.
    • 当回收: 服务, 可视, 前台这三种进程时, 系统非必要情况下不会轻易回收, 如果需要回收掉这三种进程, 在系统内存够用时, 会重新启动进程.

    • 对于服务进程:如果用户手动的关闭服务, 这时服务不会再重启了.

  • 为什么用服务, 而不用Thread? Thread运行在空进程中, 很容易的被销毁了. 服务不容易被销毁, 如果非法状态下非销毁了, 系统会在内存够用时, 重新启动.

  • 电话窃听器(当接通电话时开始录音, 挂断电话时停止录音).

    @Overridepublic void onCreate() {    super.onCreate();    System.out.println("电话窃听服务开启了。。。");    // 监听手机的通话状态    TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);    tm.listen(new PhoneStateListener() {        @Override        public void onCallStateChanged(int state, String incomingNumber) {            super.onCallStateChanged(state, incomingNumber);            if (state == TelephonyManager.CALL_STATE_IDLE && isRecording) {                // 如果电话处于空闲状态,并且正在录音中,说明是刚刚挂断电话                // 8.停止录音                mr.stop();                // 9.释放资源                mr.release();                isRecording = false;            } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {                // 如果电话接通了,开始录音                // 1. 创建一个录音器                mr = new MediaRecorder();                // 2. 设置音频源来自麦克风                mr.setAudioSource(MediaRecorder.AudioSource.MIC);                // 3. 设置输出文件的格式                mr.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);                // 4. 设置输出文件的名字                mr.setOutputFile(PATH);                // 5. 设置音频编码                mr.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);                // 6. 准备, 马上要录音了                try {                    mr.prepare();                } catch (Exception e) {                    e.printStackTrace();                }                // 7. 开始录音                mr.start();                isRecording = true;            }        }    }, PhoneStateListener.LISTEN_CALL_STATE);}
  • 服务生命周期

    • 开启方式, 特点: 把服务启动起来后, 就不关服务的事了.. activity和服务没有关系.

      • startService方法执行的时候, 服务的生命周期执行的过程: onCreate -> onStart/onStartCommand 服务正在运行中
      • stopService方法执行的时候, 服务的生命周期执行的过程: onDestory 服务销毁了
      • 使用startService方式开启的服务, 只能用stopService关闭服务.
    • 绑定方式, 特点: 不求同年同日生, 但求同年同日死.

      • bindService方法执行的时候, 服务的生命周期执行的过程: onCreate(如果服务创建了,就不再重新创建了) -> onBind
      • unbindService, 生命周期执行的过程: onUnbind -> onDestory
    • onRebind 方法, 只有在onUnbind方法返回true的情况下, 才会被调用.

  • Activity调用Android中的服务中的方法.

    • 使用绑定服务方式, 调用服务中的方法. (因为上下文是由系统底层提供的,因此不能直接new服务对象,如果要调用服务内部的方法,只能通过在服务中 自定义一个内部类,然后在这个内部类中提供调用服务内的方法,并将这个内部类对象通过onBind方法返回给调用者activity)

      • 本地服务调用

        1. 调用bindService绑定服务, 并且传递过去一个连接桥对象

        2. 在服务的类中定义一个内部类MyBinder继承Binder, 并且声明一个forwardBuyTicket方法, 在此方法中转调服务中的buyTicket方法.

        3. 在服务中的onBind方法中, 返回第二步定义的内部类MyBinder对象.

        4. 在Activity中的连接桥中实现onServiceConnected方法, 把IBinder service对象强转成服务中内部类对象MyBinder.

        5. 得到服务中内部类实例, 调用这个实例中的方法forwardBuyTicket. 此方法会转调服务中买票的方法buyTicket.

      • 远程服务调用(一个程序调用另一个程序的服务中的方法)

      • IPC(intel-process communication)机制, 通信
      • 原理基于: aidl(application interface define language) 应用接口声明语言, 不支持修饰词

      • 过程

        • 写服务类

          1. 定义一个接口文件, 声明一个forwardPayMoney方法, 把文件的后缀名修改为.aidl, 并且把修饰词(public等)去掉.

          2. 在服务中定义一个内部类MyBinder, 继承Stub类, 并且把抽象方法forwardPayMoney实现了.

          3. 在onBind方法中把第二步定义的内部类对象MyBinder返回.

        • 另一个程序的Activity

          1. 使用隐式的方式绑定服务, 传递过去一个连接桥对象.

          2. 把服务程序中的aidl文件拷贝当前工程中, 包名要保留一致.

          3. 在连接桥对象中的onServiceConnected方法中, 把IBinder对象转换成aidl接口对象

            mAlipayRemoteService = Stub.asInterface(service);
          4. 使用aidl接口对象, 调用接口中的抽象方法, 实际上会调用到远程服务中内部类中的forwardPayMoney方法.


原创粉丝点击