Android开发-Service(服务)

目录

Android四大组件:  

1. 服务的概念   

1.1 概念 

1.2 适用场景

1.3 继承结构图

2. 服务的生命周期

2.1 定义

         Service拥有自己的生命周期,不会被捆绑,即便Activity销毁之后,Service也不会销毁。

2.2 启动类型

2.3 结构图

2.4 方法

3. 服务的创建

3.1 创建类并继承Service      

3.2 注册服务

3.3 服务启动方式

3.3.1 startService方式启动服务

3.3.2 bindService方式启动服务

3.4 bindService案例

3.4.1 bindService使用场景

       绑定服务的最大作用就是用来实现对Service执行的任务进行进度监控。

3.4 服务的关闭与解绑方法

3.5 服务的启动模式

3.6 两种启动方法的区别

4 服务的通信

4.1 通信方式



Android四大组件:  

       ActivityServiceBroadcastReceiverContentProvider。   

--------------------------------------------------------------------------------------------------------------------------------

1. 服务的概念   

1.1 概念 

         Service(服务)是一个长期运行在后台没有用户界面的应用组件,即使切换到另一个应用程序或者后台,服务也可以正常运行。因此,服务适合执行一段时间不需要显示界面的后台耗时操作(需要另启子线程),比如下载网络数据播放音乐等。

Service可以看做是一个没有界面的Activity,因此启动,销毁服务跟开启,销毁Activity类似

         Service并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程,即Service运行在主线程中。当某个应用程序进行被杀掉时,所有依赖于该进程的服务都会停止运行

         Service并不会自动开启线程,所有的代码都是默认运行在主线程当中的,也就是说,需要在服务的内部手动创建子线程,并在里面执行具体的任务。否则就会出现主线程被阻塞的情况。

        Activity启动服务,主要用于响应和处理Activity的事件。Service拥有自己的生命周期,不会被捆绑,即便Activity销毁之后,Service也不会销毁。 支持显式和隐式启动服务。

1.2 适用场景

       1)下载网络数据(在Android3.0之后,只支持子线程下载,因此此功能应该在子线程中启动服务)

       2)播放音乐。

       3)访问文件、数据库等一些业务逻辑功能,可以让Service来实现。

1.3 继承结构图

       比较Service与Activity的继承关系结构图如下:

Android开发-Service(服务)_第1张图片

 

2. 服务的生命周期

2.1 定义

         Service可以看做是一个没有界面的Activity。Service拥有自己的生命周期,不会被捆绑,即便Activity销毁之后,Service也不会销毁。

2.2 启动类型

        服务的启动方式有两种,分别是startService()(启动服务)bindService()(绑定服务)方法。使用不同的方法启动服务,其生命周期也是不同的。服务的启动都是在Activity中进行的。

1.startService()

其他组件调用startService()启动一个Service,一旦启动,Service将一直运行在后台,即便启动

Service的组件已经被destory。但是,Service会在后台执行单独的操作,也并不会给启动它的

组件返回结果。

比如说:一个以启动服务方式的Service执行在后台下载或者上传一个文件的操作,

完成之后,Service自动停止。

2.bindService()

其他组件调用bindService()绑定一个Service,通过绑定方式启动的Service是一个client-server

结构,该Service可以与绑定它的组件进行交互。一个绑定的Service仅在仅有组件与其绑定时才会运行,

多个组件可与一个Service绑定,Service不在与人和网组件绑定时,将会被destory

2.3 结构图

        如下图所示:

Android开发-Service(服务)_第2张图片

       

Android开发-Service(服务)_第3张图片

2.4 方法

1.onCreate() 服务被创建,单例模式,只会创建一次
2.onStartCommand() 服务启动时调用
3.onBind() 绑定时调用,同时会调用onCreate()方法不会调用onStartCommand()方法
4.onUnBind() 解绑时调用 ,同时会调用onDestory()方法
5.onDestory() 销毁时调用

 

3. 服务的创建

3.1 创建类并继承Service      

        Service(服务)是Android四大组件之一。创建方式与广播接收者类似。【new】->【Service】,创建的Service如下所示:

public class MyService extends Service{
    //客户端通过调用bindService()方法启动服务时执行该方法
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    //客户端通过调用startService()方法启动服务时执行该方法,可以执行多次
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
    //第一次创建服务时执行的方法,且只执行一次
    @Override
    public void onCreate() {
        super.onCreate();
    }
    //客户端调用unBindeService()方法断开服务绑定时执行该方法
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
    //服务被销毁时执行的方法,且只执行一次
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

3.2 注册服务

         Service创建后,会在清单文件AndroidManifest.xml中进行注册,如下所示:


    ......
    ......
    ......
    
    

3.3 服务启动方式

3.3.1 startService方式启动服务

