- 浏览: 1381888 次
- 性别:
- 来自: 陕西.西安
文章分类
最新评论
-
dare_:
经过试验 设置之后反而更慢没有调用ensureCapacity ...
ensureCapacity()方法提高ArrayList的初始化速度 -
wangchao9053:
[flash=200,200][url][img][list] ...
Only the original thread that created a view hierarchy can touch its views的相关 -
cyb504:
考虑将rb文件代码隐藏:我先使用命令jrubyc将所有rb文件 ...
Ruby学习十 JRuby中调用java代码 -
4562xse3460:
大哥,您这个写反了,差点误导我,我觉得看着就不对。百度第一条就 ...
portrait表示纵向,landscape表示横向 -
yin138:
portrait是肖像画,即竖屏,landscape是风景画, ...
portrait表示纵向,landscape表示横向
目录
1 使用AIDL(AndRoid接口描述语言)设计和使用远程接口
1.1 使用AIDL实现IPC
1.1.1 创建一个AIDL文件
1.1.2 实现接口
1.1.3 向客户端公开接口
1.1.4 使用parcelables进行参数的值传递
1.2 调用一个IPC方法
使用AIDL(AndRoid接口描述语言)设计和使用远程接口
Since each application
runs in
its own process, and you can write a service that runs in a different
process
from your Application's UI, sometimes you need to pass objects between
processes. On the Android platform, one process can not normally access
the
memory of another process. So to talk, they need to decompose their
objects into
primitives that the operating system can understand, and "marshall" the
object
across that boundary for you.
通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的
service。在AndRoid平台中,一个进程通常不能访问其他进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成
对象跨越边界访问。
The code to do that marshalling is tedious to write, so we
provide the
AIDL tool to do it for you.
编写这种伪装代码相当的枯燥乏味,好在我们提供了AIDL工具可以来做这件
事。
AIDL (Android Interface Definition Language) is an IDL language
used to
generate code that enables two processes on an Android device to talk
using
interprocess communication (IPC). If you have code in one process (for
example,
in an Activity) that needs to call methods on an object in another
process (for
example, a Service), you would use AIDL to generate code to marshall the
parameters.
AIDL(AndRoid接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个AndRoid设备上运行的两个进程使用内
部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以
使用AIDL来生成这样的代码来伪装传递各种参数。
The AIDL IPC mechanism is interface-based, similar to COM or
Corba, but
lighter weight. It uses a proxy class to pass values between the client
and the
implementation.
AIDL
IPC的机制是基于接口的,和COM或Corba类似,但它是轻量级的。它使用代理类在客户端和实现层间传递值。
This page
includes
the following main topics:
本页包含以下主题:
Implementing IPC
Using AIDL
Calling an .aidl (IPC) Class
使用AIDL实现IPC
调用一个
AIDL(IPC)类
使用AIDL实现IPC
Follow these steps to implement an IPC
service
using AIDL.
使用AIDL实现一个IPC有下列步骤:
1.Create your .aidl file
- This
file defines an interface (YourInterface.aidl) that defines the methods
and
fields available to a client.
1、创建你的AIDL文件 -
这个文件定义一个接口(YourInterface.aidl),该接口定义了可供客户端访问的方法和属性。
2.Add the
.aidl file
to your makefile - (the Eclipse plugin manages this for you). Android
includes
the compiler, called AIDL, in the tools/ directory.
2、添加AIDL文件到你的makefile中-(Eclipse
plugin可以帮你管理)。AndRoid包括编译器,AIDL调用,这些都能在tools/directory中找到。
3.Implement
your interface methods - The AIDL compiler creates an interface in the
Java
programming language from your AIDL interface. This interface has an
inner
abstract class named Stub that inherits the interface (and implements a
few
additional methods necessary for the IPC call). You must create a class
that
extends YourInterface.Stub and implements the methods you declared in
your .aidl
file.
3、实现接口方法-AIDL编译器从你的AIDL接口中使用JAVA编程语言来创建一个接口。这个接口有一个名为Stub的内部抽象类,
它继承接口(并实现供IPC调用的所必需的几个附加方法)。你必须创建一个类来实现该接口。
4.Expose your interface to clients - If you're writing a
service, you
should extend Service and override getBinder() to returning an instance
of your
class that implements your interface.
4、向客户端开放接口-如果你写个service,你应该扩展该Service并重载getBinder()方法来返回一个实现上述接口
的类的实例。
[编辑] 创建一个AIDL文件
AIDL is a simple syntax that lets you
declare an
interface with one or more methods, that can take parameters and return
values.
These parameters and return values can be of any type, even other
AIDL-generated
interfaces. However, it is important to note that you must import all
non-built-in types, even if they are defined in the same package as your
interface. Here are the data types that AIDL can support:
AIDL语法简单,你可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。这些参数和返回值可以是任何类型,甚至是其他的
AIDL生成的接口。然而,值得重视的是你必须导入所有的non-bult-in类型,即使他们已经作为接口在其他包里定义了。下面是些AIDL支持的数
据类型:
Primitive Java programming language types (int, boolean, etc) —
No
import statement is needed.
简单Java编程语言类型(int,boolean等)
-不需要import声明。
One of the following classes (no import statements needed):
下面类之一(不需要import声明)
- .String
- .List - All elements in the List must be one of the types in this list, including other AIDL-generated interfaces
- and parcelables. List may optionally be used as a "generic" class (e.g. List<String>). The actual concrete class
- that the other side will receive will always be an ArrayList, although the method will be generated to use the
- List interface .
- .List - List中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和 parcelables。List可以作为泛型类来灵活使用(比如
- List<String>)。而实际的接受方的类则总是ArrayList,尽管该 方法将被生成来使用List接口。
- .Map - All elements in the Map must be of one of the types in this list, including other AIDL-generated interfaces
- and parcelables. Generic maps, (e.g. of the form Map<String,Integer> are not supported. The actual concrete class
- that the other side will receive will always be a HashMap,although the method will be generated to use the Map interface .
- .Map - Map中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和 parcelables。泛型化的Maps(比如:Map<Stirng,Integer>)不被支持。
- 而实际的接受方的类则总是HashMap,尽管该方法将被生成去使用Map接口。
- .CharSequence - This is useful for the CharSequence types used by TextView and other widget objects.
- .CharSequence - CharSequence的作用是可以被TextView和其他 Widget对象使用。
.String .List - All elements in the List must be one of the types in this list, including other AIDL-generated interfaces and parcelables. List may optionally be used as a "generic" class (e.g. List<String>). The actual concrete class that the other side will receive will always be an ArrayList, although the method will be generated to use the List interface. .List - List中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。List可以作为泛型类来灵活使用(比如 List<String>)。而实际的接受方的类则总是ArrayList,尽管该方法将被生成来使用List接口。 .Map - All elements in the Map must be of one of the types in this list, including other AIDL-generated interfaces and parcelables. Generic maps, (e.g. of the form Map<String,Integer> are not supported. The actual concrete class that the other side will receive will always be a HashMap,although the method will be generated to use the Map interface. .Map - Map中的所有元素都必须是可支持的类型中的一个,包括其他AIDL生成接口和parcelables。泛型化的Maps(比如:Map<Stirng,Integer>)不被支持。 而实际的接受方的类则总是HashMap,尽管该方法将被生成去使用Map接口。 .CharSequence - This is useful for the CharSequence types used by TextView and other widget objects. .CharSequence - CharSequence的作用是可以被TextView和其他Widget对象使用。
Other AIDL-generated interfaces, which are always passed
by
reference. An import statement is always needed for these. Custom
classes that
implement the Parcelable protocol and are passed by value. An import
statement
is always needed for these.
其他的AIDL生成接口通过引用方式进行传递。所以import声明是必须的。封装协议实现的自定义的类是值传递的方式。所以
import声明也是必须的。
Here is the basic AIDL syntax:
下面是基本的AIDL语法:
- // My AIDL file, named SomeClass.aidl
- // Note that standard comment syntax is respected.
- // Comments before the import or package statements are not bubbled up
- // to the generated interface, but comments above interface/method/field
- // declarations are added to the generated interface.
- // Include your fully-qualified package statement.
- package com.google.android.sample;
- // See the list above for which classes need
- // import statements (hint--most of them)
- import com.google.android.sample.IAtmService;
- // Declare the interface.
- interface IBankAccountService {
- // Methods can take 0 or more parameters, and
- // return a value or void.
- int getAccountBalance();
- void setOwnerNames(in List<String> names);
- // Methods can even take other AIDL-defined parameters.
- BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService);
- // All non-Java primitive parameters (e.g., int, bool, etc) require
- // a directional tag indicating which way the data will go. Available
- // values are in, out, inout. (Primitives are in by default, and cannot be otherwise).
- // Limit the direction to what is truly needed, because marshalling parameters
- // is expensive.
- int getCustomerList(in String branch, out String[] customerList);
- }
// My AIDL file, named SomeClass.aidl // Note that standard comment syntax is respected. // Comments before the import or package statements are not bubbled up // to the generated interface, but comments above interface/method/field // declarations are added to the generated interface. // Include your fully-qualified package statement. package com.google.android.sample; // See the list above for which classes need // import statements (hint--most of them) import com.google.android.sample.IAtmService; // Declare the interface. interface IBankAccountService { // Methods can take 0 or more parameters, and // return a value or void. int getAccountBalance(); void setOwnerNames(in List<String> names); // Methods can even take other AIDL-defined parameters. BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService); // All non-Java primitive parameters (e.g., int, bool, etc) require // a directional tag indicating which way the data will go. Available // values are in, out, inout. (Primitives are in by default, and cannot be otherwise). // Limit the direction to what is truly needed, because marshalling parameters // is expensive. int getCustomerList(in String branch, out String[] customerList); }
实现接口
AIDL generates an interface file for you with
the
same name as your .aidl file. If you are using the Eclipse plugin, AIDL
will
automatically be run as part of the build process (you don't need to run
AIDL
first and then build your project). If you are not using the plugin, you
should
run AIDL first.
AIDL生成一个接口文件,文件名和你的AIDL文件名一致。如果你使用的是Eclipse插件,AIDL会作为build过程的一部分
自动运行(你不需要首先运行ADIL然后再去创建你的项目)。否则的话,你需要首先运行AIDL。
The generated interface includes an abstract inner class named
Stub that
declares all the methods that you declared in your .aidl file. Stub also
defines
a few helper methods, most notably asInterface(), which takes an IBinder
(passed
to a client's onServiceConnected() implementation when
applicationContext.bindService() succeeds), and returns an instance of
the
interface used to call the IPC methods. See the section Calling an IPC
Method
for more details on how to make this cast.
生成的接口包括一个名为Stub的内部抽象类,该类声明了你在aidl文件中声明的所有方法。Stub也定义几个有用的方法,最特别的是
asInterface(),它执行一个IBinder(在
applicationContext.bindService()执行成功后传给客户端onServiceConnected()方法),并返回一个用
来调用IPC方法的接口实例。更多细节请查看章节调用IPC方法。
To implement your interface, extend YourInterface.Stub, and
implement
the methods. (You can create the .aidl file and implement the stub
methods
without building between--the Android build process will process .aidl
files
before .java files.)
实现接口,扩展YourInterface.Stub,并实现方法成员。(你可以创建一个aidl文件并实现stub方法而不用绑定
-AndRoid创建过程在java文件之前会处理aidl文件)。
Here is an example of implementing an interface called
IRemoteService,
which exposes a single method, getPid(), using an anonymous instance:
这里有个例子,它实现了一个调用IRemoteService的接口,并使用匿名实例公开一个简单的方法gerPid():
- // No need to import IRemoteService if it's in the same project.
- private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){
- public int getPid(){
- return Process.myPid();
- }
- }
// No need to import IRemoteService if it's in the same project. private final IRemoteService.Stub mBinder = new IRemoteService.Stub(){ public int getPid(){ return Process.myPid(); } }
A few rules about implementing your interface:
实现接口时有几个原则:
- .No exceptions that you throw will be sent back to the caller.
- .抛出的异常不要返回给调用者。
- .IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete,
- you should not call it in the Activity/View thread, because it might hang the application (Android might display
- an "Application is Not Responding" dialog). Try to call them in a separate thread.
- .IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在 Activity/View线程中调用。
- 因为它会挂起应用程序(AndRoid可能会显示 "应用程序没有响应" 对 话框)。试着在一个独立的线程中调用。
- .Only methods are supported; you cannot declare static fields in an AIDL interface .
- .只有方法才获得支持;你不能在AIDL接口中声明静态属性。
.No exceptions that you throw will be sent back to the caller. .抛出的异常不要返回给调用者。 .IPC calls are synchronous. If you know that an IPC service takes more than a few milliseconds to complete, you should not call it in the Activity/View thread, because it might hang the application (Android might display an "Application is Not Responding" dialog). Try to call them in a separate thread. .IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity/View线程中调用。 因为它会挂起应用程序(AndRoid可能会显示"应用程序没有响应"对话框)。试着在一个独立的线程中调用。 .Only methods are supported; you cannot declare static fields in an AIDL interface. .只有方法才获得支持;你不能在AIDL接口中声明静态属性。
向客户端公开接口
Now that
you've got
your interface implementation, you need to expose it to clients. This is
known
as "publishing your service." To publish a service, inherit Service and
implement getBinder() to return an instance of the class that implements
your
interface. Here's a code snippet of a service that exposes the
IRemoteService
interface to clients
现在你已完成了接口的实现,你需要向客户端公开该实现。这就是我们所熟悉的"发布服务"。发布一个Service,然后继承
Service并实现getBinder()返回一个实现的类的实例。下面是个Service的代码片断,该Service向客户端公了
IRemoteService接口。
- public class RemoteService extends Service {
- ...
- @Override
- public IBinder getBinder() {
- return mBinder;
- }
- /**
- * The IRemoteInterface is defined through IDL
- */
- private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
- public int getPid() {
- return Process.myPid();
- }
- };
- }
public class RemoteService extends Service { ... @Override public IBinder getBinder() { return mBinder; } /** * The IRemoteInterface is defined through IDL */ private final IRemoteService.Stub mBinder = new IRemoteService.Stub() { public int getPid() { return Process.myPid(); } }; }
使用parcelables进行参数的值传递
- Warning: Parcelables currently do not work if you're using the Eclipse plugin. You will see these errors if you try : 警 告:如果你现在使用Eclipse插件,Parcelables并不能工作。你会看到以下的错误信息:
- .aidl files that only declare parcelables don't need to go in the makefile
- .仅声明parcelables的.aidl文件不需要写进makefile
- .aidl can only generate code for interfaces, not parcelables
- .aidl只能生成接口代码,而不是parcelables。
- This is a known limitation. Parcelables can still be used with the ant build.xml files or your own custom build system. A workaround is for you to run the aidl tool by hand for all of your interfaces and add them to your Eclipse project. See step 5 below for why Eclipse shouldn't be trying to compile these aidl files.
- 这是个众所周知的局限。Parcelables仍然 可以被ant build的xml文件或自定义的build系统所使用。你应该在Eclipse项目中添加一个工作区,该工作区可以为所有的接口手动运行 aidl工具。下面的步骤 5 说明为何Eclipse不该尝试编译这些aidl文件。
Warning: Parcelables currently do not work if you're using the Eclipse plugin. You will see these errors if you try: 警告:如果你现在使用Eclipse插件,Parcelables并不能工作。你会看到以下的错误信息: .aidl files that only declare parcelables don't need to go in the makefile .仅声明parcelables的.aidl文件不需要写进makefile .aidl can only generate code for interfaces, not parcelables .aidl只能生成接口代码,而不是parcelables。 This is a known limitation. Parcelables can still be used with the ant build.xml files or your own custom build system. A workaround is for you to run the aidl tool by hand for all of your interfaces and add them to your Eclipse project. See step 5 below for why Eclipse shouldn't be trying to compile these aidl files. 这是个众所周知的局限。Parcelables仍然可以被ant build的xml文件或自定义的build系统所使用。你应该在Eclipse项目中添加一个工作区,该工作区可以为所有的接口手动运行aidl工具。下面的步骤5说明为何Eclipse不该尝试编译这些aidl文件。
If you have a class that you would like to send from one
process
to another through an AIDL interface, you can do that. You must ensure
that the
code for your class is available to the other side of the IPC.
Generally, that
means that you're talking to a service that you started.
如果你有类需要通过AIDL接口从一个进程发送到另一个,你必须确保类代码可以被IPC接收端所使用。通常这意味着一开始你就要和
service进行通讯。
There are five parts to making a class support the Parcelable
protocol:
让类支持parcelable协议,有五点需要注意
- 1 .Make your class implement the Parcelable interface .
- 1 . 让类实现 Parcelable接口。
- 2 .Implement the method public void writeToParcel(Parcel out) that takes the current state of the object and writes it
- to a parcel.
- 2 . 实 现 public void writeToParcel(Parcel out), 该方法可以将当前对象的状态写入parcel.
- 3 .Implement the method public void readFromParcel(Parcel in) that reads the value in a parcel into your object.
- 3 . 实现 public void readFromParcel(Parcel in), 该方法可以在parcel中读出值到对象中.
- 4 .Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface .
- 4 . 向类中添加一个静态成员,名为 CREATOR。该对象实现了Parcelable.Creator接口.
- 5 .Last but not least, add an aidl file for your parcelable class so the AIDL tool can find it, but don't add it to your
- build. This file is used like a header file in C. You don 't compile the aidl file for a parcelable just like you wouldn' t
- normally compile a .h file.
- 5 . 向 parcelable类中添加一个.aidl文件,以便AIDl工具可以找到。但不要向build中添加该文件。该文件的用法类似于C中的头文件.你不需 要为parcelable
- 编译aidl文件,就像你不会编译个.h文件一样。
1.Make your class implement the Parcelable interface. 1. 让类实现Parcelable接口。 2.Implement the method public void writeToParcel(Parcel out) that takes the current state of the object and writes it to a parcel. 2. 实现public void writeToParcel(Parcel out),该方法可以将当前对象的状态写入parcel. 3.Implement the method public void readFromParcel(Parcel in) that reads the value in a parcel into your object. 3. 实现public void readFromParcel(Parcel in),该方法可以在parcel中读出值到对象中. 4.Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creator interface. 4. 向类中添加一个静态成员,名为CREATOR。该对象实现了Parcelable.Creator接口. 5.Last but not least, add an aidl file for your parcelable class so the AIDL tool can find it, but don't add it to your build. This file is used like a header file in C. You don't compile the aidl file for a parcelable just like you wouldn't normally compile a .h file. 5. 向parcelable类中添加一个.aidl文件,以便AIDl工具可以找到。但不要向build中添加该文件。该文件的用法类似于C中的头文件.你不需要为parcelable 编译aidl文件,就像你不会编译个.h文件一样。
AIDL will use these methods
and fields
in the code it generates to marshall and unmarshall your objects.
AIDL将使用代码中生成的这些方法和成员来伪装或解读对象。
Here is an example of how
the Rect
class implements the Parcelable protocol.
下面的例子说明了Rect类如何实现了Parcelable协议.
- import android.os.Parcel;
- import android.os.Parcelable;
- public final class Rect implements Parcelable {
- public int left;
- public int top;
- public int right;
- public int bottom;
- public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect> {
- public Rect createFromParcel(Parcel in) {
- return new Rect(in);
- }
- public Rect[] newArray( int size) {
- return new Rect[size];
- }
- };
- public Rect() { }
- private Rect(Parcel in) {
- readFromParcel(in);
- }
- public void writeToParcel(Parcel out) {
- out.writeInt(left);
- out.writeInt(top);
- out.writeInt(right);
- out.writeInt(bottom);
- }
- public void readFromParcel(Parcel in) {
- left = in.readInt();
- top = in.readInt();
- right = in.readInt();
- bottom = in.readInt();
- }
- }
import android.os.Parcel; import android.os.Parcelable; public final class Rect implements Parcelable { public int left; public int top; public int right; public int bottom; public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect> { public Rect createFromParcel(Parcel in) { return new Rect(in); } public Rect[] newArray(int size) { return new Rect[size]; } }; public Rect() { } private Rect(Parcel in) { readFromParcel(in); } public void writeToParcel(Parcel out) { out.writeInt(left); out.writeInt(top); out.writeInt(right); out.writeInt(bottom); } public void readFromParcel(Parcel in) { left = in.readInt(); top = in.readInt(); right = in.readInt(); bottom = in.readInt(); } }
Here is Rect.aidl for this example
示例的Rect.aidl
- package android.graphics;
- // Declare Rect so AIDL can find it and knows that it implements
- // the parcelable protocol.
- parcelable Rect;
package android.graphics; // Declare Rect so AIDL can find it and knows that it implements // the parcelable protocol. parcelable Rect;
The marshalling in the Rect class is
pretty
simple. Take a look at the other methods on Parcel to see the other
kinds of
values you can write to a Parcel.
Rect类中的伪装是相当简单的。仔细看看Parcel中的其他方法,你会看到其他各种值你都可以写进Parcel.
- Warning: Don't forget the security implications of receiving data from other processes. In this case , the rect will read four numbers from the parcel, but it is up to you to ensure that these are within the acceptable range of values for whatever the caller is trying to do . See Security and Permissions in Android for more on how to keep your application secure from malware.
- 警告:不要忽视从其他进程接收数据时 的安全性考虑。在本例中,rect将从parcel中读四个数字,而你的工作则是确保这些都在可接受的值得范围内而不管调用者想要干什么。AndRoid 中的安全和访问许可中有更多关于如何确保应用程序安全的信息。
Warning: Don't forget the security implications of receiving data from other processes. In this case, the rect will read four numbers from the parcel, but it is up to you to ensure that these are within the acceptable range of values for whatever the caller is trying to do. See Security and Permissions in Android for more on how to keep your application secure from malware. 警告:不要忽视从其他进程接收数据时的安全性考虑。在本例中,rect将从parcel中读四个数字,而你的工作则是确保这些都在可接受的值得范围内而不管调用者想要干什么。AndRoid中的安全和访问许可中有更多关于如何确保应用程序安全的信息。
调用一个IPC方法
Here are the steps a calling class
should make
to call your remote interface:
调用类调用远程接口的步骤:
1.Declare a
variable of
the interface type that your .aidl file defined.
- 1 . 声明一个接口类型的变量,该接口类型在.aidl文件中定义。
- 2 .Implement ServiceConnection.
- 2 . 实现 ServiceConnection。
- 3 .Call ApplicationContext.bindService(), passing in your ServiceConnection implementation.
- 3 . 调用 ApplicationContext.bindService(),并在ServiceConnection实现中进行传递.
- 4 .In your implementation of ServiceConnection.onServiceConnected(), you will receive an IBinder instance (called service).
- Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type.
- 4 . 在 ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的 Service). 调用
- YourInterfaceName.Stub.asInterface((IBinder)service) 将参数转换为YourInterface类型。
- 5 .Call the methods that you defined on your interface . You should always trap DeadObjectException exceptions, which are
- thrown when the connection has broken; this will be the only exception thrown by remote methods.
- 5 . 调用接口中定义的方法。 你总会捕捉到 DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。
- 6 .To disconnect, call ApplicationContext.unbindService() with the instance of your interface .
- 6 . 断开连接,调用接口实例中的 ApplicationContext.unbindService()
1. 声明一个接口类型的变量,该接口类型在.aidl文件中定义。 2.Implement ServiceConnection. 2. 实现ServiceConnection。 3.Call ApplicationContext.bindService(), passing in your ServiceConnection implementation. 3. 调用ApplicationContext.bindService(),并在ServiceConnection实现中进行传递. 4.In your implementation of ServiceConnection.onServiceConnected(), you will receive an IBinder instance (called service). Call YourInterfaceName.Stub.asInterface((IBinder)service) to cast the returned parameter to YourInterface type. 4. 在ServiceConnection.onServiceConnected()实现中,你会接收一个IBinder实例(被调用的Service). 调用 YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为YourInterface类型。 5.Call the methods that you defined on your interface. You should always trap DeadObjectException exceptions, which are thrown when the connection has broken; this will be the only exception thrown by remote methods. 5. 调用接口中定义的方法。 你总会捕捉到DeadObjectException异常,该异常在连接断开时被抛出。它只会被远程方法抛出。 6.To disconnect, call ApplicationContext.unbindService() with the instance of your interface. 6. 断开连接,调用接口实例中的ApplicationContext.unbindService()
A few
comments
on calling an IPC service:
调用IPC服务需要注意几点:
- .Objects are reference counted across processes.
- .You can send anonymous objects as method arguments.
- .匿名对象可以通过方法参数发送。
.Objects are reference counted across processes. .You can send anonymous objects as method arguments. .匿名对象可以通过方法参数发送。
Here is some sample code demonstrating calling an
AIDL-created
service, taken from the Remote Activity sample in the ApiDemos project.
下面的代码展示了在ApiDemos项目从远程Activity例子中调用AIDL创建Service的过程。
- public class RemoteServiceBinding extends Activity{
- IRemoteService mService = null ;
- Button mKillButton;
- private boolean mIsBound;
- @Override
- protected void onCreate(Bundle icicle) {
- super .onCreate(icicle);
- setContentView(R.layout.remote_service_binding);
- // Watch for button clicks.
- Button button = (Button)findViewById(R.id.bind);
- button.setOnClickListener(mBindListener);
- button = (Button)findViewById(R.id.unbind);
- button.setOnClickListener(mUnbindListener);
- mKillButton = (Button)findViewById(R.id.kill);
- mKillButton.setOnClickListener(mKillListener);
- mKillButton.setEnabled( false );
- }
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // This is called when the connection with the service has been
- // established, giving us the service object we can use to
- // interact with the service. We are communicating with our
- // service through an IDL interface, so get a client-side
- // representation of that from the raw service object.
- mService = IRemoteService.Stub.asInterface((IBinder)service);
- mKillButton.setEnabled( true );
- // As part of the sample, tell the user what happened.
- NotificationManager nm = (NotificationManager)
- getSystemService(NOTIFICATION_SERVICE);
- nm.notifyWithText(R.string.remote_service_connected,
- getText(R.string.remote_service_connected),
- NotificationManager.LENGTH_SHORT,
- null );
- }
- public void onServiceDisconnected(ComponentName className) {
- // This is called when the connection with the service has been
- // unexpectedly disconnected -- that is, its process crashed.
- mService = null ;
- mKillButton.setEnabled( false );
- // As part of the sample, tell the user what happened.
- NotificationManager nm = (NotificationManager)
- getSystemService(NOTIFICATION_SERVICE);
- nm.notifyWithText(R.string.remote_service_disconnected,
- getText(R.string.remote_service_disconnected),
- NotificationManager.LENGTH_SHORT,
- null );
- }
- };
- private OnClickListener mBindListener = new OnClickListener() {
- public void onClick(View v) {
- // Establish a connection with the service, by its class name.
- bindService( new Intent(RemoteServiceBinding. this ,
- RemoteService. class ),
- null , mConnection, Context.BIND_AUTO_CREATE);
- mIsBound = true ;
- }
- };
- private OnClickListener mUnbindListener = new OnClickListener() {
- public void onClick(View v) {
- if (mIsBound) {
- // Detach our existing connection.
- unbindService(mConnection);
- mKillButton.setEnabled( false );
- mIsBound = false ;
- }
- }
- };
- private OnClickListener mKillListener = new OnClickListener() {
- public void onClick(View v) {
- // To kill the process hosting our service, we need to know its
- // PID. Conveniently our service has a call that will return
- // to us that information.
- if (mService != null ) {
- int pid = - 1 ;
- try {
- pid = mService.getPid();
- } catch (DeadObjectException ex) {
- // Recover gracefully from the process hosting the
- // server dying.
- // Just for purposes of the sample, put up a notification.
- NotificationManager nm = (NotificationManager)
- getSystemService(NOTIFICATION_SERVICE);
- nm.notifyWithText(R.string.remote_call_failed,
- getText(R.string.remote_call_failed),
- NotificationManager.LENGTH_SHORT,
- null );
- }
- if (pid > 0 ) {
- // Go away!
- Process.killProcess(pid);
- }
- }
- }
- };
- }
在android中,进程通讯是通过aidl机制来完成的。aidl模型如下:
|<--------------------aidl---------------------->|
client端
-->proxy
----------parcel数据包--------
stub<---server端
也就是说:proxy+parcel+stub构成了aidl.只不过,proxy运行在客户进程,而
stub运行在服务端进程。当你通过aidl去访问服务端时,客户端会阻塞在proxy,服务端处理完后,通知proxy返回。
补充1:
应
用程序获取相关服务的代码:
private AlarmManager getAlarmManager() {
synchronized (sSync) {
if (sAlarmManager == null) {
IBinder b = ServiceManager.getService(ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
sAlarmManager = new AlarmManager(service);
}
}
return sAlarmManager;
}
补充2:
AIDL文件生成的java文件中的Stub
类。
public static abstract class Stub extends
android.os.Binder implements
android.net.softap.ISoftApManager
{
private static
final java.lang.String DESCRIPTOR = "android.net.softap.ISoftApManager";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an
ISoftApManager interface, generating a
* proxy if needed.
*/
public static
android.net.softap.ISoftApManager asInterface
(
android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface) obj
.queryLocalInterface(DESCRIPTOR);
if (((iin !=
null) && (iin instanceof android.net.softap.ISoftApManager))) {
return ((android.net.softap.ISoftApManager) iin);
}
return new
android.net.softap.ISoftApManager.Stub.Proxy(obj);
}
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_getApEnabledState: {
data.enforceInterface(DESCRIPTOR);
int _result =
this.getApEnabledState();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_setApEnabled: {
data.enforceInterface(DESCRIPTOR);
boolean
_arg0;
_arg0 = (0 != data.readInt());
boolean _result = this.setApEnabled(_arg0);
reply.writeNoException();
reply.writeInt(((_result) ?
(1) : (0)));
return true;
}
case TRANSACTION_setApSettings: {
data.enforceInterface(DESCRIPTOR);
android.net.softap.SoftApConfigure _arg0;
if ((0 !=
data.readInt())) {
_arg0 =
android.net.softap.SoftApConfigure.CREATOR
.createFromParcel(data);
} else {
_arg0 = null;
}
boolean
_result = this.setApSettings(_arg0);
reply.writeNoException();
reply.writeInt(((_result) ?
(1) : (0)));
return true;
}
case TRANSACTION_getApSettings: {
data.enforceInterface(DESCRIPTOR);
android.net.softap.SoftApConfigure _result = this
.getApSettings();
reply.writeNoException();
if ((_result != null)) {
reply.writeInt(1);
_result
.writeToParcel(
reply,
android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
reply.writeInt(0);
}
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements
android.net.softap.ISoftApManager
{
private
android.os.IBinder mRemote;
Proxy(android.os.IBinder
remote) {
mRemote = remote;
}
public android.os.IBinder asBinder() {
return mRemote;
}
public
java.lang.String getInterfaceDescriptor() {
return
DESCRIPTOR;
}
public int
getApEnabledState() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
发表评论
-
Android检查是否已经连接到网络
2012-05-14 15:40 1233http://blog.csdn.net/kerenigma/ ... -
Android Framework系列之IMF(二)
2011-06-02 10:09 2193InputConnection是IMF里面一个重要的接口,他是 ... -
Android Frameworks系列之IMF(一)
2011-06-02 10:03 1877http://www.pin5i.com/showtopic- ... -
Android线程优先级设置方法
2011-05-28 14:15 3539http://blog.sina.com.cn/s/blog_ ... -
如何连接android数据库
2011-05-27 15:18 2287http://zhidao.baidu.com/questio ... -
ensureCapacity()方法提高ArrayList的初始化速度
2011-05-27 14:33 11554http://www.gznc.edu.cn/yxsz/jjg ... -
java的isAlive 和 join
2011-05-27 13:38 1591join()用于停止当前线程而运行别的线程。 isAli ... -
Linux系统下.ko文件是什么文件?.so文件是什么文件?
2011-05-25 18:55 5552.so 文件是动态链接库文件,相当于 win下的 .dll ... -
使用Geocoder
2011-05-11 10:46 61887.6 使用Geocoder 地理编 ... -
Gallery学习总结--Cache缓存及数据处理流程
2011-05-09 14:21 2195http://hi.baidu.com/%D6%C7%B4%E ... -
关注的网站
2011-04-06 14:37 1047http://blog.sina.com.cn/s/blog_ ... -
gallery3d源码学习总结(二)
2011-04-01 10:40 3531http://www.j2megame.com/htm ... -
gallery3d源码学习总结(一)——绘制流程drawFocusItems
2011-04-01 10:14 4925eoe·Android开发者门户 标题: gallery3d ... -
Android 启动过程详解(学习1)
2011-03-31 09:27 2236Android 启动过程详解 http://blog.csd ... -
Android中的WatchDog (2)
2011-03-31 09:11 1079http://wenku.baidu.com/view/09c ... -
Android平台WindowManager运用
2011-03-30 10:00 1811Android平台WindowManager运用 我们A ... -
JPEG Rotation and EXIF Orientation
2011-03-17 14:26 3916http://blog.csdn.net/daisyhd/ar ... -
Android 的动作、广播、类别等标识大全
2011-03-11 10:19 1314Android 的动作、广播、类别等标识大全 Stri ... -
浅析Android MediaProvider之二
2011-03-08 08:27 2673http://www.poemcode.net/2010/01 ... -
Task和Activity相关
2011-02-28 09:21 1561Task和Activity相关 这段时间在做一个项目,发 ...
相关推荐
在Android系统中,AIDL(Android Interface Definition Language)是一种接口定义语言,用于处理进程间通信(IPC, Inter-Process Communication)。当一个应用需要与另一个应用的组件进行交互,特别是跨越不同进程时...
Aidl是一种接口定义语言,用于描述服务端公开的接口和方法。通过Aidl,客户端可以透明地调用服务端的方法,就像调用本地对象一样。Aidl编译后会生成Java代码,实现跨进程调用所需的代理类和服务端的Stub类。 **3. ...
首先,AIDL是一种简单的接口描述语言,它的主要作用是定义接口,使得Android系统可以自动生成对应的Java绑定类,以便于两个不同进程间的对象调用对方的方法。AIDL文件通常以`.aidl`为扩展名,其中包含了方法声明、...
使用AIDL可以定义一个接口文件(通常以.aidl为后缀),这个文件描述了远程接口的行为,包括参数类型和返回值类型。AIDL编译器会根据该文件生成相应的Java代码,使得进程间能够互相调用接口中的方法。 **2. AIDL的...
AIDL本质上是一种接口定义语言,用于描述服务提供的方法和数据类型。当一个应用需要与另一个应用的远程服务进行交互时,AIDL便发挥作用。通过编写AIDL文件,系统会自动生成相应的Java接口和Stub类,这些类帮助我们...
1. **AIDL定义**: AIDL 是一种简单的接口描述语言,类似于Java,但主要用于定义跨进程调用的方法签名。它允许你在服务中定义一套接口,其他应用可以使用这些接口来与服务进行通信。 2. **进程间通信(IPC)**: 在...
AIDL是Android系统为了实现跨进程通信而设计的一种接口定义语言。它允许开发者定义接口,使得服务端(服务运行的进程)和客户端(调用服务的进程)可以互相调用方法,即使它们位于不同的进程中。AIDL生成对应的Java...
1. **基本概念**:Aidl是一种接口定义语言,它的主要作用是在Android应用的不同进程中定义和实现接口,使得服务可以被其他进程调用,实现跨进程通信。 2. **接口定义**:在Aidl文件中,我们可以定义接口(interface...
AIDL是Android提供的一个接口定义语言,它类似于Java,但专门用于描述进程间通信的接口。通过AIDL,开发者可以定义方法签名,指定参数类型和返回值,从而创建可以在进程间传递的对象。AIDL文件会被编译成Java代码,...
本教程将详细讲解如何实现Android Service以及使用AIDL来创建远程服务。 首先,让我们深入了解Android的Service。Service是一种在后台运行的组件,即使用户没有直接与应用交互,它也能执行任务。Service可以用于...
在描述中,“该项目使用Android AIDL创建远程服务”进一步强调了AIDL在构建这样的系统中的核心作用。AIDL允许开发者定义接口,这些接口可以被不同的Android进程调用,从而实现服务与客户端之间的数据交换和服务调用...
AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于处理Android应用程序间的进程间通信(IPC, Inter-Process Communication)。通过AIDL,开发者可以定义服务(Service)与...
在Android应用开发中,AIDL(Android接口定义语言)是一种用于实现进程间通信(IPC, Inter-Process Communication)的工具。当两个Android进程需要交换数据时,通常会用到AIDL,比如服务与活动之间,或者跨应用通信...
- **Android AIDL**:如上所述,是Android系统中实现进程间通信的语言,通过编写AIDL文件,可以定义接口,使得不同进程间的对象能够互相调用方法。 - **IPC(Inter-Process Communication)**:这是操作系统中的一个...
这个2014年的最佳实践例子可能包含了如何创建、使用和优化AIDL的具体示例,对于理解AIDL的运作机制非常有帮助。随着Android的发展,虽然AIDL仍然是IPC的一种方式,但现代Android开发中更多地倾向于使用其他机制,如...
AIDL是一种简单的接口定义语言,用于描述服务端提供的接口方法。当一个应用需要与另一个应用进行交互时,可以定义一个AIDL文件,声明服务端暴露的方法。AIDL文件通常以`.aidl`为扩展名,其语法类似于Java,但更精简...
- **定义**:AIDL(Android Interface Definition Language)是Android系统提供的一个接口定义语言,用于描述进程间通信(IPC)中不同应用组件如何进行交互的规则。 - **作用**:通过AIDL,开发者可以定义接口,使得...
AIDL是Android系统提供的接口定义语言,它允许开发者定义服务接口,使得客户端和服务端能够进行数据交换。AIDL文件本质上是一个简单的文本文件,后缀为.aidl,其中包含了方法声明、参数类型和返回值等信息。当...
AIDL定义了一种接口,该接口描述了客户端和服务端之间可以交换的数据类型和方法。当客户端调用服务端的方法时,Android会自动处理跨进程调用的细节。在挂断电话的场景下,我们需要创建一个AIDL文件,声明一个服务...
在Android中,则采用AIDL(Android Interface DefinitionLanguage:接口描述语言)方式实现。 AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。...