Android Service知识

一. 概览

        Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。此外,组件可通过绑定到服务与之进行交互,甚至是执行进程间通信 (IPC)。例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互.

        本篇文章,我们重点讲一讲绑定服务.  为后面写的理解进程间通信机制文章做个铺垫.

二. 服务类型

2.1 前台服务

前台服务执行一些用户能注意到的操作。例如,音频应用会使用前台服务来播放音频曲目。前台服务必须显示通知。即使用户停止与应用的交互,前台服务仍会继续运行。

2.2 后台服务

后台服务执行用户不会直接注意到的操作。例如,如果应用使用某个服务来进行数据搜集上报,则此服务通常是后台服务。

2.3  绑定服务

当应用组件通过调用 bindService() 绑定到服务时,服务即处于绑定状态。绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁

三. 基础知识

        如要创建服务,您必须创建 Service 的子类(或使用它的一个现有子类)。在实现中,您必须重写一些回调方法,从而处理服务生命周期的某些关键方面,并提供一种机制将组件绑定到服务(如适用)。以下是你应该重写的最重要的回调方法:

onStartCommand()
当另一个组件(如 Activity)请求启动服务时,系统会通过调用 startService() 来调用此方法。执行此方法时,服务即会启动并可在后台无限期运行

如果您实现此方法,则在服务工作完成后,需负责通过调用 stopSelf() 或 stopService() 来停止服务。

onBind()

当另一个组件想要与服务绑定(例如执行 RPC)时,系统会通过调用 bindService() 来调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,以供客户端用来与服务进行通信。请务必实现此方法;但是,如果你并不希望允许绑定,则应返回 null。

如果组件通过调用 startService() 启动服务(这会引起对 onStartCommand() 的调用),则服务会一直运行,直到其使用 stopSelf() 自行停止运行,或由其他组件通过调用 stopService() 将其停止为止。

[注意]: 如果通过startService()已经启动了一个服务,再通过startService()方法启动的时候,  只会走onStartCommand()方法,不会重新走onCreate()方法. 

四. 创建绑定服务

绑定服务允许应用组件通过调用 bindService() 与其绑定,从而创建长期连接.

如需与 Activity 和其他应用组件中的Service服务进行交互,或需要通过进程间通信 (IPC) 向其他应用公开某些应用功能,则应创建绑定服务。

[要点]:

如要创建绑定服务,您需通过实现 onBind() 回调方法返回 IBinder,从而定义与服务进行通信的接口;

1. 必须定义指定客户端如何与服务进行通信的接口

2. 服务与客户端之间的这个接口必须是 IBinder 的实现,并且服务端必须从 onBind() 回调方法返回该接口。

3. 收到 IBinder 后,客户端便可开始通过该接口与服务端进行交互。

多个客户端可以同时绑定到服务。完成与服务的交互后,客户端会通过调用 unbindService() 来取消绑定。如果没有绑定到服务的客户端,则系统会销毁该服务。

等同于下面这句话的理解:

多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务(服务不必自行停止运行).


五. 服务生命周期


  

六. 实践出真知

本篇文章重点只讲绑定本地服务, 在同一个进程间通信

如果您的服务仅供本地应用使用,且无需跨进程工作,您可以实现自有 Binder 类,让客户端通过该类直接访问服务中的公共方法。

注意:只有当客户端和服务处于同一应用和进程内(最常见的情况)时,此方式才有效。例如,对于需要将 Activity 绑定到在后台播放音乐的自有服务的音乐应用,此方式非常有效。

实现步骤:

1. 在你的服务中,创建可执行以下某种操作的 Binder 实例:
     包含客户端可调用的公共方法。
     返回当前的 Service 实例,该实例中包含客户端可调用的公共方法。
     返回由服务承载的其他类的实例,其中包含客户端可调用的公共方法。

2. 从 onBind() 回调方法返回此 Binder 实例。

3. 在客户端中,从 onServiceConnected() 回调方法接收 Binder,并使用提供的方法调用绑定服务。

客户端代码

public class LocalClient extends AppCompatActivity {
    private Intent intent;

    //同一进程, 本地服务对象
    LocalService mService;

    //是否绑定成功
    boolean mBound = false;

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

        intent = new Intent(this, LocalService.class);

        Button btn = (Button)findViewById(R.id.start_btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mBound) {
                    int num = mService.getRandomNumber();
                    Toast.makeText(LocalClient.this, "number: " + num, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            Log.e("test", "===客户端===onServiceConnected======");
            mBound = true;
            //已经绑定到LocalService,强制转换IBinder并获取LocalService实例
            LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
            mService = binder.getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e("test", "====onServiceDisconnected=====");
            mBound = false;
        }
    };

    //在onstart方法中 调用 bindservice 绑定服务
    @Override
    protected void onStart() {
        super.onStart();
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    //在onstop方法中, 调用unbindservice 解绑服务
    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
        mBound = false;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

本地服务端的代码:

public class LocalService extends Service {

    // Binder given to clients
    private final IBinder binder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();


    public LocalService() {
    }

    /** method for clients */
    public int getRandomNumber() {
        return mGenerator.nextInt(100);
    }

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     * 用于客户端的Binder类。因为我们知道该服务总是在与其客户端相同的进程中运行,所以我们不需要处理IPC。
     */
    class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }


    @Override
    public IBinder onBind(Intent intent) {
        Log.e("test", "====LocalService  onBind====绑定服务回调===");
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("test", "====LocalService  onUnbind===解绑服务回调==");
        return super.onUnbind(intent);
    }

打开app界面后,打印log:

03-06 15:16:16.612 19858 19858 E test    : ====LocalService  onBind====绑定服务回调=
03-06 15:16:16.623 19858 19858 E test    : ===客户端===onServiceConnected======

客户端通过bindservice 绑定服务, 打印'===LocalService  onBind===='然后服务端通过onBind()回调方法返回此Binder实例

在客户端中从 onServiceConnected() 回调方法接收 Binder对象,打印"客户端===onServiceConnected===="

退出app界面后, 解绑服务,打印log:

03-06 15:22:52.460 19858 19858 E test    : ====LocalService  onUnbind===解绑服务回调==


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值