          startService(Intent intent), 传入Intent对象,通过startService方式启动服务,服务会长期在后台运行,并且服务的状态与开启者的状态没有关系,即便启动服务的组件已经被销毁,服务也依旧会运行

3.3.2 bindService方式启动服务

           通过bindService方式启动服务,服务会与组件进行绑定。一个被绑定的服务提供一个客户端与服务器接口,允许组件与服务进行交互发送请求得到结果多个组件可以绑定一个服务,当调用onUnbind()方法时,这个服务就被销毁了,即调用onDestory()方法。

           bindService()方法完整名为bindService(Intent service,ServiceConnection conn,int flags),该方法的三个参数解释如下:

 Intent对象 用于指定要启动的Service。
ServiceConnection对象

用于监听调用者与Service之间的连接状态。当调用者与Service连接成功时,

将回调该对象的onServiceConnected(ComponentName name,IBinder service)方法。

断开连接时,将回调该对象的onServiceDisconnected(ComponentName name)方法。

 flag

绑定时是否自动创建Service(如果Service还未创建)。可指定为0,即不自动创建,

也可指定为“BIND_AUTO_CREATE”,即自动创建。 

       之所以需要ServiceConnection对象,是为了表示绑定与解绑某个具体Service。

3.4 bindService案例

3.4.1 bindService使用场景

       绑定服务的最大作用就是用来实现对Service执行的任务进行进度监控。

          需要使用的两个类如下:

1.ServiceConnection

是一个接口,主要在绑定服务中用于客户端和服务器端链接的,使用ServiceConnection时

通常要重写onServiceConnected()OnServiceDisconnected()方法

2.IBinder  

     案例如下,Service类:

public class MyService extends Service{
    
    //服务创建
    @Override
    public void onCreate() {
        super.onCreate();
    }

    //绑定服务
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
       //返回一个Binder对象,Binder继承与IBinder
        return new MyBinder();
    }

    //创建服务代理,调用服务中的方法
    class MyBinder extends Binder{
        methodInService();
    }

    //自定义方法
    public void methodInService(){
    }

    //解绑
    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }
}

        可以看出,Binder是实现了IBinder接口。从而在Binder类里面可以自定义方法。

     Activity类:

public class MainActivity extends AppCompatActivity{
    private MyServiceConnection connection;  //ServiceConnection对象

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

    //绑定服务
    public void btnBind(View view){
        if(connection == null){
            connection = new MyServiceConnection();
        }
        Intent intent = new Intent(this,MyService.class);
        //绑定服务,BIND_AUTO_CREATE表示绑定时自动创建Service
        bindService(intent,connection,BIND_AUTO_CREATE);
    }

    //解绑服务
    public void btnUnbind(View view){
        if(connection != null){
            //解绑服务,这里需要传入ServiceConnection对象
            unbindService(connection);
            connection = null;
        }
    }

    //调用绑定的服务里面的方法
    public void btnCallServiceInMethod(View view){
    }
    
    /**
     * 创建类继承ServiceConnection,用于解绑服务方法调用
     */
    public class MyServiceConnection implements ServiceConnection{
        //当客户端正常连接这个服务时,成功绑定到服务时调用该方法。注意IBinder参数对象
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //如果成功绑定,iBinder为MyService里面的IBinder对象
            Log.i("MainActivity","服务绑定成功,内存地址为:"+iBinder.toString());
        }
        //当客户端与服务失去连接时调用该方法
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //解绑
            Log.i("MainActivity","服务解绑成功");
        }
    }
}

          可以看出,onServiceConnected()方法里面的IBinder就是Service里面的onBinder()方法的返回IBinder对象。

 

3.4 服务的销毁方法

    1)通过startService方式启动的服务时,销毁服务方法

         通过stopService(Intent inetnt)方式;

    2)通过bindService方式启动的服务时,销毁服务方法

         通过unbindService(ServiceConnection conn)方式。

3.5 服务的启动模式

       1)单例模式:Service在Android中是单例模式,即onCreate()与onDestory()只会被调用一次。

       2)重新创建:如果系统发生异常导致服务终止后,如果内存足够,服务所在的进程会重新创建服务。如果是用户主动销毁的,则不会重新创建。

3.6 两种启动方法的区别

在Android中绑定式服务bindService会随着Activity的结束而结束,但是启动式服务startService不受Activity的影响。

 

4 服务的通信

       通过绑定方式开启服务后,服务与Activity是可以通信的,通过Activity可以控制服务进行一些操作。

4.1 通信方式

        在Android中,服务的通信方式有两种:本地服务通信远程服务通信。使用这两种方式进行通信时,必须保证服务是以绑定的形式开启的,否则无法进行通信和数据交换

       1)本地服务通信

           指的是应用程序内部的通信。首先需要创建一个Service类,该类会提供一个onBind()方法,onBind()方法的返回值是一个IBinder对象,IBinder对象会作为参数传递给ServiceConnection类中的onServiceConnected(ComponentName name,IBinder service)方法,这样访问者就可用通过IBinder对象与Service进行通信。如下图所示:

