在android中要构建远程(不同进程之间)服务,需要使用AIDL实现
一,服务端:
1,AIDL定义:AIDL定义之后,编译器会自动在R文件中生成AIDL的java文件
package com.cjf.stock1; interface IStockQuoteService { double getQuote(String ticker); }
2,实现AIDL接口
package com.cjf.stock1; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; //服务类继承必须SERVICE public class StockQuoteService extends Service { private static final String TAG = "StockQuoteService"; //实现AIDL(IStockQuoteService.Stub)接口,此类充当着远程服务的实现,并且onBind()方法返回此类的实例 public class StockQuoteServiceImpl extends IStockQuoteService.Stub{ public double getQuote(String ticker) throws RemoteException { Log.i(TAG, "getQuote() called for " + ticker); return 20.0; } } //在onCreate()之后被调用 @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind() called "); return new StockQuoteServiceImpl();//返回AIDL的一个实例 } //当绑定服务时,此方法首先被调用,做一些初始化工作,(每次绑定都会被调用) @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate() called "); } //解除绑定时,此方法会被调用 @Override public void onDestroy() { Log.i(TAG, "onDestory() called "); super.onDestroy(); } }
3,描述文件androidmanifest.xml声明
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cjf.stock1" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <service android:name=".StockQuoteService"> <intent-filter> <!-- 为希望公开的服务接口添加filter --> <action android:name="com.cjf.stock1.IStockQuoteService"/> </intent-filter> </service> </application> </manifest>
二,客户端
从客户端应用程序调用服务,注意在客户端项目中必须复制服务端的AIDL接口文件,且包名与服务端需保持一致。
1,main.xml布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <ToggleButton android:id="@+id/bindBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textOn="Bind" android:textOff="Unbind" android:onClick="doClick" /> <Button android:id="@+id/callBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="call service" android:enabled="false" android:onClick="doClick"/> </LinearLayout>
2,MainActivity
package com.cjf.client1; import com.cjf.stock1.IStockQuoteService; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.widget.ToggleButton; //客户端复制服务端的AIDL文件,且AIDL文件的包名必须和服务端相同 public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private IStockQuoteService stockService = null; private ToggleButton bindBtn; private Button callBtn; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); bindBtn = (ToggleButton) this.findViewById(R.id.bindBtn); callBtn = (Button) this.findViewById(R.id.callBtn); } public void doClick(View v){ switch(v.getId()){ case R.id.bindBtn: if(((ToggleButton)v).isChecked()){ //属于异步调用 bindService(new Intent(IStockQuoteService.class.getName()),//AIDL服务的名称 serConn,//链接的一个实例 Context.BIND_AUTO_CREATE);//自动创建服务的标识 }else{ unbindService(serConn); callBtn.setEnabled(false); } break; case R.id.callBtn: callService();//调用服务 break; } } //调用服务的方法 private void callService(){ try { double val = stockService.getQuote("ANDROID"); Toast.makeText(this, "value from service is " + val, Toast.LENGTH_LONG).show(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //绑定和解除服务时需使用此对象(服务链接对象) private ServiceConnection serConn = new ServiceConnection(){ //链接成功时调用 public void onServiceConnected(ComponentName name, IBinder service) { Log.i(TAG, "onServiceConnected called "); stockService = IStockQuoteService.Stub.asInterface(service);//得到AIDL的一个引用 bindBtn.setChecked(true);//选中状态 callBtn.setEnabled(true);//可用状态 } //服务崩溃时自动调用 public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "onServiceDisconnected called "); bindBtn.setChecked(false);//选中状态 callBtn.setEnabled(false);//可用状态 stockService = null; }}; @Override protected void onDestroy() { Log.i(TAG, "onDestroy() called "); if(callBtn.isEnabled()){ unbindService(serConn); } super.onDestroy(); } }
点击Bind按钮时: