android AIDL服务

android的本地服务:它只能由承载它的应用程序使用。现在我们将介绍如何构建可由其他进程通过 RPC 使用服务。与许多其他基于 RPC 的解决方案一样,在Android中,需要使用 IDL来定义将向客户端公开的接口。在Android中,这个 IDL 称为 AIDL。要构建远程服务,执行以下步骤。

(1)编写一个AIDL文件来向客户端定义接口。AIDL 文件使用 java语法,它的扩展名是点 .aidl 使用的包名称与Android项目所使用的包相同。

(2)将AIDL 文件添加到项目的任意包下。Android Eclipse 插件将调用AIDL编译器来从 AIDL 文件生成 Java接口。

上边这2步说白了就是  你自己随便定义一个文件 扩展名是 .aidl 然后将这个文件复制到你的包下面,那个包都可以。然后 Android Eclipse 插件会自动帮你 根据这个 AIDL 文件生成 Java文件。

(3)实现一个服务并从 onBind()方法返回所生成的接口。

(4)将服务配置添加到 AndroidManifest.xml文件中。

在AIDL中定义服务接口

为了展示远程服务实例,我们将编写一个股票报价服务。此服务将提供一种方法来获取股票代号并返回价格。要在Android 中编写远程服务,第一步是在 AID文件中定义服务的接口。

股票报价服务的 AIDL 定义

1.//This file is IStockQuoteService.aidl

2.package com.androidbook.stockquoteservice;

3.interface IStockQuoteService

4.{

  1. double getQuote(String ticker);

6.}

IStockQuoteService 以字符串的形式接受股票代号,并以双精度数字形式返回当前的股票价值。当创建AIDL文件时, Android Eclipse插件将运行 AIDL 编译器来处理 AIDL文件(在构建过程中)。如果AIDL文件成功编译,编译器将生成一个适合 RPC 通信的 Java接口。请注意,生成的文件将位于在 AIDL文件中指定的包中,在本例中为 com.androidbook.stockquoteservice。

下面是为 IStockQuoteService接口生成的Java文件。生成的文件将放在Eclipse的 gen文件夹中。

1./*

    • This file is auto-generated. DO NOT MODIFY.
    • Original file: F:\workspace\StockQuoteService\src\com\androidbook\stockquoteservice\IStockQuoteService.aidl
  1. */

5.package com.androidbook.stockquoteservice;

6.public interface IStockQuoteService extends android.os.IInterface

7.{

8./** Local-side IPC implementation stub class. */

9.public static abstract class Stub extends android.os.Binder implements com.androidbook.stockquoteservice.IStockQuoteService

10.{

11.private static final java.lang.String DESCRIPTOR = “com.androidbook.stockquoteservice.IStockQuoteService”;

12./** Construct the stub at attach it to the interface. */

13.public Stub()

14.{

15.this.attachInterface(this, DESCRIPTOR);

16.}

17./**

    • Cast an IBinder object into an com.androidbook.stockquoteservice.IStockQuoteService interface,
    • generating a proxy if needed.
  1. */

21.public static com.androidbook.stockquoteservice.IStockQuoteService asInterface(android.os.IBinder obj)

22.{

23.if ((obj==null)) {

24.return null;

25.}

26.android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);

27.if (((iin!=null)&&(iin instanceof com.androidbook.stockquoteservice.IStockQuoteService))) {

28.return ((com.androidbook.stockquoteservice.IStockQuoteService)iin);

29.}

30.return new com.androidbook.stockquoteservice.IStockQuoteService.Stub.Proxy(obj);

31.}

32.public android.os.IBinder asBinder()

33.{

34.return this;

35.}

36.@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

37.{

38.switch (code)

39.{

40.case INTERFACE_TRANSACTION:

41.{

42.reply.writeString(DESCRIPTOR);

43.return true;

44.}

45.case TRANSACTION_getQuote:

46.{

47.data.enforceInterface(DESCRIPTOR);

48.java.lang.String _arg0;

49._arg0 = data.readString();

50.double _result = this.getQuote(_arg0);

51.reply.writeNoException();

52.reply.writeDouble(_result);

53.return true;

54.}

55.}

56.return super.onTransact(code, data, reply, flags);

57.}

58.private static class Proxy implements com.androidbook.stockquoteservice.IStockQuoteService

59.{

60.private android.os.IBinder mRemote;

61.Proxy(android.os.IBinder remote)

62.{

63.mRemote = remote;

64.}

65.public android.os.IBinder asBinder()

66.{

67.return mRemote;

68.}

69.public java.lang.String getInterfaceDescriptor()

70.{

71.return DESCRIPTOR;

72.}

73.public double getQuote(java.lang.String ticker) throws android.os.RemoteException

74.{

75.android.os.Parcel _data = android.os.Parcel.obtain();

76.android.os.Parcel _reply = android.os.Parcel.obtain();

77.double _result;

78.try {

79._data.writeInterfaceToken(DESCRIPTOR);

80._data.writeString(ticker);

81.mRemote.transact(Stub.TRANSACTION_getQuote, _data, _reply, 0);

82._reply.readException();

83._result = _reply.readDouble();

84.}

85.finally {

86._reply.recycle();

87._data.recycle();

88.}

89.return _result;

90.}

91.}

92.static final int TRANSACTION_getQuote = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

93.}

