【远程Service】AIDL进程间通信实例

来源:互联网 发布:网络布线验收标准 编辑:程序博客网 时间:2024/06/06 00:02

对于Service的定义及使用场合等请详见官方定义:http://developer.android.com/guide/components/services.html

Service有两种类型:

1. 本地服务(Local Service):用于应用程序内部

2. 远程服务(Remote Service):用于android系统内部的应用程序之间

本文讲解远程Service服务的使用。

 远程Service通常用于Android内部应用程序之间通信,既然是两个应用程序,所以可以将其理解为一个是服务器提供Service服务,一个是客户端使用Service服务。通常远程Service使用AIDL(Android Interface Define Language)接口定义语言进行进程间通信。

下面编写服务器Service应用的实例代码(三步即可完成):

1)创建一个应用之后,新建一个接口文件,后缀*.adil结尾。如图:

       

文件中的使用Java语言编写一个接口:

package com.example.aidl;interface CountInterface { int getCount(); //可以继续定义更多方法提供给客户端使用}

该文件定义好之后,系统会自动生成其对应的*.java 文件。如图:



2)创建一个服务器端提供的Service服务类,继承Service。实例代码如下:

package com.example.a_bindservice_a;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import com.example.aidl.CountInterface;import com.example.aidl.CountInterface.Stub;public class MyBindService extends Service {Thread t;int i = 0;/** * 创建一个CountInterface.Stub类型的binder,binder将返回给客户端作为客户端的代理,从而可以调用当前服务的方<span style="white-space:pre"></span> *法。 * Stub是CountInterface接口的一个静态内部类 * */CountInterface.Stub binder = new Stub() {@Overridepublic int getCount() throws RemoteException {return i;//在这里实现CountInterface计数的方法}};@Overridepublic IBinder onBind(Intent intent) {// 如果使用远程Service 必须返回一个binder对象。return binder;}@Overridepublic void onCreate() {super.onCreate();System.out.println("bind Oncreate");// 通过启动线程在Service中实现一个计数的功能。t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Thread run");while (true) {i++;try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}});t.start();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {System.out.println("onStartCommand");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {System.out.println("onDestroy");t.interrupt();// 当远程调用unbindService()方法时,当前Service一起被销毁,同时终止子线程。super.onDestroy();}@Overridepublic boolean onUnbind(Intent intent) {System.out.println("onUnbind");return super.onUnbind(intent);}}
需要注意的是:远程Service的onBind()方法中必须返回一个binder对象。binder对象使用CountInterface的内部类Stub 创建。

3)在AndroidManifest.xml文件中注册当前Service并添加Action(不然其他应用找不到这个Service)

注册代码如下:

 <service android:name="MyBindService">            <intent-filter >                <action android:name="com.example.a_bindservice_a.MyBindService"/>            </intent-filter>        </service>




下面创建客户端使用Service服务的实例代码(两步即可完成):
1)首先将服务器Service创建的接口文件连同报名一同拷贝到客户端应用中。如图:

2)编写客户端使用远程Service的实例代码:

package com.example.a_bindservice_b;import com.example.aidl.CountInterface;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;/** * 远程服务在客户端:首先将服务器端的AIDL包及文件拷贝到当前项目中。 * 在客户端创建AIDL接口类型的引用对象cInterface,用来作为服务器再本地的代理。 * 在本地创建ServiceConnection类型的对象sConnection, * 并且重写onServiceConnected和onServiceDisconnected两个方法。 * onServiceConnected方法会在bindService时被回调。 * 在onServiceConnected方法里面对AIDL接口对象赋值,cInterface = * CountInterface.Stub.asInterface(binder);。 在unbindService时清空cInterface对象的引用。 * bindService(intent, sConnection, BIND_AUTO_CREATE); * unbindService(sConnection); Intent对象通过new Intent("Action")方法创建。 * sConnection对象就是ServiceConnection的对象。 *  * */public class MainActivity extends Activity implements OnClickListener {Intent intent; //通过Intent找到服务器端的Service CountInterface cInterface; // 创建一个接口对象,实现本地代理?private Button bind;//绑定Service的按钮private Button unbind;//解绑的按钮private Button getNum;//调用远程Service中接口方法的按钮@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);intent = new Intent("com.example.a_bindservice_a.MyBindService");bind = (Button) findViewById(R.id.btnbind);unbind = (Button) findViewById(R.id.btnUnbind);getNum = (Button) findViewById(R.id.btngetCount);getNum.setOnClickListener(this);bind.setOnClickListener(this);unbind.setOnClickListener(this);}@Overrideprotected void onDestroy() {super.onDestroy();if (cInterface != null) {unbindService(sConnection);cInterface = null;}};ServiceConnection sConnection = new ServiceConnection() {/** * onServiceDisconnected() 在连接正常关闭的情况下是不会被调用的, 该方法只在Service * 被破坏了或者被杀死的时候调用. 例如, 系统资源不足, 要关闭一些Services, 刚好连接绑定的 Service 是<span style="white-space:pre"></span> *被关闭者之一, * 这个时候onServiceDisconnected() 就会被调用。 * */@Overridepublic void onServiceDisconnected(ComponentName name) {System.out.println("onServiceDisconnected");cInterface = null;}/** * 在调用bindService方法时会回调此方法。 * 远程Service在onBind()方法必须返回一个binder对象,否则当前方法不会被调用。 * */@Overridepublic void onServiceConnected(ComponentName name, IBinder binder) {System.out.println("onServiceConnected");// 通过asInterface()方法获得接口CountInterface对象的引用实例。binder就是服务器Service返回的<span style="white-space:pre"></span>//binder对象。cInterface = CountInterface.Stub.asInterface(binder);}};// 为按钮添加监听@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnbind:bindService(intent, sConnection, BIND_AUTO_CREATE);break;case R.id.btnUnbind:if (cInterface != null) {unbindService(sConnection);cInterface = null;}break;case R.id.btngetCount:try {if (cInterface != null) {int i =cInterface.getCount();// 通过cInterface对象调用应用A的getCount()方法System.out.println("--------------->" + i);}} catch (RemoteException e) {System.out.println("RemoteException");e.printStackTrace();}break;default:break;}}}

需要注意的是:1.客户端使用服务器Service的接口方法时通过CountInterface接口的变量cInterface来实现的。

 2.客户端在bindService时需要使用ServiceConnection类型的变量,创建sConnection变量时使用匿名    内部类,并实现其中的两个方法。


到此运行程序。然后就可以在客户端程序B中使用服务器A中定义的接口方法了。

真正纯自己写的第一个Blog,参考了许多其他大神的博客。如有错误,欢迎探讨~~好开森~大笑大笑




1 1
原创粉丝点击