Service

2017-05-07  本文已影响0人  我爱吃青苹果

1.基本概念

Service 是应用组件之一,用来执行需要长时间运行的操作,Service 运行在后台并且跟用户没有交互界面。

其他应用的组件可以启动一个Service,一旦启动起来,该Service就一直在后台运行,就算用户已经将该应用置为后台进程。

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

2.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

/**
 * 后台的服务 ,用来窃听电话
 */
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;
    }
}
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);
    }
}
//保存录音文件到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的生命周期

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

6.AIDL实现进程间通信

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

猜你喜欢

热点阅读