android aidl 自定义类型 作参数

遇到的问题是使用数组作为参数和返回值。

找了半天资料, 没有介绍。

最后看了别人的一个程序代码, 原来如此。

问题,实现玩parcelable之后, 还需要在AUDIO_TAG中添加一个类名称的定义才行。

1. 代码结构:

注意选中部分,和内容:

 

2. 主要的AIDL文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.shougao.Audio.media;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import com.shougao.Audio.DataBase.AUDIO_TAG;
import android.os.Parcelable;
//import android.os.Parcelable.Creator;
 
interface IMediaService{
AUDIO_TAG[] getAudio();
int getCurrentOrderIndex();
AUDIO_TAG[] getCurrentPlayAudio();
int getCurrentPlayIndex();
int getDruation();
int getMediaTime();
AUDIO_TAG[] getPlayList();
void play();
void stop();
void pause();
void prev();
void next();
int getPlayState();
int getRepeatMode();
int getShuffleMode();
int getTotalPlayNum();
int setRepeatMode();
void setCurrentPlayIndex();
void setShuffleMode( int paramInt);
void setMediaTime( int paramInt);
AUDIO_TAG[] setPlayList();
//void updatePlayList(AUDIO_TAG);
}
整个原理:

1. 要在ImediaService中使用数组类型, 就需要先定义AUDIO_TAG类,并实现pracelable接口和create。

2. 然后在定义一个AUDIO_TAG.aidl.

到此返回值定义完毕。

 

遗留问题:

可能你已经发现最后一行被注释。

原因是,数组作为参数传递还不行,如果你知道如何做请指教。谢谢了。

 

非标准答案:

需要特别注意的是,  对于非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。

    AIDL只支持接口方法,不能公开static变量。


?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.shougao.Audio.media;
 
import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
import android.os.RemoteException;
import com.shougao.Audio.DataBase.AUDIO_TAG;
import com.shougao.Audio.DataBase.AUDIO_TAG_1;
import android.os.Parcelable;
 
interface IMediaService{
AUDIO_TAG[] getAudio();
int getCurrentOrderIndex();
AUDIO_TAG[] getCurrentPlayAudio();
int getCurrentPlayIndex();
int getDruation();
int getMediaTime();
AUDIO_TAG[] getPlayList();
void play();
void stop();
void pause();
void prev();
void next();
int getPlayState();
int getRepeatMode();
int getShuffleMode();
int getTotalPlayNum();
int setRepeatMode();
void setCurrentPlayIndex();
void setShuffleMode( int paramInt);
void setMediaTime( int paramInt);
AUDIO_TAG[] setPlayList();
void setStopTimer( long paramInt)
void updatePlayList(out AUDIO_TAG[] paramInt);
}

 

 

**** AIDL经典教程:


定义AIDL接口
    AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。保存在src目录下。  如果其他应用程序需要IPC,则那些应用程序的src也要带有这个文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。service必须适当地实现这个IBinder接口。那么客户端程序就能绑定这个service并在IPC时从IBinder调用方法。
    每个aidl文件只能定义一个接口,而且只能是接口的声明和方法的声明。
 
1.创建.aidl文件 
     AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。
    其中对于Java编程语言的基本数据类型 (int, long, char, boolean等),String和CharSequence,集合接口类型List和Map,不需要import 语句。
    而如果需要在AIDL中使用其他AIDL接口类型,需要import,即使是在相同包结构下。AIDL允许传递实现Parcelable接口的类,需要import. 
    需要特别注意的是,  对于非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。
    AIDL只支持接口方法,不能公开static变量。 
 
例如 (IMyService.aidl): 
package com.demo;  

import com.demo.Person;  

interface IMyService {  
          void savePersonInfo(in Person person);  
        List<Person> getAllPerson();  
}

2.实现接口
    创建一个类实现刚才那个aidl的接口:
public   class RemoteService   extends Service {  