94.public double getQuote(java.lang.String ticker) throws android.os.RemoteException;

95.}

对于所生成的类,请注意以下几点。

在 AIDL 文件中定义的接口在生成的代码中实现为接口 (也就是说,有一个名为IStockQuoteService的接口)。

名为Stub的 static final 抽象类扩展了 android.os.Binder并实现了 IStockQuoteService。请注意该类是一个抽象类。

名为 Proxy的内部类实现了 IStockQuoteService, 后者是Stub类的代理。

AIDL文件必须位于应该包含所生成文件的包中(在AIDL文件的包声明中指定)。

在服务类中实现AIDL接口

上边我们为股票报价服务定义了 AIDL 文件并生成了绑定文件。现在我们将提供该服务的实现。要实现服务的接口,需要编写一个类来扩展 android.app.Service 并实现 IStockQuoteService接口。我们将编写的类 命名为 StockQuoteService。为了将服务向客户端公开,StockQuoteService 需要提供onBind()方法 的实现,我们还需要将一些配置信息添加到 AndroidManifest.xml文件中。  下面给出 我们服务类得实现。

IStockQuoteService 服务实现。

package com.androidbook.stockquoteservice;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

public class StockQuoteService extends Service {

private static final String TAG = “StockQuoteService”;

public class StockQuoteServiceImpl extends IStockQuoteService.Stub {

@Override

public double getQuote(String ticker) throws RemoteException {

Log.v(TAG, "getQuote() called for " + ticker);

return 20.0;

}

}

@Override

public void onCreate() {

super.onCreate();

Log.v(TAG, “onCreate called”);

}

@Override

public void onDestroy() {

super.onDestroy();

Log.v(TAG, “onDestory() called”);

}

@Override

public void onStart(Intent intent, int startId) {

super.onStart(intent, startId);

Log.v(TAG, “onStart() called”);

}

@Override

public IBinder onBind(Intent intent) {

Log.v(TAG, “onBind() called”);

return new StockQuoteServiceImpl();

}

}

在这个服务类中大家可以看到我们实现了 onBind() 方法。从AIDL文件生成的 Stub类是抽象类并且它实现了 IStockQuoteService接口。在我们的服务实现中,有一个扩展了 Stub类得内部类,名为 StockQuoteServiceImpl。此类充当着远程服务实现,而且 onBind()方法会返回此类的实例。到此,我们有了一个有效的 ADIL服务,但是外部的客户端还无法连接到它。

要将服务向客户端公开,需要在AndroidManifest.xml文件中添加服务声明,而这一次我们需要一个Intent 过滤器来公开服务,如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从客户端应用程序调用服务

当客户端与服务通信时,它们之间必须有一个协议或契约。在Android中,这个契约就是AIDL。所以,使用服务的第一步是,获取服务的 AIDL文件并将其复制到客户端项目中。当将AIDL文件复制到客户端项目时,AIDL 编译器将创建一个接
口定义文件,这个文件与我们在服务端定义的文件相同。这会向客户端公开所有的方法、参数并返回服务的类型。我们创建一个新项目并复制AIDL文件。

(1)创建一个新的Android项目, 将其命名为 StockQuoteClient。使用不同的包名称比如 com.androidbook.stockquoteclient。在Create Activity字段中使用 MainActivity注意不要把IStockQuoteService.aidl文件放到这包中,这个包只有一个MainActivity 类。

(2)在此项目中新建一个包 com.androidbook.stockquoteservice,放在src目录下。

(3)将IStockQuoteService.aidl文件从 StockQuoteService 项目也就是我们服务端得项目复制到新建的包中。复制过来之后,AIDL编译器会自动生成关联的java文件。

重新生成的服务接口充当着客户端与服务之间的契约。下一步是获取服务的引用,以便调用getQuote()方法。对于远程服务,必须调用 bindService()方法,而不是 startService()方法。

客户端布局文件

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”

android:orientation=“vertical”

android:layout_width=“fill_parent”

android:layout_height=“fill_parent”

<Button

android:id=“@+id/bindBtn”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“Bind”/>

<Button

android:id=“@+id/callBtn”

android:layout_height=“wrap_content”

android:layout_width=“wrap_content”

android:text=“Call Again”/>

<Button

android:id=“@+id/unbindBtn”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“UnBind”/>

MainActivity类

package com.androidbook.stockquoteclient;

import com.androidbook.stockquoteservice.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.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

public class MainActivity extends Activity {

protected static final String TAG = “StockQuoteClient”;

private IStockQuoteService stockService = null;

private Button bindBtn;

private Button callBtn;

private Button unbindBtn;

@Override

le;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

public class MainActivity extends Activity {

protected static final String TAG = “StockQuoteClient”;

private IStockQuoteService stockService = null;

private Button bindBtn;

private Button callBtn;

private Button unbindBtn;

@Override

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值