Android使用AIDL实现两个App间通信
作者:斡风的天空 发布时间:2023-06-21 18:05:45
标签:Android,AIDL,App,通信
今天开发了一个功能,通过Android的AIDL机制完成两个app间的通信。功能需求很简单,一个客户端app,叫做client,一个服务端app叫orderManager;客户端负责展示订单列表,并且可以向服务端添加订单;服务端负责管理订单,可以对外提供订单信息。
闲言少叙,下面直接上代码。
1、编写bean类。
首先在client中定义OrderBean类,字段很简单,注意需要实现Parcelable接口:
package com.example.wang.client.bean;
import android.os.Parcel;
import android.os.Parcelable;
public class OrderBean implements Parcelable{
private String id;
private String name;
private int amount;
public OrderBean(){}
public OrderBean(String id, String name, int amount) {
this.id = id;
this.name = name;
this.amount = amount;
}
protected OrderBean(Parcel in) {
id = in.readString();
name = in.readString();
amount = in.readInt();
}
public static final Creator<OrderBean> CREATOR = new Creator<OrderBean>() {
@Override
public OrderBean createFromParcel(Parcel in) {
return new OrderBean(in);
}
@Override
public OrderBean[] newArray(int size) {
return new OrderBean[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(name);
dest.writeInt(amount);
}
//get/set方法略
}
2、定义aidl文件。aidl文件的存放位置在Android Studio中一般存放在如下路径:
client/src/aidl/…
// OrderBean.aidl
package com.example.wang.client.bean;//存放的包路径同bean类
parcelable OrderBean;//通信用到的Parcelable需要声明,并且使用小写的parcelable
// IBookManager.aidl
package com.example.wang.client.aidl;
import com.example.wang.client.bean.OrderBean;//除了系统提供的对象,都需要明确导入
interface IOrderManager {
List<OrderBean> getAll();
void add(in OrderBean bean);
}
3、定义布局文件,编写MainActivity。这个很简单,Button和RecyclerView结合即可:
#activity_main.xml - 主页面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:text="订单管理"
android:textSize="20dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp">
<Button
android:id="@+id/search_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15dp"
android:text="刷新订单"/>
<Button
android:id="@+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15dp"
android:text="添加订单"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
还要写一个item_order.xml,用于RecyclerView的展示,很简单,此处略过。
//MainActivity.java
package com.example.wang.client;
...
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private List<OrderBean> orderList;
private IOrderManager orderManager;
//UI
private Button search_button;
private Button add_button;
private RecyclerView recyclerView;
private OrderAdapter adapter;
ServiceConnection conn = new ServiceConnection() {//这个最重要,用于连接Service
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("MainActivity.conn","@@ onServiceConnected name="+name);
IOrderManager manager = IOrderManager.Stub.asInterface(service);
orderManager = manager;
refreshOrderList();
try {
service.linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("MainActivity.conn","@@ onServiceDisconnected name="+name);
}
};
IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {//注册一个死亡代理,监测连接状态
@Override
public void binderDied() {
Log.i("MainActivity","@@ binderDied "+(orderManager==null));
if(orderManager==null){
return;
}
orderManager.asBinder().unlinkToDeath(deathRecipient, 0);
orderManager = null;
//重新绑定
bindOrderService();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("MainActivity","@@ onCreate");
setContentView(R.layout.activity_main);
getLayoutInflater();
//view
search_button=findViewById(R.id.search_button);
add_button=findViewById(R.id.add_button);
recyclerView=findViewById(R.id.recyclerView);
//组装recyclerView
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
adapter=new OrderAdapter(this);
recyclerView.setAdapter(adapter);
//onclick
search_button.setOnClickListener(this);
add_button.setOnClickListener(this);
//bind
bindOrderService();
}
private void bindOrderService(){
Intent intent = new Intent("com.example.wang.ordermanager.OrderService");
intent.setPackage("com.example.wang.ordermanager");
intent.addCategory(Intent.CATEGORY_LAUNCHER);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
/**
* 重新获取数据并刷新列表。
*/
private void refreshOrderList(){
try {
if(orderManager!=null){
orderList = orderManager.getAll();
}
if(orderList!=null){
adapter.setData(orderList);
adapter.notifyDataSetChanged();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View v) {
if(v==search_button){
//刷新订单
refreshOrderList();
}else if(v==add_button){
//增加订单
try {
OrderBean orderBean=new OrderBean();
Random random=new Random();
orderBean.setAmount(random.nextInt(800)+100);
orderBean.setId(random.nextInt(100000000)+100000+"");
orderBean.setName("玩具"+random.nextInt());
orderManager.add(orderBean);
refreshOrderList();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
4、编写服务端代码
这里主要做两件事,第一个是移植aidl文件和bean类,将client中的aidl文件和OrderBean移植过来,文件路径要保持一致,第二个是编写OrderService.java类。
//OrderService.java
package com.example.wang.ordermanager;
...
public class OrderService extends Service{
private CopyOnWriteArrayList<OrderBean> list = new CopyOnWriteArrayList<>();
@Override
public void onCreate() {
super.onCreate();
Log.i("OrderService","@@ onCreate");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("OrderService","@@ onBind");
return binder;
}
Binder binder = new IOrderManager.Stub(){
@Override
public List<OrderBean> getAll() throws RemoteException {
return list;
}
@Override
public void add(OrderBean bean) throws RemoteException {
list.add(bean);
}
};
}
OrderService服务在AndroidManifest.xml中的配置如下:
<service android:name=".OrderService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.wang.ordermanager.OrderService"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</service>
代码编写就完成了,运行时需要先运行服务端app,再运行client,如果运行过程中OrderService服务断掉了,client会通过死亡代理得到通知,再重新绑定即可。
运行如下:
来源:https://blog.csdn.net/wangwofeng1987/article/details/79955549


猜你喜欢
- 本文实例为大家分享了java文件上传和预览实现代码,供大家参考,具体内容如下1、下载uploadify插件2、index.html<!
- 目录效果展示实现步骤1.生成抽奖矩形:2.添加奖品图片:3.实现抽奖动画:4.实现动态设置参数:5.添加抽奖结果回调效果展示实现步骤1.生成
- 一丶前言在之前我们学习了SpringBoot自动装配如何实现的,我们总结了Spring IOC的底层原理。但是我们还是不知道SpringAp
- 在Android的应用框架中,ActivityManagerService是非常重要的一个组件,尽管名字叫做ActivityManagerS
- 命名空间的特性首先熟悉一下命名空间的两个概念。声明区域:可以在其中进行声明的区域,如全局文件的声明区域是文件,函数内声明的变量声明区域为代码
- 消息都是存放在一个消息队列中去,而消息循环线程就是围绕这个消息队列进入一个无限循环的,直到线程退出。如果队列中有消息,消息循环线程就会把它取
- 1、首先看一下下面两个sql语句的区别:<select id="selectByNameAndPassword"
- 一、概要介绍 本文要介绍的是Java中的transient关键字,transient是短暂的意思。对于transie
- 本文实例为大家分享了java中文传值乱码问题,以及解决方法,供大家参考,具体内容如下一般编码格式设置:1.可以经过两次编码处理,即设置字符集
- 前言当我们写了一个方法,那么这个方法是如何被执行的呢?public int add(){ int a = 10;
- 前言最近有一项需求,要定时判断任务执行条件是否满足并触发 Spark 任务,平时编写 Spark 任务时都是封装为一个 Jar 包,然后采用
- 要求:1.通过手指移动来拖动图片 2.控制图片不能超出屏幕显示区域技术点:1.MotionEvent处理2.对View进行动态定位
- 本文实例讲述了C#自定义繁体和简体字库实现中文繁体和简体之间转换的方法。分享给大家供大家参考。具体分析如下:这里使用C#自定义繁体和简体字库
- 上篇文章给大家介绍了浅析C# 中的类型系统(值类型和引用类型),接下来通过本文给大家介绍下c# 泛型类型,说下C#中的泛型,熟练地使用泛型能
- 一、线程间的共享1.1 ynchronized内置锁用处Java支持多个线程同时访问一个对象或者对象的成员变量关键字synchronized
- 需求描述现在有这样一个需求:我有A、B两台服务器,其中A是一个视频处理服务器,B是一个数据存储服务器。此时有一个视频需要先在A服务器上进行一
- 声明类定义类:class MyClass { // 字段、构造函数和 // 方法声明}
- 判断有无虚拟按键(导航栏)现在很大一部分手机没有虚拟按键,一部分有。我们在做适配的时候可能会用到这方面的知识。例如:屏幕填充整个屏幕的时候,
- 使用匿名内部类课使代码更加简洁、紧凑,模块化程度更高。内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到。然而这
- WPF 窗体设置亚克力效果框架使用大于等于.NET40。Visual Studio 2022。项目使用 MIT 开源许可