android系统进程隔离内存隔离,进程间不能共享内存 所以就需要一些机制在不同进程间进行数据通讯
AIDL:Android Interface Definition Language 安卓接口定义语言,封装了Binder实现内存通讯.
Android AIDL实现
1:创建服务端
1.1创建AIDL
包名右键-->New--->AIDL--->AIDLFile
1.1
IShareDataInterface.aidl
// IShareDataInterface.aidl
package com.wu.ipcservice;
import com.wu.ipcservice.IShareDataListener;
import com.wu.ipcservice.ShareDataInfo;
interface IShareDataInterface {
void sendShareData(int key, String values);
String getShareData(int key) ;
void registerCallback(int id, IShareDataListener callback) ;
void unregisterCallback(IShareDataListener callback) ;
void sendShareDataInfo(in ShareDataInfo info);
}
1.2创建封装数据类型:注意实现parcelable 序列化
1.2.1 创建封装数据
package com.wu.ipcservice;
import android.os.Parcel;
import android.os.Parcelable;
/**
* 作者:吴奎庆
* <p>
* 时间:7/29/23
* <p>
* 用途:
*/
public class ShareDataInfo implements Parcelable {
int type;
String content;
protected ShareDataInfo(Parcel in) {
type = in.readInt();
content = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(type);
dest.writeString(content);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<ShareDataInfo> CREATOR = new Creator<ShareDataInfo>() {
@Override
public ShareDataInfo createFromParcel(Parcel in) {
return new ShareDataInfo(in);
}
@Override
public ShareDataInfo[] newArray(int size) {
return new ShareDataInfo[size];
}
};
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "ShareDataInfo{" +
"type=" + type +
", content='" + content + '\'' +
'}';
}
}
1.1.3 创建封装数据的AIDL文件(只需要一个parcelable ShareDataInfo)
package com.wu.ipcservice;
parcelable ShareDataInfo;
注意
- 千万注意Make project一下(小锤子)
- 注意导包
-
注意序列化
service.png
- 创建服务
2.1创建服务Binder ShareDataBinder.
package com.wu.ipcservice;
import android.os.RemoteException;
import android.util.Log;
/**
* 作者:吴奎庆
* <p>
* 时间:7/29/23
* <p>
* 用途:
*/
public class ShareDataBinder extends IShareDataInterface.Stub {
IShareDataListener callback;
@Override
public void sendShareData(int key, String values) throws RemoteException {
Log.e("IPCService:", "收到了客户端的消息:" + values);
if (callback != null)
callback.notifyShareData(key, values);
}
@Override
public String getShareData(int key) throws RemoteException {
return "返回服务了服务层数据";
}
@Override
public void registerCallback(int id, IShareDataListener callback) throws RemoteException {
this.callback = callback;
}
@Override
public void unregisterCallback(IShareDataListener callback) throws RemoteException {
callback = null;
}
@Override
public void sendShareDataInfo(ShareDataInfo info) throws RemoteException {
Log.e("IPCService:", "收到了客户端的ShareDataInfo消息:" + info.toString());
}
}
2.2 创建ShareDataService服务
package com.wu.ipcservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import androidx.annotation.Nullable;
/**
* 作者:吴奎庆
* <p>
* 时间:7/29/23
* <p>
* 用途:
*/
public class ShareDataService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new ShareDataBinder();
}
}
2.3 清单配置
process:进程名
exported: 可外部访问
action: 外部开启的Action
<service
android:name=".ShareDataService"
android:process=":ipc_service"
android:exported="true" >
<intent-filter>
<action android:name="com.wu.ipc.service" />
</intent-filter>
</service>
2.创建客户端访问数据
2.1 将服务端创建的AIDL文件复制都客户端同样的位置线
- 位置:src-->main 下(和java统一目录下)
- make project (小锤子)一下
- 将创建的封装数据类型 放到和服务端同样的包名下(创建服务端包名,然后复制封装对象即可)
2.4 跨进程通讯
package com.wu.ipcclient;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
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 com.wu.ipcservice.IShareDataInterface;
import com.wu.ipcservice.ShareDataInfo;
public class MainActivity extends AppCompatActivity {
private IShareDataInterface shareDataInterface;
boolean isConnected;
ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
isConnected = true;
shareDataInterface = IShareDataInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
isConnected = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
findViewById(R.id.bt_connected).setOnClickListener(v ->{
startService();
});
findViewById(R.id.bt_send).setOnClickListener(v ->{
try {
shareDataInterface.sendShareData(10086,"发送了消息");
Log.e("IPCClient:","发送了消息:"+10086);
} catch (RemoteException e) {
e.printStackTrace();
}
});
findViewById(R.id.bt_get).setOnClickListener(v ->{
try {
String content=shareDataInterface.getShareData(10086);
Log.e("IPCClient:","获取消息:"+content);
} catch (RemoteException e) {
e.printStackTrace();
}
});
findViewById(R.id.bt_get_info).setOnClickListener(v ->{
try {
ShareDataInfo info= new ShareDataInfo(10010,"对象信息");
shareDataInterface.sendShareDataInfo(info);
} catch (RemoteException e) {
e.printStackTrace();
}
});
}
private void startService() {
ComponentName name = new ComponentName("com.wu.ipcservice", "com.wu.ipcservice.ShareDataService");
Intent intent = new Intent();
intent.setAction("com.wu.ipc.service");
intent.setComponent(name);
this.bindService(intent, this.mServiceConnection, this.BIND_AUTO_CREATE);
}
}
注意
- 注意引用不到的时候make project 一下
- 注意导包(封装数据类型注意序列化)
- 注意清单文件配置
- 注意 bindService()
总结
AIDL是通过IBinder封装的通讯协议来实现IPC的,AIDL是通过AIDL类的内部类Stub继承了IBinder的子类Binder实现跨进程通讯的Binder自身也是可以做跨进程通讯的.
核心方法:
- onTransact(int code, Parcel data, Parcel reply, int flags) 响应数据
- transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) 发送
网友评论