关闭

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

标签: AndroidAIDL跨进程传递对象进程间通讯
58人阅读 评论(0) 收藏 举报
分类:
传递复杂数据的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.
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:76767次
    • 积分:1144
    • 等级:
    • 排名:千里之外
    • 原创:12篇
    • 转载:162篇
    • 译文:1篇
    • 评论:7条
    文章分类
    最新评论