为了账号安全,请及时绑定邮箱和手机立即绑定

远程接口调用AIDL

标签:
Android

AIDL概述

AIDL全称是“Android Interface Definition Language”,即Android的接口定义语言。AIDL用来协助开发者来处理进程间通信,我们知道可以使用Messenger完成进程间通信。但是Messenger每次调用都只能传递一个消息包,不能很好的完成一些复杂的调用,比如说我们想像API调用那样通过不同的方法来实现不同的动作,这时Messenger就难以实现了。所以Android引入了AIDL服务来完成这种RPC调用。
下面是在项目工程中运用AIDL的具体方法和步骤。

AIDL定义修改

普通方法

通过菜单“File”——“New”创建扩展名为aidl的文件,文件内容与interface接口格式类似(区别在于要在输入参数前面加上in关键字)。文件定义完成并且没有错误,则ADT会自动在gen目录下生成该aidl文件对应的java文件。下面是一个AIDL接口定义文件的例子:

[代码]java代码:

?

1

2

3

interface IUserService { 

    double multiply(in double a1, in double a2); 

}



方法中传递了自定义数据结构

如果想在aidl方法中使用自定义数据结构,则需加上如下步骤:
1、把自定义数据结构的代码(如User.java)挪到aidl包下面,这个数据结构必须实现Parcelable接口;
2、在aidl包下新建一个User.aidl文件,文件内容为“parcelable User;”;很简单,告诉aidl,我这里有个叫做User的parcelable对象;
3、在aidl接口定义中添加新的方法,并使用import导入User的完整路径。即使User.java就在aidl目录下,那也得import,不然ADT不认这个对象;下面是补充后的文件定义例子:

[代码]java代码:

?

1

2

3

4

5

6

import com.example.exmprocess.aidl.data.User; 

   

interface IUserService { 

    double multiply(in double a1, in double a2); 

    int save(in List<user> userList);   

}  </user>



项目代码修改

客户端代码修改

1、定义一个ServiceConnection对象,在onServiceConnected方法中获取对方服务的实例。代码例子如下:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

10

11

private IUserService mService; 

private ServiceConnection mAidlConn = new ServiceConnection() { 

    public void onServiceConnected(ComponentName name, IBinder binder) { 

        mService   = IUserService.Stub.asInterface(binder); 

    } 

   

   

    public void onServiceDisconnected(ComponentName name) { 

        mService   = null; 

    } 

};

2、远程服务当然只能通过bindService方法启动,不能通过startService方法启动。同时Intent对象也只能通过setAction来指定对方服务的动作,而不能直接指定对方服务的class;

3、绑定服务后,再调用aidl服务端,即可使用mService来调用相应的方法;

服务端代码修改

重写的Binder类要改为继承自Stub(原来继承自Binder),即ADT根据aidl文件定义自动生成的Stub类,查看自动生成的java源码,其实Stub类就是从Binder类派生出来的。

另外,服务端的Binder类需要实现aidl中定义的方法。



需要注意的地方

1、intent-filter节点中的“android:name”必须填入原始名称,不可用“@string/aaa”这种定义来代替。
2、Android5.0之后不能再隐式启动Service,只能显式启动Service,所以需要判断当前SDK版本从而做分支处理。
3、aidl定义文件需要同时加入到客户端项目代码与服务端项目代码中,并且aidl文件所在的包路径也要保持一致。




使用示例

下面是AIDL服务调用的效果图:
 


下面是AIDL客户端的示例代码:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

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

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

import java.util.ArrayList; 

import java.util.List; 

   

import android.app.Activity; 

import android.content.ComponentName; 

import android.content.Context; 

import android.content.Intent; 

import android.content.ServiceConnection; 

import android.os.Build; 

import android.os.Bundle; 

import android.os.IBinder; 

import android.os.RemoteException; 

import android.util.Log; 

import android.view.View; 

import android.view.View.OnClickListener; 

import android.widget.Button; 

import android.widget.TextView; 

import android.widget.Toast; 

   

import com.example.exmprocess.R; 

import com.example.exmprocess.aidl.data.IUserService; 

import com.example.exmprocess.aidl.data.User; 

import com.example.exmprocess.util.IntentUtil; 

   

public class AidlActivity   extends Activity   implements OnClickListener   { 

   

    private static final String   TAG = "AidlActivity"; 

    private String AIDL_SERVICE = "com.example.exmprocess.aidl.action.AIDL_ADD";   

    private TextView tv_aidl; 

   

    @Override 

    protected void onCreate(Bundle savedInstanceState) { 

        super.onCreate(savedInstanceState);   

        setContentView(R.layout.activity_aidl);   

   

        tv_aidl   = (TextView) findViewById(R.id.tv_aidl); 

        Button   btn_aidl_bind = (Button) findViewById(R.id.btn_aidl_bind); 

        Button   btn_aidl_unbind = (Button) findViewById(R.id.btn_aidl_unbind); 

        Button   btn_aidl_send = (Button) findViewById(R.id.btn_aidl_send); 

        btn_aidl_bind.setOnClickListener(this);   

        btn_aidl_unbind.setOnClickListener(this);   

        btn_aidl_send.setOnClickListener(this);   

    } 

   

    private IUserService mService; 

    private ServiceConnection mAidlConn = new ServiceConnection() { 

        public void onServiceConnected(ComponentName name, IBinder binder) { 

            mService   = IUserService.Stub.asInterface(binder); 

        }   

   

        public void onServiceDisconnected(ComponentName name) { 

            mService   = null; 

        }   

    }; 

   

    @Override 

    public void onClick(View v) { 

        if (v.getId() == R.id.btn_aidl_bind) {   

            Intent   intent = new Intent();   

            intent.setAction(AIDL_SERVICE);   

            Intent   newIntent = intent; 

            //Android5.0之后不能再隐式启动Service,只能显式启动Service 

            if (Build.VERSION.SDK_INT >=   Build.VERSION_CODES.LOLLIPOP) { 

                newIntent   = new Intent(IntentUtil.getExplicitIntent(this,   intent)); 

            }   

            boolean bBind = bindService(newIntent, mAidlConn,   Context.BIND_AUTO_CREATE); 

            Toast.makeText(this,   "绑定结果为"+bBind, Toast.LENGTH_LONG).show(); 

        }   else if (v.getId() == R.id.btn_aidl_unbind)   { 

            unbindService(mAidlConn);   

            mService   = null; 

        }   else if (v.getId() == R.id.btn_aidl_send) {   

            if (mService == null) { 

                Toast.makeText(this,   "未绑定AIDL服务", Toast.LENGTH_LONG).show(); 

            }   else {   

                try

                    double a1 = 123; 

                    double a2 = 9; 

                    double result = mService.multiply(a1, a2);   

                       

                    List<user>   userList = new ArrayList<user>();   

                    userList.add(new User(1, "张三", "111111"));   

                    userList.add(new User(2, "李四", "999999"));   

                    userList.add(new User(3, "王五", "123456"));   

                    int count = mService.save(userList); 

                       

                    String   desc = String.format("%f*%f计算结果是%f\n本次保存了%d条记录",  

                            a1,   a2, result, count); 

                    tv_aidl.setText(desc);   

                }   catch (RemoteException   e) { 

                    //   TODO Auto-generated catch block 

                    e.printStackTrace();   

                }   

            }   

        }   

    } 

}  </user></user>


下面是AIDL服务端的示例代码:

[代码]java代码:

?

01

02

03

04

05

06

07

08

09

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

import java.util.List; 

   

import com.example.exmprocess.aidl.data.IUserService.Stub; 

import com.example.exmprocess.aidl.data.User; 

   

import android.app.Service; 

import android.content.Intent; 

import android.os.IBinder; 

import android.os.RemoteException; 

import android.util.Log; 

   

public class AidlService   extends Service   { 

    private static final String   TAG = "AidlService"; 

    private final IBinder mBinder = new LocalBinder(); 

   

    public class LocalBinder extends Stub { 

        @Override 

        public double multiply(double a1, double a2) throws RemoteException { 

            return a1*a2; 

        }   

   

        @Override 

        public int save(List<user> userList) throws RemoteException { 

            //此处省略保存操作 

            return userList.size(); 

        }   

    } 

   

    @Override 

    public IBinder onBind(Intent intent) { 

        Log.d(TAG,   "onBind"); 

        return mBinder; 

    } 

   

}  </user>

原文链接:http://www.apkbus.com/blog-508687-63159.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消