Android 绑定 Service

上一章节我们介绍了 startService() 方式启动一个非绑定的 Service,我们发现 onBind() 方法并没有被调用

本章节我们来学习下 bindService() 方式启动一个 Service

bindService() 启动 Service

bindService(Intent Service,ServiceConnection conn,int flags)
参数 说明
service 通过该 Intent 指定要启动的 Service
conn ServiceConnection 对象,用户监听访问者与 Service 间的连接情况,连接成功回调该对象中的 onServiceConnected(ComponentName,IBinder) 方法;

如果 Service 所在的宿主由于异常终止或者其它原因终止,导致 Service 与访问者间断开连接时调用 onServiceDisconnected(CompanentName ) 方法,主动通过 unBindService() 方法断开并不会调用上述方法
flags 指定绑定时是否自动创建 Service** (如果 Service 还未创建),参数可以是 0(不自动创建),BIND_AUTO_CREATE (自动创建)
  1. 当首次使用 bindService() 绑定一个 Service 时,系统会实例化一个 Service 实例,并调用其 onCreate()onBind() 方法,然后调用者就可以通过 IBinder 和 Service 进行交互了,此后如果再次使用 bindService() 绑定 Service,系统不会创建新的 Sevice 实例,也不会再调用 onBind() 方法,只会直接把 IBinder 对象传递给其他后来增加的客户端

  2. 想要解除与服务的绑定,只需调用 unbindService(),此时 onUnbind()onDestory() 方法将会被调用

    这是一个客户端的情况,假如是多个客户端绑定同一个 Service 的话, 那么当一个客户完成和 service 之间的互动后,它调用 unbindService() 方法来解除绑定

    当所有的客户端都和 service 解除绑定后,系统会销毁 Service (除非 Service 也被 startService() 方法开启)

  3. startService() 不同的是,bindService() 模式下的 Service 是与调用者相互关联的,可以理解为 "一条绳子上的蚂蚱", 要死一起死, 在 bindService()后,一旦调用者销毁,那么 Service 也立即终止

  4. onServiceConnected() 方法中有一个 IBinder 对象,该对象即可实现与被绑定 Service 之间的通信

    我们实现 Service 类时,默认需要实现 IBinder onBind() 方法,该方法返回的 IBinder 对象会传到 ServiceConnection 对象中的 onServiceConnected 的参数

    就可以在这里通过这个IBinder与Service进行通信

也就是说

  1. 在自定义的 Service 中继承 Binder,实现自己的 IBinder 对象
  2. 通过 onBind() 方法返回自己的 IBinder 对象
  3. 在绑定该 Service 的类中定义一个 ServiceConnection 对象,重写两个方法 onServiceConnected()onDisconnected() 然后直接读取 IBinder 传递过来的参数即可

验证 BindService 启动 Service 的顺序