Android开发-Service(服务)_第4张图片

           从上图可以看出,服务在进行通信时实际使用的是IBinder对象,在ServiceConnection类中得到的IBinder对象,通过这个对象可以获取到服务中自定义的方法,执行具体的操作。

     2)远程服务通信

          在Android系统中,各个应用程序都运行在自己的进程中,如果想要完成不同进程之间的通信,就需要用到远程服务通信。远程服务通信时通过AIDL(Android Interface Definition Language)实现的,接口定义语言,语法格式简单,与Java中定义接口类似,但存在差异如下:

        》AUDL定义接口的源代码必须以.aidl结尾。

        》AIDL接口中用到的数据类型,除了基本数据类型及String、List、Map、CharSequence之外,其他类型全部都需要导入到包,即使它们在同一个包中。

 

     下面一个音乐播放器案例演示本地服务通信:

      布局文件:



    
    
        
        
    

       Service类:

public class MusicPlayerService extends Service {
    private static final String TAG = "MucisPalyerService";
    public MediaPlayer mediaPlayer;
    public MusicPlayerService() {
    }
    class MyBinder extends Binder{
        //播放音乐
        public void play(String path){
            try{
                if(mediaPlayer == null){
                    //创建一个MediaPlayer播放器
                    mediaPlayer = new MediaPlayer();
                    //指定参数为音频文件
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    //指定播放的路径
                    mediaPlayer.setDataSource(path);
                    //准备播放
                    mediaPlayer.prepare();
                    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
                        public void onPrepared(MediaPlayer mp){
                            //开始播放
                            mediaPlayer.start();
                        }
                    });
                }else{
                    //int position = getCurrent
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        //暂停播放
        public void pause(){
            if(mediaPlayer != null && mediaPlayer.isPlaying()){
                mediaPlayer.pause();
            }else if(mediaPlayer != null && (!mediaPlayer.isPlaying())){
                mediaPlayer.start();
            }
        }
    }
    public void onCreate(){
        super.onCreate();
    }
    //获取当前进度
    public int getCurrentProgress(){
        if(mediaPlayer != null && mediaPlayer.isPlaying()){
            return mediaPlayer.getCurrentPosition();
        }else if(mediaPlayer != null && (!mediaPlayer.isPlaying())){
            return mediaPlayer.getCurrentPosition();
        }
        return 0;
    }
    public void onDestory(){
        if(mediaPlayer != null){
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        super.onDestroy();
    }
    @Override
    public IBinder onBind(Intent intent) {
        //第一步执行onBind方法
        return new MyBinder();
    }
}

       上述代码使用了MediaPlayer类来实现音乐播放功能,其常用方法如下:

        》setAudioStreamType():指定音频文件的类型,必须在prepare()方法之前使用。

        》setDataSource():设置要播放的音频文件的位置,即URI路径,

        》prepare():准备播放,调用此方法会使MediaPlayer进入准备状态。

        》start():开始或继续播放音频。

        》pause():暂停播放音频。

        》seekTo():从指定的位置开始播放音频。

        》release():释放掉与MediaPlayer对象相关的资源。

        》isPlaying():判断当前MediaPlayer是否正在播放音频。

        》getCurrentPosition():获取当前播放音频文件的位置。

       Activity类:

public class MusicPlayerActivity extends AppCompatActivity implements View.OnClickListener{
    private EditText path;
    private Intent intent;
    private MyConn conn;
    MusicPlayerService.MyBinder binder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.musicplayer_layout);
        path = (EditText)findViewById(R.id.musicplayer_et_inputpath);
        findViewById(R.id.musicplayer_tv_paly).setOnClickListener(this);
        findViewById(R.id.musicplayer_tv_pause).setOnClickListener(this);
        conn = new MyConn();
        intent = new Intent(this,MusicPlayerService.class);
        bindService(intent,conn,BIND_AUTO_CREATE);
    }
    private class MyConn implements ServiceConnection{
        public void onServiceConnected (ComponentName name, IBinder service){
            binder = (MusicPlayerService.MyBinder)service;
        }
        public void onServiceDisconnected(ComponentName name){
        }
    }
    public void onClick(View v) {
        String pathway = path.getText().toString().trim();
        File SDPath = Environment.getExternalStorageDirectory();
        File file = new File(SDPath, pathway);
        String path = file.getAbsolutePath();
        switch (v.getId()) {
            case R.id.musicplayer_tv_paly:
                if (file.exists() && file.length() > 0) {
                    binder.play(path);
                } else {
                    Toast.makeText(this, "找不到音乐文件", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.musicplayer_tv_pause:
                binder.pause();
                break;
            default:
                break;
        }
    }
    protected void onDestory(){
            unbindService(conn);
            super.onDestroy();
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Android)