概述
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android 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接口的说明:
(1)AIDL接口只支持方法,不能声明静态成员;
(2)不会有返回给调用方的异常。
(以上来自百度百科)
下面写一个简单的测试小例子:
客户端打开后,直接链接服务器的服务,并返回服务器存储的名字和年龄!
准备,需要新建两个工程:
客户端:ipcloginclient.Apk(包名com.yuan.ipcloginclient)
服务器:ipcloginserver.Apk(包名com.yuan.ipcloginserver)
客户端代码:
先建一个User.adil, 这个文件的作用是引入了一个序列化User供其他的AIDL文件使用
package com.yuan.aidl;
parcelable User;
定义 User.java, 实现序列化
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
//作用是定义方法接口
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 文件
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);
跟一般的绑定服务有差别!
比如:@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
其实是客户端应该跟服务器的标准一样,否则连不上,以服务器为准!
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
<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的一个简单学习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复