一、远程服务主要代码
1.IService.aidl

package com.shz.remoteservice; interface IService { String getTicketInfoById(int id); }
编译aidl文件自动生成的IService.java文件(存在于gen目录下)

/* * This file is auto-generated. DO NOT MODIFY. * Original file: E:\Code\Java\远程服务\src\com\shz\remoteservice\IService.aidl */ package com.shz.remoteservice; public interface IService extends android.os.IInterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.Binder implements com.shz.remoteservice.IService { private static final java.lang.String DESCRIPTOR = "com.shz.remoteservice.IService"; /** Construct the stub at attach it to the interface. */ public Stub() { this.attachInterface(this, DESCRIPTOR); } /** * Cast an IBinder object into an com.shz.remoteservice.IService interface, * generating a proxy if needed. */ public static com.shz.remoteservice.IService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof com.shz.remoteservice.IService))) { return ((com.shz.remoteservice.IService)iin); } return new com.shz.remoteservice.IService.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_getTicketInfoById: { data.enforceInterface(DESCRIPTOR); int _arg0; _arg0 = data.readInt(); java.lang.String _result = this.getTicketInfoById(_arg0); reply.writeNoException(); reply.writeString(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements com.shz.remoteservice.IService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public java.lang.String getTicketInfoById(int id) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); java.lang.String _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeInt(id); mRemote.transact(Stub.TRANSACTION_getTicketInfoById, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_getTicketInfoById = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); } public java.lang.String getTicketInfoById(int id) throws android.os.RemoteException; }
2.TicketService.java

package com.shz.remoteservice; import java.util.ArrayList; import java.util.List; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * 后台服务(组件),提供查询电影票相关信息 * @author SHZ * */ public class TicketService extends Service { private final static String TAG = "TicketService"; private List<Ticket> tickets; @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind 服务绑定成功"); // 2.Activity绑定服务成功之后,服务返回给Activity一个IBinder类型的对象, // 通过该对象,Activity就可以和服务进行交互了,就像一个代理一样 return new TicketBinder(); } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate 服务创建成功"); this.tickets = new ArrayList<Ticket>(); this.tickets.add(new Ticket(1, "变形金刚4", 103)); this.tickets.add(new Ticket(2, "窃听风云3", 86)); this.tickets.add(new Ticket(3, "反腐风暴", 75)); } @Override public void onStart(Intent intent, int startId) { Log.i(TAG, "onStart 服务启动"); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand 服务启动"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind 服务解绑成功"); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "onDestroy 服务销毁成功"); } private Ticket getTicket(int id) { for(Ticket ticket:this.tickets) { if(ticket.Id == id) { return ticket; } } return null; } /** * 服务内部方法:查询电影票信息 * @param id * @return */ public String getTicketInfo(int id) { Ticket ticket = this.getTicket(id); if(ticket == null) { return "未查询到该电影票信息"; } else { return ticket.toString(); } } /** * 服务内部方法(测试用,没有意义):更新电影票价格 * @param id * @param newPrice */ public void updateTicketPrice(int id, float newPrice) { Ticket ticket = this.getTicket(id); if(ticket != null) { ticket.Price = newPrice; } } /** * 自定义一个代理类,继承Binder并实现IService接口。 * 服务会返回该类的一个实例给调用者,调用者可通过该实例调用相应的类方法 * @author SHZ * */ private class TicketBinder extends IService.Stub { /** * 实现IService接口中的方法,调用服务内部的方法,这样调用服务的Activity就可以获取电影票信息了 */ @Override public String getTicketInfoById(int id) { return getTicketInfo(id); } /** * 由于该方法并未在IService接口中定义,故调用者无法使用该方法 * @param id * @param newPrice */ public void updateTicketPrice(int id,float newPrice) { updateTicketPrice(id, newPrice); } } }
3.Ticket.java(实体类)

package com.shz.remoteservice; public class Ticket { public int Id; public String Name; public float Price; public Ticket(int id, String name, float price) { Id = id; Name = name; Price = price; } @Override public String toString() { return "您查询的电影是:"+this.Name+",票价为:"+this.Price; } }
4.清单配置文件AndroidManifest.xml

<service android:name="com.shz.remoteservice.TicketService"> <intent-filter> <!-- 如果用于远程服务,则需指定action --> <action android:name="com.shz.TICKETSERVICE"/> </intent-filter> </service>
二、调用远程服务的代码
1.把远程服务工程里面的IService.aidl文件(包括包名)拷贝到调用者的工程中
2.调用代码

package com.shz.callremoteservice; 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.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.shz.remoteservice.IService; public class MainActivity extends Activity { private TicketServiceConnection conn; private IService ticketBinder; private EditText txtTicketId; private TextView lblTicketInfo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtTicketId = (EditText) findViewById(R.id.txtTicketId); lblTicketInfo = (TextView) findViewById(R.id.lblTicketInfo); } private class TicketServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 2.绑定服务成功之后,后台服务会返回IBinder类型的 service 对象,通过该对象可以间接调用后台服务的方法 ticketBinder = IService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } } /** * 绑定服务 * @param view */ public void bindService(View view) { Intent service = new Intent(); service.setAction("com.shz.TICKETSERVICE"); // 通过action指定要调用的服务 // 1.绑定服务 // service:服务意图 // new TicketServiceConnection():与后台服务连接的对象,接收后台服务信息 // BIND_AUTO_CREATE:如果服务没有被创建,则自动创建并绑定 conn = new TicketServiceConnection(); bindService(service, conn, BIND_AUTO_CREATE); } @Override protected void onDestroy() { try { unbindService(conn); } catch (Exception e) { } super.onDestroy(); } public void callServiceMethod(View view) { if(this.ticketBinder == null) { Toast.makeText(this, "请先绑定服务", 1).show(); } else { String strTicketId = this.txtTicketId.getText().toString().trim(); if(TextUtils.isEmpty(strTicketId)) { Toast.makeText(this, "请输入电影票Id", 1).show(); return; } try { // 3.调用IBinder对象的方法 String ticketInfo = this.ticketBinder.getTicketInfoById(Integer.parseInt(strTicketId)); this.lblTicketInfo.setText(ticketInfo); } catch (NumberFormatException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } } }
3.前台UI布局代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.shz.localservice.MainActivity" tools:ignore="MergeRootFrame" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="bindService" android:text="绑定服务" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入电影票Id" android:id="@+id/txtTicketId"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="callServiceMethod" android:text="查询" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/lblTicketInfo" android:textColor="#ff0000"/> </LinearLayout>
调用服务前必须先绑定服务(当然了,远程服务必须首先启动起来)
调用结果截图: