我是靠谱客的博主 精明飞鸟,这篇文章主要介绍Aidl的一个简单学习,现在分享给大家,希望可以做个参考。

为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用Remote Procedure CallRPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition LanguageIDL)来公开服务的接口。我们知道4Android应用程序组件中的3个(ActivityBroadcastReceiverContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDLAndroid Interface Definition Language)服务。

 

建立AIDL服务的步骤

建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:

1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。

2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。

3)建立一个服务类(Service的子类)。

4)实现由aidl文件生成的Java接口。

5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。

实现AIDL接口的说明:

1AIDL接口只支持方法,不能声明静态成员;

2)不会有返回给调用方的异常。

(以上来自百度百科)

 

下面写一个简单的测试小例子:

客户端打开后,直接链接服务器的服务,并返回服务器存储的名字和年龄!

 

准备,需要新建两个工程: 

客户端:ipcloginclient.Apk(包名com.yuan.ipcloginclient

服务器:ipcloginserver.Apk(包名com.yuan.ipcloginserver

 

客户端代码:

先建一个User.adil, 这个文件的作用是引入了一个序列化User供其他的AIDL文件使用

复制代码
1
2
3
package com.yuan.aidl; parcelable User;


定义 User.java, 实现序列化

复制代码
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
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
public class User implements Parcelable { private String name; private int age; public User(){ } public User(Parcel in) { name = in.readString(); age = in.readInt(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static final Creator<User> CREATOR = new Creator<User>() { @Override public User createFromParcel(Parcel in) { return new User(in); } @Override public User[] newArray(int size) { return new User[size]; } }; @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated method stub dest.writeString(name); dest.writeInt(age); } /** * 参数是一个Parcel,用它来存储与传输数据 * @param dest */ public void readFromParcel(Parcel dest) { //注意,此处的读值顺序应当是和writeToParcel()方法中一致的 name = dest.readString(); age = dest.readInt(); } //方便打印数据 @Override public String toString() { return "name : " + name + " , age : " + age; } }

定义UserManger.aidl

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//作用是定义方法接口 package com.yuan.aidl; //导入所需要使用的非默认支持数据类型的包 import com.yuan.aidl.User; interface UserManger { //所有的返回值前都不需要加任何东西,不管是什么数据类型 List<User> getUsers(); //传参时除了Java基本类型以及String,CharSequence之外的类型 //都需要在前面加上定向tag,具体加什么量需而定 void addUser(inout User user); }

这个UserManger.aidl编译的时候会在gen里生成UserManager.java

下面是Activity 文件

复制代码
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
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
public class MainActivity extends Activity { //由AIDL文件生成的Java类 private UserManger mUserManger = null; //标志当前与服务端连接状况的布尔值,false为未连接,true为连接中 private boolean mBound = false; //包含Book对象的list private List<User> mUser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } /** * 按钮的点击事件,点击之后调用服务端的addUserIn方法 * * @param view */ public void addUser(View view) { //如果与服务端的连接处于未连接状态,则尝试连接 if (!mBound) { attemptToBindService(); Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show(); return; } if (mUserManger == null) return; User user = new User(); user.setName("李老三"); user.setAge(23); try { mUserManger.addUser(user); Log.e(getLocalClassName(), user.toString()); } catch (RemoteException e) { e.printStackTrace(); } } /** * 尝试与服务端建立连接 */ private void attemptToBindService() { Intent intent = new Intent(); intent.setAction("com.yuan.login"); intent.setPackage("com.yuan.ipcloginserver"); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStart() { super.onStart(); if (!mBound) { attemptToBindService(); } } @Override protected void onStop() { super.onStop(); if (mBound) { unbindService(mServiceConnection); mBound = false; } } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.e(getLocalClassName(), "service connected"); mUserManger = UserManger.Stub.asInterface(service); mBound = true; if (mUserManger != null) { try { mUser = mUserManger.getUsers(); Log.e(getLocalClassName(), mUser.toString()); } catch (RemoteException e) { e.printStackTrace(); } } } @Override public void onServiceDisconnected(ComponentName name) { Log.e(getLocalClassName(), "service disconnected"); mBound = false; } }; }

注意:

bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);

也是bindService哦!

也必须 new 一个 ServiceConnection也就是mServiceConnection


还要注意

mUserManger = UserManger.Stub.asInterface(service);

跟一般的绑定服务有差别!

比如:

复制代码
1
2
3
4
5
6
7
8
@Override   public void onServiceConnected(ComponentName name, IBinder service) {      // TODO Auto-generated method stub      MyBinder binder = (MyBinder)service;      bindService = binder.getService();      bindService.BindMethod();      connFlag = true;   }  

下面是服务器:

s服务器:

User.aidl        User.java       UserManager.aidl

这三个文件必须要跟客户端的包名 路径等一模一样!都是 com.yuan.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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class LoginService extends Service{ public final String TAG = this.getClass().getSimpleName(); //包含User对象的list private List<User> mUsers = new ArrayList<User>(); //由AIDL文件生成的UserManger private final UserManger.Stub mUserManger = new UserManger.Stub() { @Override public List<User> getUsers() throws RemoteException { synchronized (this) { Log.e(TAG, "invoking getUsers() method , now the list is : " + mUsers.toString()); if (mUsers != null) { return mUsers; } return new ArrayList<User>(); } } @Override public void addUser(User user) throws RemoteException { synchronized (this) { if (mUsers == null) { mUsers = new ArrayList<User>(); } if (user == null) { Log.e(TAG, "User is null in In"); user = new User(); } //尝试修改user的参数,主要是为了观察其到客户端的反馈 user.setAge(66); if (!mUsers.contains(user)) { mUsers.add(user); } //打印mUsers列表,观察客户端传过来的值 Log.e(TAG, "invoking addUsers() method , now the list is : " + mUsers.toString()); } } }; @Override public void onCreate() { User user = new User(); user.setName("刘老六"); user.setAge(28); mUsers.add(user); super.onCreate(); } @Nullable @Override public IBinder onBind(Intent intent) { Log.e(getClass().getSimpleName(), String.format("on bind,intent = %s", intent.toString())); return mUserManger; } }

记得在服务器的 AndroidManifest.xml

复制代码
1
2
3
4
5
6
7
8
<service android:name=".service.LoginService" android:exported="true" > <intent-filter> <action android:name="com.yuan.login" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>

注意:

private final UserManger.Stub mUserManger = new UserManger.Stub()

在IBinder onBind(Intent intent){ } 的时候,返回的是mUserManger 

 

一般的绑定服务定义的是一个Binder

比如

private MyBinder myBinder = new MyBinder();  

在IBinder onBind(Intent intent){}的时候,返回的是myBinder 


差不多就这样子哦!

当制作音乐播放器的时候可以这么做哦!






最后

以上就是精明飞鸟最近收集整理的关于Aidl的一个简单学习的全部内容,更多相关Aidl内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部