parcelable

来源:互联网 发布:java asm demo 编辑:程序博客网 时间:2024/04/27 21:02

AIDL服务: 跨进程访问的服务
实现步骤:
1.新建一个IMyService.aidl文件,写入内容

123456789
package com.dhy.testaidl.server.aidl;    interface IMyService{        String getValue();   // 传递基本类型        Map getMap(in String country, in Product product);    //传递自定义对象        Product getProduct();}

1.2 接口中包含自定义对象,另外还需要建2个文件: 一个实现Parcelable接口的Product类, 一个单独的Product.aidl,并用关键字parcelable修饰

123
1.2.1 新建Product.aidl文件,写入内容  ```Java

parcelable Product; //这个parcelable关键字声明,类似public

为什么要用Parcelable类,因为要跨进程访问,跨进程访问不能向同一进程访问一样,直接传递位置,必须流化再传递。

参照 

http://developer.android.com/guide/components/aidl.html

Passing Objects over IPC


If you have a class that you would like to send from one process to another through an IPC interface, you can do that. However, you must ensure that the code for your class is available to the other side of the IPC channel and your class must support the Parcelable interface. Supporting the Parcelable interface is important because it allows the Android system to decompose objects into primitives that can be marshalled across processes.

To create a class that supports the Parcelable protocol, you must do the following:

  1. Make your class implement the Parcelable interface.
  2. Implement writeToParcel, which takes the current state of the object and writes it to a Parcel.
  3. Add a static field called CREATOR to your class which is an object implementing the Parcelable.Creatorinterface.
  4. Finally, create an .aidl file that declares your parcelable class (as shown for the Rect.aidl file, below).

    If you are using a custom build process, do not add the .aidl file to your build. Similar to a header file in the C language, this .aidl file isn't compiled.

AIDL uses these methods and fields in the code it generates to marshall and unmarshall your objects.

For example, here is a Rect.aidl file to create a Rect class that's parcelable:

package android.graphics;// Declare Rect so AIDL can find it and knows that it implements// the parcelable protocol.parcelable Rect;


 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
    1.2.2 新建实现Parcelable接口的Product类        之前对Parcel对象也没什么了解,于是借助了几篇文章,了解了下什么是Parcel对象        参考文章:  为什么要使用Parcel         http://blog.csdn.net/nkmnkm/article/details/6451699                         如何实现Parcelable接口         http://892848153.iteye.com/blog/1603743        关键就是: writeToParcel()                    自定义的对象 ----序列化----  Parcel对象                         CREATOR中实现createFromParcelable()               Parcel对象 ------反序列化----- 自定义的对象2.编译成功时,会生成一个IMyService.java(gen目录下),包含一个提供客户端访问的接口Stub3.编写一个继承Service的类,实现上述接口  ,注意,这里实现的类MyService 和 aidl要放在同一个包下,否则IMyService.Stub访问不到```Javapublic class MyService extends Service{    public class MyServiceImpl implements IMyService.Stub{        //实现接口中定义的方法        public String getValue(){            return "I'm from AIDL";        }        public Map getMap(String country, Product product){            Map map = new Map();            map.put("id", product.getId());            map.put("name", product.getName());            return map;        }        public Product getProduct(){            Product product = new Product();            product.setId(1);            product.setName("product from AIDL");            return product;        }    }    @override    public IBinder onBind(Intent intent){        return new MyServiceImpl(); //返回一个实现的类的实例,用于获取IMyService对象    }}

4.manifest中注册服务,并定义action

 1 2 3 4 5 6 7 8 910
<service android:name = ".MyService">    <intent-filter>        <!-- 这个action就是客户端中声明Intent的参数 -->        <action android:name = "com.dhy.testaidl.server.aidl.IMyService" />     </intent-filter></service>

5.新建一个Android Project,做客户端用
把服务器中自动生成的IMyService.java所在的包整个复制到客户端src中
另外Product.java也要拷贝过去

6.客户端中,声明ServiceConnection,获取IMyService对象

 1 2 3 4 5 6 7 8 9101112
private ServiceConnection conn = new ServiceConnection(){    public void onServiceDisconnected(ComponentName name){    }    public void onServiceConnected(ComponentName name, IBinder service){        myService = IMyService.Stub.asInterface(service);    }}

7.客户端绑定服务器的服务

1
bindService(new Inten("com.dhy.testaidl.server.aidl.IMyService"), conn, Context.BIND_AUTO_CREATE);

8.调用

12
myService.getValue();myService.getMap("China", myService.getProduct());

总结: 我犯的纠结的错误:
错误: 同一个进程中可以访问,但是跨进程访问时,找不到service
原因:
1 应用与应用之间包名不能相同(可以加上项目名称,用以区分不同项目)
如 com.dhy.testaidl.server.ui
com.dhy.testaidl.client.ui
(拷贝过去的不用管)

2 运行客户端之前要运行服务器,这个居然搞错,我也不懂我怎么想的了

0 0