8.4.2 建立AIDL服务的步骤(2)
在编写上面代码时应注意如下两点:
使用bindService方法来绑定AIDL服务。其中需要使用Intent对象指定AIDL服务的ID,也就是<action>标签中android:name属性的值。
在绑定时需要一个ServiceConnection对象。创建ServiceConnection对象的过程中如果绑定成功,系统会调用onServiceConnected方法,通过该方法的service参数值可获得AIDL服务对象。
首先运行AIDL服务程序,然后运行客户端程序,单击【绑定AIDL服务】按钮,如果绑定成功,【调用AIDL服务】按钮会变为可选状态,单击这个按钮,会输出getValue方法的返回值,如图8.26所示。
实例53:传递复杂数据的AIDL服务
AIDL服务工程目录:src\ch08\ch08_complextypeaidl
客户端程序工程目录:src\ch08\ch08_complextypeaidlclient
AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要做更一步处理。AIDL服务支持的数据类型如下:
Java的简单类型(int、char、boolean等)。不需要导入(import)。
String和CharSequence。不需要导入(import)。
List和Map。但要注意,List和Map对象的元素类型必须是AIDL服务支持的数据类型。不需要导入(import)。
AIDL自动生成的接口。需要导入(import)。
实现android.os.Parcelable接口的类。需要导入(import)。
其中后两种数据类型需要使用import进行导入,将在本章的后面详细介绍。
传递不需要import的数据类型的值的方式相同。传递一个需要import的数据类型的值(例如,实现android.os.Parcelable接口的类)的步骤略显复杂。除了要建立一个实现android.os.Parcelable接口的类外,还需要为这个类单独建立一个aidl文件,并使用parcelable关键字进行定义。具体的实现步骤如下:
(1)建立一个IMyService.aidl文件,并输入如下代码:
package net.blogjava.mobile.complex.type.aidl;
import net.blogjava.mobile.complex.type.aidl.Product;
interface IMyService
{
Map getMap(in String country, in Product product);
Product getProduct();
}
在编写上面代码时要注意如下两点:
Product是一个实现android.os.Parcelable接口的类,需要使用import导入这个类。
如果方法的类型是非简单类型,例如,String、List或自定义的类,需要使用in、out或inout修饰。其中in表示这个值被客户端设置;out表示这个值被服务端设置;inout表示这个值既被客户端设置,又被服务端设置。
(2)编写Product类。该类是用于传递的数据类型,代码如下:
package net.blogjava.mobile.complex.type.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Product implements Parcelable
{
private int id;
private String name;
private float price;
public static final Parcelable.Creator<Product>
CREATOR = new Parcelable.Creator<Product>()
{
public Product createFromParcel(Parcel in)
{
return new Product(in);
}
public Product[] newArray(int size)
{
return new Product[size];
}
};
public Product()
{
}
private Product(Parcel in)
{
readFromParcel(in);
}
@Override
public int describeContents()
{
return 0;
}
public void readFromParcel(Parcel in)
{
id = in.readInt();
name = in.readString();
price = in.readFloat();
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeInt(id);
dest.writeString(name);
dest.writeFloat(price);
}
// 此处省略了属性的getter和setter方法
... ...
}
在编写Product类时应注意如下3点:
Product类必须实现android.os.Parcelable接口。该接口用于序列化对象。在Android中之所以使用Pacelable接口序列化,而不是java.io.Serializable接口,是因为Google在开发Android时发现Serializable序列化的效率并不高,因此,特意提供了一个Parcelable接口来序列化对象。
在Product类中必须有一个静态常量,常量名必须是CREATOR,而且CREATOR常量的数据类型必须是Parcelable.Creator。
在writeToParcel方法中需要将要序列化的值写入Parcel对象。
(3)建立一个Product.aidl文件,并输入如下内容:
parcelable Product;
(4)编写一个MyService类,代码如下:
package net.blogjava.mobile.complex.type.aidl;
import java.util.HashMap;
import java.util.Map;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
// AIDL服务类
public class MyService extends Service
{
public class MyServiceImpl extends IMyService.Stub
{
@Override
public Product getProduct() throws RemoteException
{
Product product = new Product();
product.setId(1234);
product.setName("汽车");
product.setPrice(31000);
return product;
}
@Override
public Map getMap(String country, Product
product) throws RemoteException
{
Map map = new HashMap<String, String>();
map.put("country", country);
map.put("id", product.getId());
map.put("name", product.getName());
map.put("price", product.getPrice());
map.put("product", product);
return map;
}
}
@Override
public IBinder onBind(Intent intent)
{
return new MyServiceImpl();
}
}
(5)在AndroidManifest.xml文件中配置MyService类,代码如下:
<service android:name=".MyService" >
<intent-filter>
<action android:name="net.blogjava.
mobile.complex.type.aidl.IMyService" />
</intent-filter>
</service>
在客户端调用AIDL服务的方法与实例52介绍的方法相同,首先将IMyService.java和Product.java文件复制到客户端工程(ch08_complextypeaidlclient),然后绑定AIDL服务,并获得AIDL服务对象,最后调用AIDL服务中的方法。完整的客户端代码如下:
package net.blogjava.mobile;
import net.blogjava.mobile.complex.type.aidl.IMyService;
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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Main extends Activity implements OnClickListener
{
private IMyService myService = null;
private Button btnInvokeAIDLService;
private Button btnBindAIDLService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
// 获得AIDL服务对象
myService = IMyService.Stub.asInterface(service);
btnInvokeAIDLService.setEnabled(true);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
}
};
@Override
public void onClick(View view)
{
switch (view.getId())
{
case R.id.btnBindAIDLService:
// 绑定AIDL服务
bindService(new Intent("net.blogjava.
mobile.complex.type.aidl.IMyService"),
serviceConnection, Context.BIND_AUTO_CREATE);
break;
case R.id.btnInvokeAIDLService:
try
{
String s = "";
// 调用AIDL服务中的方法
s = "Product.id = " + myService.
getProduct().getId() + "\n";
s += "Product.name = " + myService.
getProduct().getName() + "\n";
s += "Product.price = " + myService.
getProduct().getPrice() + "\n";
s += myService.getMap("China",
myService.getProduct()).toString();
textView.setText(s);
}
catch (Exception e)
{
}
break;
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService);
btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService);
btnInvokeAIDLService.setEnabled(false);
textView = (TextView) findViewById(R.id.textview);
btnInvokeAIDLService.setOnClickListener(this);
btnBindAIDLService.setOnClickListener(this);
}
}
首先运行服务端程序,然后运行客户端程序,单击【绑定AIDL服务】按钮,待成功绑定后,单击【调用AIDL服务】按钮,会输出如图8.27所示的内容。
分享到:
相关推荐
在深入探讨“AIDL服务使用”这一主题之前,我们先来...开发者需要掌握AIDL接口定义、服务端实现以及客户端绑定的具体步骤,才能顺利实现服务的跨进程调用。此外,还需要注意处理好异常情况,确保服务稳定可靠地运行。
8.1 Service起步 8.1.1 Service的生命周期 8.1.2 绑定Activity和Service 8.1.3 在BroadcastReceiver中启动Ser.. 8.2.1 获得系统服务+ ... 8.4.2 建立AIDL服务的步骤(2) 8.4.2 建立AIDL服务的步骤
3. **连接服务**:在客户端应用中,通过`IBinder`对象获取服务的引用,并使用`bindService()`方法建立连接。 4. **执行测试**:使用生成的客户端接口调用HAL服务的方法,执行测试用例。 5. **断开连接**:测试完成后...
- 绑定服务:客户端通过Binder机制与服务建立连接,获取到Stub的代理对象。 - 跨进程调用:客户端调用Stub对象的方法,实际调用会被封装成Parcel数据并发送到服务端,服务端接收到Parcel后,反序列化执行相应方法,...
通过以上步骤,我们可以构建一个基于AIDL的双向绑定服务,利用Kotlin的简洁性和强大功能,提升代码可读性和维护性。双向绑定的实现不仅需要对AIDL有深入理解,还需要掌握Android服务的生命周期管理以及进程间通信的...
在Android应用开发中,当需要一个服务(Service)为其他应用程序组件提供服务时,AIDL就起到了关键作用。本文将详细阐述AIDL在bindService过程中的工作原理,并结合提供的"流程图.png"来解析整个通信流程。** 首先...
4. **在客户端调用服务**:在需要调用服务的Activity或BroadcastReceiver中,使用`bindService()`方法建立连接。首先创建一个`Intent`,指定要绑定的服务,然后创建一个`ServiceConnection`,在`onServiceConnected...
在客户端,我们需要做以下步骤来使用AIDL服务: 1. 创建并注册服务:在服务端,你需要创建一个实现AIDL接口的类,并在AndroidManifest.xml中注册服务。 2. 绑定服务:在客户端,通过`bindService()`方法绑定到服务...
2. **建立连接**:客户端通过`bindService()`方法连接到服务端,传入一个`Intent`来指定要绑定的服务和一个`ServiceConnection`,在连接成功时回调`onServiceConnected()`。 3. **获取AIDL接口代理对象**:在`...
4. 绑定服务:客户端通过`bindService()`方法与服务建立连接,并传入实现了AIDL接口的Binder对象。 5. 调用方法:连接建立后,客户端就可以通过返回的IBinder对象调用服务中的方法。 示例: ```aidl interface ...
4. 实现客户端:在客户端(应用或其他系统组件)中,导入由AIDL生成的Java接口,通过IBinder接口与服务端建立连接并调用服务端方法。 总结起来,AIDL在Android System Service架构中扮演着桥梁的角色,它使得系统...
以下是使用AIDL完成IPC的步骤: 1. **创建AIDL文件** 在Android Studio的项目目录下,新建一个.aidl文件,例如`IAidlInterface.aidl`。在该文件中,你可以声明服务提供的接口,包括方法名、参数类型和返回值。例如...
当连接建立后,可以获取到服务提供的Binder对象,通过这个Binder对象调用AIDL接口定义的方法。 5. **处理回调**: 客户端需要实现接口中的回调方法,以便接收服务端的响应。 ### 三、注意事项 1. **数据类型限制**...
2. 获取服务:客户端可以通过`startService`或`bindService`与服务建立连接。`bindService`通常用于需要长时间交互的情况。 3. 调用服务方法:使用`ServiceConnection`回调中的`onServiceConnected`方法获取到`...
5. **连接管理**:在调用服务之前,需要建立一个`ServiceConnection`来处理服务的连接和断开。当不再需要服务时,确保正确地解绑以避免内存泄漏。 通过以上步骤,你可以在Xamarin应用中有效地使用AIDL进行进程间...
在Activity中,可以通过startService()或bindService()方法与服务建立连接,然后通过返回的IBinder接口调用服务端的方法。 **实现步骤:** 1. **创建AIDL文件**:在项目的res/aidl目录下创建.AIDL文件,定义接口。 ...
- 客户端代码,展示了如何启动服务,建立连接,以及如何通过AIDL接口调用服务端的方法。 - 可能还有测试类或者示例Activity,用来验证AIDL的通信效果。 通过这个实例,你可以学习到如何设置AIDL服务,如何处理跨...
在Android开发中,AIDL(Android Interface Definition Language)是一种用于实现跨进程通信(IPC, ...通过分析和实践这个Demo,开发者将能够熟练运用AIDL进行服务的暴露和调用,进一步提升自己的Android开发技能。
2. **服务(Service)**:Android服务是后台运行的组件,不与用户界面直接交互。`PlayService.java`就是这样的一个服务,负责处理MP3的播放逻辑。它需要实现AIDL中定义的接口,并通过`Binder`机制暴露给其他进程调用...
2. 在接口定义中,可以声明基本数据类型、List、Map以及其他的AIDL接口作为参数或返回值。 3. 编译后,Android编译系统会自动生成对应的Java代码,这个生成的类包含了一个Binder对象,可以跨进程传递。 在Service端...