android之Service介绍之四 如何传递复杂数据的AIDL服务

转载 2015年11月18日 14:45:05
传递复杂数据的AIDL服务


AIDL是一种接口定义语言,用于约束两个进程间的通信规则,供编译器生成代码,实现
Android 设备上的进程间通信。 
进程之间的通信信息首先会被转换成AIDL 协议消息,然后发送给对方,对方受到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文件,并输入如下代码:
1. package net.blogjava.mobile.complex.type.aidl;  
2. import net.blogjava.mobile.complex.type.aidl.Product;  
3. interface IMyService    
4. {    
5.    Map getMap(in String country, in Product product);  
6.    Product getProduct();       
7.
在编写上面代码时要注意如下两点:
Product是一个实现android.os.Parcelable接口的类,需要使用import导入这个类。
如果方法的类型是非简单类型,例如,String、List或自定义的类,需要使用in、out或inout修饰。其中in表示这个值被客户端设置;out表示这个值被服务端设置;inout表示这个值既被客户端设置,又被服务端设置。
(2)编写Product类。该类是用于传递的数据类型,代码如下:
1. package net.blogjava.mobile.complex.type.aidl;  
2.  
3. import android.os.Parcel;  
4. import android.os.Parcelable;  
5.  
6. public class Product implements Parcelable  
7. {  
8.    private int id;  
9.    private String name;  
10.    private float price;  
11.    public static final Parcelable.Creator<Product>
 CREATOR = new Parcelable.Creator<Product>()  
12.    {  
13.        public Product createFromParcel(Parcel in)  
14.        {  
15.            return new Product(in);  
16.        }  
17.  
18.        public Product[] newArray(int size)  
19.        {  
20.            return new Product[size];   
21.        }  
22.    };  
23.    public Product()  
24.    {  
25.    }  
26.    private Product(Parcel in)  
27.    {  
28.        readFromParcel(in);  
29.    }  
30.    @Override  
31.    public int describeContents()  
32.    {  
33.        return 0;  
34.    }  
35.    public void readFromParcel(Parcel in)  
36.    {  
37.        id = in.readInt();  
38.        name = in.readString();  
39.        price = in.readFloat();  
40.    }  
41.    @Override  
42.    public void writeToParcel(Parcel dest, int flags)  
43.    {  
44.        dest.writeInt(id);  
45.        dest.writeString(name);  
46.        dest.writeFloat(price);  
47.    }  
48.    //  此处省略了属性的getter和setter方法  
49.    ... ...  
50.
在编写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文件,并输入如下内容:
1. parcelable Product; 
8.4.2 建立AIDL服务的步骤(3)
8.4.2  建立AIDL服务的步骤(3)
(4)编写一个MyService类,代码如下:
1. package net.blogjava.mobile.complex.type.aidl;  
2.  
3. import java.util.HashMap;  
4. import java.util.Map;  
5. import android.app.Service;  
6. import android.content.Intent;  
7. import android.os.IBinder;  
8. import android.os.RemoteException;  
9. //  AIDL服务类  
10. public class MyService extends Service  
11. {   
12.    public class MyServiceImpl extends IMyService.Stub  
13.    {  
14.        @Override  
15.        public Product getProduct() throws RemoteException  
16.        {  
17.            Product product = new Product();  
18.            product.setId(1234);  
19.            product.setName("汽车");  
20.            product.setPrice(31000);   
21.            return product;  
22.        }  
23.        @Override  
24.        public Map getMap(String country, Product
product) throws RemoteException  
25.        {  
26.            Map map = new HashMap<String, String>();  
27.            map.put("country", country);  
28.            map.put("id", product.getId());  
29.            map.put("name", product.getName());  
30.            map.put("price", product.getPrice());  
31.            map.put("product", product);  
32.            return map;  
33.        }  
34.    }  
35.    @Override  
36.    public IBinder onBind(Intent intent)  
37.    {          
38.        return new MyServiceImpl();  
39.    }  
40.
(5)在AndroidManifest.xml文件中配置MyService类,代码如下:
1. <service android:name=".MyService" > 
2.    <intent-filter>   
3.        <action android:name="net.blogjava.
mobile.complex.type.aidl.IMyService" /> 
4.    </intent-filter> 
5. </service> 
在客户端调用AIDL服务的方法与实例52介绍的方法相同,首先将IMyService.java和Product.java文件复制到客户端工程(ch08_complextypeaidlclient),然后绑定AIDL服务,并获得AIDL服务对象,最后调用AIDL服务中的方法。完整的客户端代码如下:
1. package net.blogjava.mobile;  
2.  
3. import net.blogjava.mobile.complex.type.aidl.IMyService;  
4. import android.app.Activity;  
5. import android.content.ComponentName;  
6. import android.content.Context;  
7. import android.content.Intent;  
8. import android.content.ServiceConnection;  
9. import android.os.Bundle;  
10. import android.os.IBinder;  
11. import android.view.View;  
12. import android.view.View.OnClickListener;  
13. import android.widget.Button;  
14. import android.widget.TextView;  
15.  
16. public class Main extends Activity implements OnClickListener  
17. {  
18.    private IMyService myService = null;  
19.    private Button btnInvokeAIDLService;  
20.    private Button btnBindAIDLService;  
21.    private TextView textView;  
22.    private ServiceConnection serviceConnection = new ServiceConnection()  
23.    {  
24.        @Override  
25.        public void onServiceConnected(ComponentName name, IBinder service)  
26.        {  
27.              //  获得AIDL服务对象  
28.            myService = IMyService.Stub.asInterface(service);  
29.            btnInvokeAIDLService.setEnabled(true);  
30.        }  
31.        @Override  
32.        public void onServiceDisconnected(ComponentName name)  
33.        {  
34.        }  
35.    };  
36.    @Override  
37.    public void onClick(View view)  
38.    {  
39.        switch (view.getId())  
40.        {  
41.            case R.id.btnBindAIDLService:  
42.                   //  绑定AIDL服务  
43.                bindService(new Intent("net.blogjava.
mobile.complex.type.aidl.IMyService"),  
44.                        serviceConnection, Context.BIND_AUTO_CREATE);  
45.                break;  
46.            case R.id.btnInvokeAIDLService:  
47.                try  
48.                {  
49.                    String s = "";  
50.                       //  调用AIDL服务中的方法  
51.                    s = "Product.id = " + myService.
getProduct().getId() + "\n";  
52.                    s += "Product.name = " + myService.
getProduct().getName() + "\n";  
53.                    s += "Product.price = " + myService.
getProduct().getPrice() + "\n";              
54.                    s += myService.getMap("China", 
myService.getProduct()).toString();  
55.                    textView.setText(s);  
56.                }  
57.                catch (Exception e)  
58.                {  
59.                }  
60.                break;  
61.        }  
62.    }  
63.    @Override  
64.    public void onCreate(Bundle savedInstanceState)  
65.    {  
66.        super.onCreate(savedInstanceState);  
67.        setContentView(R.layout.main);  
68.        btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService);  
69.        btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService);  
70.        btnInvokeAIDLService.setEnabled(false);  
71.        textView = (TextView) findViewById(R.id.textview);  
72.        btnInvokeAIDLService.setOnClickListener(this);  
73.        btnBindAIDLService.setOnClickListener(this);  
74.    }  
75.

Android AIDL Service 跨进程传递复杂数据

服务交互的方式有很多,广播、文件、接口都可以;但是假如服务处于独立进程中,并要求效率呢? 此时AIDL可以为你解决,但是AIDL中,默认传递的类型不多(String,Char,Int,Long,Boo...
  • qiujuer
  • qiujuer
  • 2015年07月15日 13:48
  • 3430

AIDL的复杂参数的传递和完整使用过程(AndroidStudio)

昨天开始认真研究了一下AIDL,使用AIDL绑定远程服务并且传递复杂自定义的参数,在使用过程中碰到了一些问题,网上的技术贴有很多不全面的,另外有些细节部分根本不会提到,然后就查找了很多技术贴,自己动手...
  • AXCMIKE
  • AXCMIKE
  • 2016年08月14日 21:34
  • 857

AIDL进程间传递复杂数据类型—AIDL传递其他AIDL接口

AIDL进程间传递复杂数据类型系列: AIDL进程间传递复杂数据类型—AIDL传递其他AIDL接口AIDL进程间传递复杂数据类型—AIDL传递android.os.Parcelable接口=====...
  • hp910315
  • hp910315
  • 2015年08月15日 14:32
  • 1422

Android:远程服务Service(含AIDL & IPC讲解)

前言 Service作为Android四大组件之一,应用非常广泛 本文将介绍Service其中一种常见用法:远程Service 如果你对Service还未了解,建议先阅读我写的另外一篇文章: ...
  • carson_ho
  • carson_ho
  • 2016年11月14日 16:25
  • 2987

关于Android中的四大组件(AIDL Service的使用)

跨进程调用Service(AIDL Service) Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。 在前一篇文章(关于Android中的四大组...
  • GULINHAI12
  • GULINHAI12
  • 2015年08月18日 17:59
  • 3056

Android Studio下使用AIDL创建和使用远程service

好久没来更新博客了,今天心血来潮来写一篇关于如何在AS下结合AIDL创建和使用远程service。在此之前我先跟大家解释下什么是远程service?以及为什么要使用远程service?相信不管对于安卓...
  • u010214991
  • u010214991
  • 2016年07月05日 18:34
  • 1553

AndroidStudio通过AIDL开启、绑定远程Service

本文以一个简单的案例,记录一下怎么使用AIDL结合Serice实现进程间的通信,让其他程序可以调用服务中的方法...
  • man_help
  • man_help
  • 2016年04月17日 15:25
  • 3443

AIDL(2):通过传输复杂对象

IPC通过AIDL传递复杂对象 1.定义数据传输对象 Person.aidl文件: Person.java文件中: (1)实现parcelable接口 (2)提供一个...
  • u010739551
  • u010739551
  • 2014年08月04日 01:07
  • 1281

android 学习笔记9-服务 启动停止 调用服务方法 远程服务 AIDL进程通信

1、服务的概念 2、5个进程优先级 3、服务的启动与停止 4、服务的案例-电话侦听 5、服务两种启动方式 6、调用服务中的方法-通过Binder实现 7、服务中中间人方法抽取到接口,MyBinder类...
  • gaopinqiang
  • gaopinqiang
  • 2017年01月08日 23:56
  • 534

传递复杂数据的AIDL服务

1.AIDL服务只支持有限的数据类型,因此要用AIDL服务传递一些复杂的数据就需要做更进一步的处理。AIDL服务支持的数据类型如下: 1)Java的简单类型(int、char、boolean等),不...
  • panda1234lee
  • panda1234lee
  • 2013年04月10日 16:24
  • 676
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android之Service介绍之四 如何传递复杂数据的AIDL服务
举报原因:
原因补充:

(最多只允许输入30个字)