4.创建一个被绑定的服务
被绑定的服务是允许应用程序组件通过调用bindService()绑定的服务,目的在于创建一个长期的连接。
当我们想要这个服务与其他应用程序中的Activity交互时,创建一个被绑定的服务将是一个不错的选择。
想要创建一个被绑定的服务,则必须实现onBind()方法去返回与服务通信的接口对象(IBinder)。其他应用程序组件可以调用bindService()去检索服务提供的接口并且开始在服务中调用这些方法。服务只为绑定它的应用程序组件服务而活,因此,当没有组件绑定到这个服务的时候,系统会销毁它(在系统通过onStartCommand()来启动服务时,我们不需要停止一个绑定服务)
为创建一个被绑定的服务,必须要做的第一件事情是定义接口,该接口指定客户如何与该服务通信。服务和客户端之间的接口必须是一个IBinder的实现,它是服务从onBind()回调方法中返回的。一旦这个客户端收到IBinder,它能通过该接口与服务交互。
多个客户端能立刻绑定这个服务。当客户端完成与服务交互的时候,它调用unBindService()去解绑。一旦没有客户绑定到这个服务上,系统就会销毁该服务。
实现一个被绑定的服务有很多方法,它比实现被启动的服务更为复杂。
①基本介绍
被绑定的服务是Service类的一个实现,该类允许其他应用程序绑定到服务上并与之交互,为给服务提供绑定,我们必须实现onBind()回调方法。该方法返回一个IBinder对象,该对象定义了客户端可以用来与服务交互的编程接口。
客户端可以通过调用bindService()方法绑定到这个服务。当这样做的时候它必须提供ServiceConnection实现,该实现将监视与服务的连接。没有值的bindService()方法会立即返回,但当Android系统创建客户端与服务之间的连接时,我们会调用ServiceConnection中的onServiceConnected()方法来传递IBinder,而客户端可用IBinder来与服务通信。
多个客户端可立即连接到服务上,但是只有首个客户端被绑定的时候,系统才会调用服务的onBind()方法去检索IBinder。之后,系统交付相同的IBinder到绑定的任何额外客户端上,不用再次调用onBind()方法。
当最后的客户端从这个服务中解除绑定的时候,系统会销毁服务(除非该服务也是通过startService()方法启动的)。
当我们实现被绑定服务的时候,最重要的部分是定义onBind()回调方法返回的接口。定义服务的IBinder接口有几种方法,接下来将会介绍这些方法。
②LYJBoundService实例
前面我们讲述了被绑定服务的特性以及生命周期,现在来看一个完整的实例,通过这个实例,我们将深入理解如何定义AIDL并使用它来实现服务,具体步骤如下所示。
Ⅰ使用上面的LYJService项目,在”liyuanjing.example.com.lyjService“下添加IRemoteService.aidl文件以定义远程接口,相关代码如下所示:
package liyuanjing.example.com.lyjservice; interface IRemoteService { int getPid(); }
当完成这个步骤时,我们的项目工程将会发生变化,Android工具将为我们编译出iRemoteService.java库。
Ⅱ创建一个名叫“LYJBoundService”的服务类,它继承自Service类。
这里我们需要完成以下两件事。
㈠实现Ⅰ中定义的接口。
㈡实现必要的服务生命周期回调函数,最重要的是需要实现onBind()接口
修改后的服务代码如下所示:
public class LYJBoundService extends Service { public LYJBoundService() { } //实现IRmeoteService中的getPid()接口 IRemoteService.Stub mRemoteBinder=new IRemoteService.Stub(){ @Override public int getPid() throws RemoteException { return android.os.Process.myPid(); } }; @Override public IBinder onBind(Intent intent) { //将mRemoteBinder通过此接口返回 return mRemoteBinder; } }
Ⅲ将LYJBoundService配置到AndroidManifest.xml文件中,并增加一个<service>节点,代码如下:
<service android:name=".LYJBoundService" android:enabled="true" android:exported="true" > <intent-filter> <action android:name="liyuanjing.example.com.boundservice.remote"/> </intent-filter> </service>
Ⅳ修改默认的Activity使存在3个按钮,它们分别是“Bind Service”,"UnBind Service"和“Kill Service”,其中,只有当成功绑定到服务的时候,“UnBindService”按钮才变为用。修改后的代码如下所示:
布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/bind" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bind Service" /> <Button android:id="@+id/unBind" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="UnBind Service" /> <Button android:id="@+id/kill" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Kill Service" /> </LinearLayout>
MainActivity:
public class MainActivity extends Activity implements View.OnClickListener{ private final static String SERVICE_ACTION="liyuanjing.example.com.boundservice.remote"; private static final String TAG="MainActivity"; private Button bind; private Button unBind; private Button kill; private IRemoteService mIRemoteService; private ServiceConnection mServiceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIRemoteService=IRemoteService.Stub.asInterface(service); unBind.setEnabled(true); kill.setEnabled(true); } @Override public void onServiceDisconnected(ComponentName name) { mIRemoteService=null; unBind.setEnabled(false); kill.setEnabled(false); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final Intent intent=new Intent(SERVICE_ACTION); this.bind=(Button)findViewById(R.id.bind); this.unBind=(Button)findViewById(R.id.unBind); this.kill=(Button)findViewById(R.id.kill); this.bind.setOnClickListener(this); this.unBind.setOnClickListener(this); this.kill.setOnClickListener(this); } @Override public void onClick(View v) { int id=v.getId(); switch (id){ case R.id.bind: Intent intent=new Intent(SERVICE_ACTION); bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE); break; case R.id.unBind: if(mIRemoteService!=null){ try{ int pid=mIRemoteService.getPid(); Log.e(TAG,"Service_Pid = "+pid); unbindService(mServiceConnection); }catch(RemoteException e){ e.printStackTrace(); } } break; case R.id.kill: if(mIRemoteService!=null){ try{ int pid=mIRemoteService.getPid(); Log.e(TAG,"Service_Pid = "+pid); }catch(RemoteException e){ e.printStackTrace(); } } break; } } }
Ⅴ运行应用程序,先点击Bind Service,在点击unBind Service,最后点击Kill Service得到如下日志:
项目目录结构如下图: