一、远程服务主要代码
1.IService.aidl
package com.shz.remoteservice;
interface IService {
String getTicketInfoById(int id);
}
View Code
编译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;
}
View Code
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);
}
}
}
View Code
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;
}
}
View Code
4.清单配置文件AndroidManifest.xml
<service android:name="com.shz.remoteservice.TicketService">
<intent-filter>
<!-- 如果用于远程服务,则需指定action -->
<action android:name="com.shz.TICKETSERVICE"/>
</intent-filter>
</service>
View Code
二、调用远程服务的代码
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();
}
}
}
}
View Code
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>
View Code
调用服务前必须先绑定服务(当然了,远程服务必须首先启动起来)
调用结果截图: