AIDL
(
Android
接口定义语言),可以使用它定义客户端与服务端进程间通信(
IPC
)的编程接口。在 Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分 隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL
就是为了满 足这种需求而诞生的。通过AIDL
,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法, 从而满足进程间通信的需求。
使用流程
1.
在
.aidl
文件中定义
AIDL
接口,并将其添加到应用工程的
src
目录下,创建完成之后
rebuild
2. Android SDK
工具会自动生成基于该
.aidl
文件的
IBinder
接口,具体的业务对象实现这个接口,
这个具体的业务对象也是
IBinder
对象,当绑定服务的时候会根据实际情况返回具体的通信对象
(本地还是代理)
3.
将客户端绑定到该服务上,之后就可以调用
IBinder
中的方法来进行进程间通信(
IPC
)
在服务端
1. 首先,在工程的
src
目录下创建
.aidl
文件
2.打开
IPersonAidlInterface.aidl
,在
.aidl
文件中添加具体的业务 比如
// PayAidlInterface.aidl
package com.hopu.trueservise;
// Declare any non-default types here with import statements
interface PayAidlInterface {
具体业务
void setAccount(String user,String pswood);
boolean getInfo();
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
}
3.然后,重新 rebuild project , Android SDK 工具会在相应的目录生成对应的与 .aidl 文件同名的 .java
4.那么这个业务要体现在什么地方呢,从上面可知 Stub 是一个抽象类,那么它所提供的具体业务必然需要一个具体的实现类来完成,下面实现这个具体的业务类,具体如下
package com.hopu.trueservise;
import android.os.RemoteException;
public class Ture extends PayAidlInterface.Stub{
private String user;
private String pswood;
@Override
public void setAccount(String user, String pswood) throws RemoteException {
this.user = user;
this.pswood = pswood;
}
@Override
public boolean getInfo() throws RemoteException {
String[] useri = {"123456","789123"};
String[] pswoodi = {"147258","0369"};
for (int i = 0; i < useri.length; i++) {
if (user.equals(useri[i]) && pswood.equals(pswoodi[i])){
return true;
}
}
return false;
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
}
5.
向客户端公开接口
package com.hopu.trueservise;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
return new Ture();
}
}
当外部调用
bindService()
方法绑定服务时,就会调用
onBind()
方法返回
IBinder
对象,这个
IBinder 对象也是具体的业务对象,如这里的 onBind()
方法返回的也是具体的业务对象,两者是统一的。此外, 创建的 Service
要在
AndroidManifest.xml
文件中声明,具体如下:
<serviceandroid:name = ".PersonService"android:enabled = "true"android:exported = "true"android:process = ":remote" ></service>其中使用 process 关键字表示为该服务开启一个独立的进程, remote 可任意,表示进程名称, ":" 将会 在主进程(进程名为包名)添加新名称作为新进程的名称,如 com.hopu.study 将会变成 com.hopu.study:remote。
在客户端
客户端远程调用
package com.hopu.login;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.hopu.trueservise.PayAidlInterface;
public class MainActivity extends AppCompatActivity {
private Button but_LogIn;
private TextInputEditText tf_user;
private TextInputEditText tf_pwd;
private PayAidlInterface payAidlInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but_LogIn = findViewById(R.id.but_LogIn);
tf_user = findViewById(R.id.tf_user);
tf_pwd = findViewById(R.id.tf_pwd);
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.hopu.trueservise","com.hopu.trueservise.MyService"));
bindService(intent,conn,BIND_AUTO_CREATE);
but_LogIn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String user = tf_user.getText().toString();
String pwd = tf_pwd.getText().toString();
try {
payAidlInterface.setAccount(user,pwd);
if (payAidlInterface.getInfo()){
Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("TAG", "onServiceConnected: ");
payAidlInterface = PayAidlInterface.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
}