我们写一个 demo 用 bindService() 开发一个用来计时的 Service 用来演示 bindService() 的用法以及方法调用流程

  1. 创建一个 空的 Android 项目 cn.twle.android.BindService

  2. MainActivity.java 目录下新建一个 Service MsTestService.java

    package cn.twle.android.bindservice;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.Binder;
    import android.util.Log;
    
    public class MsTestService extends Service {
    
        private final String TAG = "MsTestService";  
        private int count;  
        private boolean quit;
    
        //定义onBinder方法所返回的对象  
        private MsBinder binder = new MsBinder();  
        public class MsBinder extends Binder  
        {  
            public int getCount()  
            {  
                return count;  
            }  
        }
    
        //必须实现的方法,绑定改Service时回调该方法  
        @Override  
        public IBinder onBind(Intent intent) {  
            Log.i(TAG, "onBind方法被调用!");  
            return binder;  
        }
    
        //Service被创建时回调  
        @Override  
        public void onCreate() {  
            super.onCreate();  
            Log.i(TAG, "onCreate方法被调用!");  
            //创建一个线程动态地修改count的值  
            new Thread()  
            {  
                public void run()   
                {  
                    while(!quit)  
                    {  
                        try  
                        {  
                            Thread.sleep(1000);  
                        }catch(InterruptedException e){e.printStackTrace();}  
                        count++;  
                    }  
                };  
            }.start();
    
        }
    
        //Service断开连接时回调  
        @Override  
        public boolean onUnbind(Intent intent) {  
            Log.i(TAG, "onUnbind方法被调用!");  
            return true;  
        }
    
        //Service被关闭前回调  
        @Override  
        public void onDestroy() {  
            super.onDestroy();  
            this.quit = true;  
            Log.i(TAG, "onDestroyed方法被调用!");  
        }
    
        @Override  
        public void onRebind(Intent intent) {  
            Log.i(TAG, "onRebind方法被调用!");  
            super.onRebind(intent);  
        }  
    }
    
  3. 修改 AndroidManifest.xml 完成 Service 注册,在 </activity> 后添加

    <!-- 配置 Service 组件,同时配置一个 action -->
    <service android:name=".MsTestService">
        <intent-filter>
            <action android:name="cn.twle.android.bindservice.MS_TEST_SERVICE"/>
        </intent-filter>
    </service>
    
  4. 修改 activity_main.xml 添加两个按钮

    <?xml version="1.0" encoding="utf-8" ?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal" 
        android:orientation="horizontal" >
    
        <Button 
            android:text="锁定 Service"
            android:id="@+id/service_lock"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" />
    
        <Button 
            android:text="解除锁定"
            android:id="@+id/service_unlock"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" />
    
        <Button 
            android:text="获取状态"
            android:id="@+id/service_status"
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" />
    
    </LinearLayout>
    
  5. 修改 MainActivity.java

    package cn.twle.android.bindservice;
    
    import android.app.Service;
    import android.support.v7.app.AppCompatActivity;
    import android.content.Intent;
    import android.content.ComponentName;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.View;
    import android.widget.Button;
    import android.widget.Toast;
    import android.util.Log;
    
    public class MainActivity extends AppCompatActivity {
    
        //保持所启动的Service的IBinder对象,同时定义一个ServiceConnection对象  
        MsTestService.MsBinder binder;  
        private ServiceConnection conn = new ServiceConnection() {
    
            // Activity  Service 断开连接时回调该方法
    
            @Override  
            public void onServiceDisconnected(ComponentName name) {  
                Log.i("MsTestService","------Service DisConnected-------");  
            }
    
            // Activity  Service 连接成功时回调该方法  
            @Override  
            public void onServiceConnected(ComponentName name, IBinder service) {  
                Log.i("MsTestService","------Service Connected-------");  
                binder = (MsTestService.MsBinder) service;  
            }  
        };
    
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);
    
            Button service_lock = (Button) findViewById(R.id.service_lock);  
            Button service_unlock = (Button) findViewById(R.id.service_unlock);  
            Button service_status = (Button) findViewById(R.id.service_status);
    
            final Intent it = new Intent(this,MsTestService.class);
    
            service_lock.setOnClickListener(new View.OnClickListener() {            
                @Override  
                public void onClick(View v) {  
                    //绑定service  
                    bindService(it, conn, Service.BIND_AUTO_CREATE);                  
                }  
            });
    
            service_unlock.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    //解除service绑定  
                    unbindService(conn);                  
                }  
            });
    
            service_status.setOnClickListener(new View.OnClickListener() {  
                @Override  
                public void onClick(View v) {  
                    Toast.makeText(getApplicationContext(), "Service的count的值为:"  
                            + binder.getCount(), Toast.LENGTH_SHORT).show();  
                }  
            });  
        }  
    }
    

运行效果如下

点击锁定 Service

继续点击锁定:没任何变化

获取当前 Service 的状态

解除绑定

如果我们再绑定后直接关掉 Activity ,会自动调用 onUnbindonDestory() 方法

从运行结果可以看出

使用 bindService 绑定 Service,依次调用 onCreate(),onBind() 方法

我们可以在 onBind() 方法中返回自定义的 IBinder 对象;

再接着调用的是 ServiceConnection 的 onServiceConnected() 方法该方法中可以获得 IBinder 对象,从而进行相关操作;

当 Service 解除绑定后会自动调用 onUnbind()onDestroyed() 方法

如果绑定多客户端情况需要解除所有的绑定才会调用 onDestoryed() 方法进行销毁

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.