          private LinkedList<Person> personList =   new LinkedList<Person>();  
          
        @Override  
          public IBinder onBind(Intent intent) {  
                  return mBinder;  
        }  

        private final IMyService.Stub mBinder = new IMyService.Stub(){  

                @Override  
                  public   void savePersonInfo(Person person)   throws RemoteException {  
                          if (person !=   null){  
                                personList.add(person);  
                        }  
                }  

                @Override  
                  public List<Person> getAllPerson()   throws RemoteException {  
                          return personList;  
                }  
        };  
}
 
    这里会看到有一个名为IMyService.Stub类,查看aidl文件生成的Java文件源代码就能发现有这么一段代码:
/** Local-side IPC implementation stub class. */  
public   static   abstract   class Stub   extends android.os.Binder   implements com.demo.IMyService
    原来Stub类就是继承于Binder类,也就是说RemoteService类和普通的Service类没什么不同,只是所返回的IBinder对象比较特别,是一个实现了AIDL接口的Binder。
 
    接下来就是关于所传递的数据Bean——Person类,是一个序列化的类,这里使用Parcelable 接口来序列化,是Android提供的一个比Serializable 效率更高的序列化类。
    Parcelable需要实现三个函数: 
    1)   void writeToParcel(Parcel dest, int flags) 将需要序列化存储的数据写入外部提供的Parcel对象dest。而看了网上的代码例子,个人猜测,读取Parcel数据的次序要和这里的write次序一致,否则可能会读错数据。具体情况我没试验过! 
    2)   describeContents() 没搞懂有什么用,反正直接返回0也可以 
    3)   static final Parcelable.Creator对象CREATOR  这个CREATOR命名是固定的,而它对应的接口有两个方法: 
    createFromParcel(Parcel source) 实现从source创建出JavaBean实例的功能 

    newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话(return new T[size])即可。估计本方法是供外部类反序列化本类数组使用。 
  
仔细观察Person类的代码和上面所说的内容:
public   class Person   implements Parcelable {  

          private String name;  
          private String telNumber;  
          private   int age;  

          public Person() {}  

        public Person(Parcel pl){ 
                name = pl.readString(); 
                telNumber = pl.readString(); 
                age = pl.readInt(); 
        } 

          public String getName() {  
                  return name;  
        }  

          public   void setName(String name) {  
                  this.name = name;  
        }  

          public String getTelNumber() {  
                  return telNumber;  
        }  

          public   void setTelNumber(String telNumber) {  
                  this.telNumber = telNumber;  
        }  

          public   int getAge() {  
                  return age;  
        }  

          public   void setAge(  int age) {  
                  this.age = age;  
        }  

        @Override 
        public int describeContents() { 
                return 0; 
        } 

        @Override 
        public void writeToParcel(Parcel dest, int flags) { 
                dest.writeString(name); 
                dest.writeString(telNumber); 
                dest.writeInt(age); 
        } 

        public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {  

                @Override  
                  public Person createFromParcel(Parcel source) {  
                          return new Person(source); 
                }  

                @Override  
                  public Person[] newArray(  int size) {  
                          return new Person[size]; 
                }  

        };  
}

然后创建Person.aidl文件,注意这里的parcelable和原来实现的Parcelable 接口,开头的字母p一个小写一个大写:
package com.demo;  

parcelable Person;
 
     对于实现AIDL接口,官方还提醒我们:
    1. 调用者是不能保证在主线程执行的,所以从一调用的开始就需要考虑多线程处理,以及确保线程安全;
    2. IPC调用是同步的。如果你知道一个IPC服务需要超过几毫秒的时间才能完成地话,你应该避免在Activity的主线程中调用。也就是IPC调用会挂起应用程序导致界面失去响应,这种情况应该考虑单独开启一个线程来处理。 
    3. 抛出的异常是不能返回给调用者(跨进程抛异常处理是不可取的)

 

转自:http://my.oschina.net/zhangqingcai/blog/29080

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值