相关类关系:
public interface IBinder {...}
public class Binder implements IBinder {...}
//BookManager为自定义的aidl接口
public interface BookManger extends IInterface {
//Stub为内部类
public static abstract class Stub extends Binder implements BookManger{...}
}
public interface IInterface
{
public IBinder asBinder();
}
1、创建.aidl文件,并定义通信接口。(服务端和客户端都必须有此文件,连同包名、类名及内容都必须相同)
1、创建aidl文件:src/main 文件夹下创建一个AIDL文件(Android Studio->File->New->AIDL->AIDL file),创建后Android Studio会自动把这个.aidl文件放到一个aidl的目录下。
2、定义接口:
// IRemoteService.aidl
package com.example.administrator.aidldemo;
// Declare any non-default types here with import statements
interface IRemoteService {
int getPid();
/**
* 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、建好后build ,Android SDK Tool会根据我们的.aidl文件自动生成一个同名的.java文件。
路径为:
AIDLDemo\app\build\generated\source\aidl\debug\com\example\administrator\aidldemo\IRemoteService.java
2、服务端:创建一个Service暴露AIDL接口并实现AIDL的接口函数。service要在清单文件中注册。
package com.example.administrator.aidldemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.support.annotation.Nullable;
/**
* 服务端
* Created by Administrator on 2017/6/2.
*/
public class RemoteService extends Service {
public RemoteService() {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
/*Stub类:Binder的实现类,服务端需要实现这个类来提供服务。*/
private IRemoteService.Stub binder = new IRemoteService.Stub() {
@Override
public int getPid() throws RemoteException {
return Process.myPid();
}
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
};
}
manifest.xml中注册service
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true"
android:process=":remote" />
3、客户端:调用服务端的服务:
package com.example.administrator.aidldemo;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
/*客户端*/
public class MainActivity extends AppCompatActivity {
private final static String TAG = "MainActivity";
private IRemoteService remoteService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, RemoteService.class);
bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE); // 绑定服务
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取AIDL的接口实现引用
/*asInterface函数: 一个静态函数,用来将IBinder转换成对应的Binder的引用。*/
IRemoteService iRemoteService = IRemoteService.Stub.asInterface(service);
try {
Log.i(TAG, "Client pid= " + Process.myPid());//当前进程
Log.i(TAG, "RemoteService pid= " + iRemoteService.getPid());//服务端进程
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "Service has unexpectedly disconnected");
remoteService = null;
}
};
}
运行效果:
MainActivity: Client pid= 8541
MainActivity: RemoteService pid= 8553
通过IPC传递对象
1:使用Parcelable来序列化对象
注意读音:
parcel:扒~手
parcelable:帕斯~雷柏
package com.example.administrator.aidldemo2;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Administrator on 2017/6/2.
*/
public class CellPhone implements Parcelable {
private String phone;
private String name;
public CellPhone(String phone, String name) {
this.phone = phone;
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.phone);
dest.writeString(this.name);
}
public CellPhone() {
}
protected CellPhone(Parcel in) {
this.phone = in.readString();
this.name = in.readString();
}
public static final Parcelable.Creator<CellPhone> CREATOR = new Parcelable.Creator<CellPhone>() {
@Override
public CellPhone createFromParcel(Parcel source) {
return new CellPhone(source);
}
@Override
public CellPhone[] newArray(int size) {
return new CellPhone[size];
}
};
@Override
public String toString() {
return "CellPhone{" +
"phone='" + phone + '\'' +
", name='" + name + '\'' +
'}';
}
}
2:创建.aidl文件,并定义通信接口。
(服务端和客户端都必须有此文件,连同包名、类名及内容都必须相同)
1、aidl文件名要与上面的序列化类名一致。但是这样的话,好像创建不了aidl文件,它会提示你“Interface name must be unique”,这时,你可以任意起一个名字,这时会生成一个aidl文件。然后对这个aidl文件进行重命名,把它命名成与上面的序列化类名一致 , 然后在这个aidl文件里,对这个类序列化。
CellPhone.aidl
package com.example.administrator.aidldemo2;
parcelable CellPhone;
2、接下来就是在当前aidl包名下,再创建一个Aidl文件,在这个文件中暴露出你想调用的方法。
CellPhoneManager.aidl
package com.example.administrator.aidldemo2;
import com.example.administrator.aidldemo2.CellPhone;
interface CellPhoneManager {
String call();
CellPhone getPhone();
}
这里特别要注意“import com.example.administrator.aidldemo2.CellPhone;”导入这个。
如图:
3、build,Android SDK Tool会根据我们的.aidl文件自动生成一个同名的.java文件。
路径为:
AIDLDemo2\app\build\generated\source\aidl\debug\com\example\administrator\aidldemo2.CellPhoneManager.java
如图:
4、为了避免AIDL 自定义类型CellPhoneManager.java找不到问题,可以添加以下内容到build.gradle中android 目录中的最后。
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
如图:
3、服务端:创建一个Service暴露AIDL接口并实现AIDL的接口函数。service要在清单文件中注册。
package com.example.administrator.aidldemo2;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
/**
* Created by Administrator on 2017/6/2.
*/
public class CellServer extends Service {
public CellServer() {
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
CellPhoneManager.Stub binder = new CellPhoneManager.Stub() {
@Override
public String call() throws RemoteException {
return "hello my name is call";
}
@Override
public CellPhone getPhone() throws RemoteException {
CellPhone cell = new CellPhone();
cell.setPhone("110-1234567");
cell.setName("公安局");
return cell;
}
@Override
public IBinder asBinder() {
return super.asBinder();
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
}
注册:
<service android:name=".CellServer"
android:enabled="true"
android:exported="true"
android:process=":remote">
4、客户端:调用服务端的服务:
客户端要有与服务端相同的aidl文件,只不过包名要注意也要相同,不要弄错,然后还有CellPhone这个类也相同。
package com.example.administrator.aidldemo2;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button mBtn;
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mBtn = (Button) findViewById(R.id.press);
mTv = (TextView) findViewById(R.id.tv);
mBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//启动服务
Intent intent = new Intent(MainActivity.this,CellServer.class);
//automatically create the service as long
//* as the binding exists. Note that while this will create the service,
bindService(intent,mConnection,BIND_AUTO_CREATE);
}
});
}
//服务链接
ServiceConnection mConnection = new ServiceConnection() {
CellPhoneManager mServer;
String content;
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("Test","onServiceConnected");
//初始化aidl
mServer = CellPhoneManager.Stub.asInterface(service);
try {
content = mServer.call()+" 》》》》 ";
CellPhone cell = mServer.getPhone();
content += cell.getPhone();
mTv.setText(content);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mServer = null;
}
};
}
布局 :
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.aidldemo2.MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/press"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="aidl通信对象" />
</android.support.constraint.ConstraintLayout>
效果: