Service

作者: 我爱吃青苹果 | 来源:发表于2017-05-07 22:25 被阅读0次

    1.基本概念

    Service 是应用组件之一,用来执行需要长时间运行的操作,Service 运行在后台并且跟用户没有交互界面。
    
    其他应用的组件可以启动一个Service,一旦启动起来,该Service就一直在后台运行,就算用户已经将该应用置为后台进程。
    
    其他应用的组件也可以通过绑定的形式跟一个Service进行交互,甚至完成进程间通信
    
    • Service的特点
    1.Service 在Android中是一种长生命周期的组件,它不实现任何用户界面,是一个没有界面的Activity
    2.Service 长期在后台运行,执行不关乎界面的一些操作比如:网易新闻服务,每隔1分钟去服务查看是否有最新新闻
    3.Service 和Thread 有点相似,但是使用Thread 不安全,不严谨
    4.Service 和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的操作
    

    2.Android中的进程

    • 在Android 中进程优先级由高到低,依次分为:
    1.Foreground process(前台进程)
    2.Visible process(可见进程)
    3.Service process(服务进程)
    4.Background process(后台进程)
    5.Empty process(空进程)
    
    • 进程的回收机制
    进程的回收顺序是:从低到高
    1.当系统内存不够用时, 会把空进程一个一个回收掉
    2.当系统回收所有的完空进程不够用时, 继续向上回收后台进程, 依次类推
    3.面对服务进程、可视进程、前台进程时, 系统非必要情况下不会轻易回收
    4.如果需要回收以上三种进程,在系统内存够用时,会再重新启动进程;但是服务进程如果用户手动的关闭服务, 这时服务不会再重启了
    

    3. 使用service

    1.服务是运行在后台的进程,跟我们熟悉的Thread很像
    2.在使用Service 时一定要注意,Service默认运行在应用的主线程中,因此如果你需要在Service 中执行大量的或者阻塞(比如网络访问、IO等)的任务,那么依然需要在Service 中开启一个Thread 来完成这些工作
    3.使用Service并不影响使用Thread,而且很多情形下,我们都是在Service中开启子Thread的混合使用方式
    

    4.Code

    • 自定义Service
    /**
     * 后台的服务 ,用来窃听电话
     */
    public class PhoneService extends Service {
        
        private TelephonyManager tm;//电话管理器
        private MyPhoneListener listener;//监听器
        private MediaRecorder mRecorder;//录音器
        
        public IBinder onBind(Intent intent) {
            return null;
        }
        
        //创建服务时
        public void onCreate() {
            //获取电话管理器
            tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
            listener = new MyPhoneListener();
            //注册电话状态的监听器
            tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
        }
        
        //自定义电话监听器
        private class MyPhoneListener extends PhoneStateListener {
        
            public void onCallStateChanged(int state, String incomingNumber) {
                super.onCallStateChanged(state, incomingNumber);
                switch (state) {
                    // 空闲状态,代表当前没有电话
                    case TelephonyManager.CALL_STATE_IDLE: 
                        if(mRecorder!=null){
                            System.out.println("停止录音");
                            stopRecording();//停止录音方法
                        }
                        break;
                    // 响铃状态
                    case TelephonyManager.CALL_STATE_RINGING:
                    break;
                    // 通话状态
                    case TelephonyManager.CALL_STATE_OFFHOOK:
                        System.out.println("通话状态,开启录音机,录音.");
                        startRecording();//开始录音方法
                    break;
                }
            }
        }
        
        //销毁服务时
        public void onDestroy() {
            //注销电话状态的监听
            tm.listen(listener, PhoneStateListener.LISTEN_NONE);
            super.onDestroy();
        }
        
        //开始录音的方法
        private void startRecording() {
            mRecorder = new MediaRecorder();
            //设置声音来源,从麦克风录音
            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            //设置输出格式为3gp 
            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();//开启
        }
        
        //停止录音的方法
        private void stopRecording() {
            mRecorder.stop();
            //释放录音器资源
            mRecorder.release();
            mRecorder = null;
        }
    }
    
    • 启动Service
    startService 或 bindService两种启动方式
    
    public class MainActivity extends Activity {
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
        public void start(View view){
            //创建一个Intent 对象
            Intent intent = new Intent(this,PhoneService.class);
            //启动服务
            startService(intent);
        }
    }
    
    • AndroidManifest.xml中注册
    //保存录音文件到sdcard、监听电话状态、录音都需要添加权限
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    
    //注册Service:
    <service android:name="com.demo.phonelistener.PhoneService" >
    </service>
    

    5.Service的生命周期

    • Service有生命周期,Service的生命周期,从它被创建开始,到它被销毁为止,可以有两条不同的路径:标准开启模式和绑定模式

    • started service(标准开启模式)

    1.被开启的service 通过其他组件调用startService()被创建
    2.这种service 可以无限地运行下去,必须调用stopSelf()方法或者其他组件调用stopService()方法来停止它
    3.当service 被停止时,系统会销毁它
    
    • bound service(绑定模式)
    1.被绑定的service是当其他组件(一个客户)调用bindService()来创建的
    2.客户可以通过一个IBinder接口和service 进行通信
    3.客户可以通过unbindService()方法来关闭这种连接
    4.一个service 可以同时和多个客户绑定,当多个客户都解除绑定之后,系统会销毁service
    
    • 任何Service 都潜在地允许被绑定
    • 一个被开启的Service仍然可能被绑定

    6.AIDL实现进程间通信

    1.Android 采用了一种轻量级的实现方式RPC(Remote Procedure Call 远程进程调用)来完成进程之间的通信
    2.Android 通过接口定义语言(Android Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码
    3.AIDL 是Android 的一种接口描述语言,编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的
    
    • aidl的使用步骤

    • service端

    //1.远程服务定义的接口文件不能是.java文件,需要改成.aidl文件,里面的修饰符都不需要
    
    package com.demo.remote;
    
    interface IService {
        void callMethodInService();
    }
    
    //2.程序会自动在gen目录下生成Iservice.java文件,会有一个抽象的静态类Stub继承了Binder对象并实现了IService接口
    
    //3.创建服务,在服务中创建中间代理人对象,在onBind()方法中返回出去给绑定该服务的对象使用。
    
    public class RemoteService extends Service {
        /**中间代理人*/
        private class MyBinder extends IService.Stub{
            public void callMethodInService() {
                //调用服务里面的方法
                methodInService();
            }
        }
    
        public IBinder onBind(Intent intent) {
            //返回中间代理人
            return new MyBinder();
        }
        
        public void onCreate() {
            System.out.println("远程服务被创建了...");
            super.onCreate();
        }
        
        public void onDestroy() {
            System.out.println("远程服务被销毁了...");
            super.onDestroy();
        }
        
        //服务里面的方法
        public void methodInService(){
            System.out.println("我是远程服务的方法,我被调用了....");
        }
    }
    
    • 调用者端
    public class MainActivity extends Activity {
        private MyConn conn;
        private IService iService;
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public void bind(View view){
            Intent intent = new Intent();
            //调用远程服务 :隐式意图
            intent.setAction("com.demo.remote");
            conn = new MyConn();
            bindService(intent, conn, BIND_AUTO_CREATE);
        }
        
        private class MyConn implements ServiceConnection{
            public void onServiceConnected(ComponentName name, IBinder service) {
                //得到远程服务的代理对象
                iService = IService.Stub.asInterface(service);
            }
            public void onServiceDisconnected(ComponentName name) {
            }
        }
        
        public void call(View view){
            try {
                //通过代理对象调用远程服务的方法
                iService.callMethodInService();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Service

          本文链接:https://www.haomeiwen.com/subject/hiyptxtx.html