Android 使用AIDL进行两个APP之间通讯以及相互消息回调(一)

949次阅读
没有评论

前言:
AIDL:Android Interface Definition Language,翻译过来就是Android接口定义语言。是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。所以使用AIDL需要一个服务端和客户端
作用:可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。

1.AIDL支持的基本数据类型
八种基本数据类型:byte、char、short、int、long、float、double、boolean
String,CharSequence
实现了Parcelable接口的数据类型
List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
2.服务端的实现
创建工程,以及所需aidl文件
使用Android Studio新建一个工程,命名为TestAidlDemo1
右键New一个AIDL文件,取名为IAidlInterface,AS会自动在工程目录生成一个路径完全一样的aidl文件夹
既然是要回调消息,那就还需要一个回调接口,同样的方法,创建IAidlCallBack.aidl文件,那么接下来就进行代码编写
实现代码逻辑
编写IAidlInterface.aldi代码,因为我们需要回调消息,那么我们需要注册回调以及注销回调接口,一个发送消息的接口,一个获取历史消息的接口,代码如下(AIDL文件不会自动导包,一些不是基本支持数据类型需要我们自己手动import,)
import com.pgc.testaidldemo1.IAidlCallBack;
interface IAidlInterface {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void registerCallBack(IAidlCallBack iAidlCallBack);
void unregisterCallBack(IAidlCallBack iAidlCallBack);
void sendMessage(String message);
List getMessages();
}

编写IAidlCallBack.aidl代码:既然是回调接口,那么我们只需要一个消息发送成功的回调接口就行,代码如下

interface IAidlCallBack {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void onMessageSuccess(String message);
}

既然是服务端,我们需要实现接收消息已经处理消息的逻辑代码,所以我们创建一个AidlService,继承Service,因为Service不能直接接收Callback,但是提供了RemoteCallbackList来注册回调

private RemoteCallbackList callbackList= new RemoteCallbackList<>();
同时RemoteCallbackList提供了beginBroadcast来获取当前注册的回调数,因此我们可以通过这个方法进行回调处理(再使用了beginBroadcast之后必须调用finishBroadcast不然会报beginBroadcast() called while already in a broadcast错误)

final int num=callbackList.beginBroadcast();
for (int i=0;i<num;i++){
IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
iAidlCallBack.onMessageSuccess(message);
}
callbackList.finishBroadcast();
接下来实例化binder对象并返回给客户端,

@Override
public IBinder onBind(Intent intent) {
return binder;
}

private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
    @Override
    public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
        callbackList.register(iAidlCallBack);
    }

    @Override
    public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
        callbackList.unregister(iAidlCallBack);
    }

    @Override
    public void sendMessage(String message) throws RemoteException {
        messages.add(message);
        final int num=callbackList.beginBroadcast();
        for (int i=0;i<num;i++){
            IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
            iAidlCallBack.onMessageSuccess(message);
        }
        callbackList.finishBroadcast();
    }

    @Override
    public List<String> getMessages() throws RemoteException {
        return messages;
    }
};

在AndroidManifest.xml注册Service

AidlService全部代码

package com.pgc.testaidldemo1;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

/**

  • Created by PengGuiChu on 2020/4/11.
    */
    @SuppressLint(“Registered”)
    public class AidlService extends Service {
    private RemoteCallbackList callbackList= new RemoteCallbackList<>();
    private List messages=new ArrayList<>();
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    return binder;
    } private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
    @Override
    public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
    callbackList.register(iAidlCallBack);
    } @Override public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException { callbackList.unregister(iAidlCallBack); } @Override public void sendMessage(String message) throws RemoteException { messages.add(message); final int num=callbackList.beginBroadcast(); for (int i=0;i<num;i++){ IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i); iAidlCallBack.onMessageSuccess(message); } callbackList.finishBroadcast(); } @Override public List<String> getMessages() throws RemoteException { return messages; } }; @Override
    public void onCreate() {
    super.onCreate();
    }
    }

因为是服务端和客户端实现相互消息回调,因此在服务端也需要通过binderService来获取binder,相对客户端,因为服务端和AidlService是在同一线程,我们可以直接binderService

Intent intent=new Intent(getApplicationContext(),AidlService.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
然后实例化ServiceConnection

private ServiceConnection serviceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {

    }

};
然后在onServiceConnected中获取binder

iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
try {
iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
messages.addAll(iAidlInterface.getMessages());//获取历史消息
listView.setAdapter(arrayAdapter=new ArrayAdapter<>
(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
} catch (RemoteException e) {
e.printStackTrace();
}
DeathRecipient实例

private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    //当承载IBinder的进程消失时接收回调的接口
    @Override
    public void binderDied() {
        if (null == iAidlInterface) {
            return;
        }
        try {
            iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
        iAidlInterface = null;
    }
};

iAidlCallBack实例

private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
    @Override
    public void onMessageSuccess(String message) {
        if (messages!=null&&arrayAdapter!=null){
            messages.add(message);
            handler.sendEmptyMessage(1);
        }
    }
};

MainActivity全部代码

package com.pgc.testaidldemo1;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {
@BindView(R.id.list_view)
ListView listView;
private IAidlInterface iAidlInterface;
private int num;
private List messages=new ArrayList<>();
private ArrayAdapter arrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Intent intent=new Intent(getApplicationContext(),AidlService.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}

@OnClick(R.id.send_message)
public void onViewClicked(View view) {
    if (iAidlInterface!=null){
        try {
            iAidlInterface.sendMessage("消息"+num);
            num++;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

private ServiceConnection serviceConnection=new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
        try {
            iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
            iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
            messages.addAll(iAidlInterface.getMessages());//获取历史消息
            listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {

    }
};

private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    //当承载IBinder的进程消失时接收回调的接口
    @Override
    public void binderDied() {
        if (null == iAidlInterface) {
            return;
        }
        try {
            iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
        iAidlInterface = null;
    }
};

private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
    @Override
    public void onMessageSuccess(String message) {
        if (messages!=null&&arrayAdapter!=null){
            messages.add(message);
            handler.sendEmptyMessage(1);
        }
    }
};

@SuppressLint("HandlerLeak")
private Handler handler=new Handler(){
    @Override
    public void handleMessage(@NonNull Message msg) {
        arrayAdapter.notifyDataSetChanged();
    }
};

@Override
protected void onDestroy() {
    //解除注册
    if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
        try {
            iAidlInterface.unregisterCallBack(iAidlCallBack);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    //解除绑定服务
    unbindService(serviceConnection);
    super.onDestroy();
}

}

到此我们的服务端就编码完成,实现效果

3.客户端实现
创建client工程
选中TestAidlDemo1工程右键NEW一个model,命名为client
要想client项目能够连接上Service,我们直接复制上面工程的aidl文件到client工程的main文件里,这样是为了保证两个项目的aidl文件路径一致

而调用逻辑基本和上面MainActivity一样,需要注意一点的是,因为是两个不同进程,在这里我们不能直接bindService来调起服务端,而是通过以下代码实现
Intent intent=new Intent();
String ACTION = “AIDL.service”;//对应服务端AndroidManifest.xml配置service action:name
intent.setAction(ACTION);
intent.setPackage(“com.pgc.testaidldemo1”);//对应服务端AndroidManifest.xml package
bindService(intent,serviceConnection,BIND_AUTO_CREATE);

client的MainActivity全部代码

package com.pgc.client;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.pgc.testaidldemo1.IAidlCallBack;
import com.pgc.testaidldemo1.IAidlInterface;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {
@BindView(R.id.list_view)
ListView listView;
private IAidlInterface iAidlInterface;
private int num;
private List messages=new ArrayList<>();
private ArrayAdapter arrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Intent intent=new Intent();
String ACTION = “AIDL.service”;
intent.setAction(ACTION);
intent.setPackage(“com.pgc.testaidldemo1”);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}

@OnClick(R.id.send_message)
public void onViewClicked(View view) {
    if (iAidlInterface!=null){
        try {
            iAidlInterface.sendMessage("消息"+num);
            num++;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

private ServiceConnection serviceConnection=new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
        try {
            iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);
            iAidlInterface.registerCallBack(iAidlCallBack);
            messages.addAll(iAidlInterface.getMessages());
            listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {

    }
};

private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    //当承载IBinder的进程消失时接收回调的接口
    @Override
    public void binderDied() {
        if (null == iAidlInterface) {
            return;
        }
        iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
        iAidlInterface = null;
        //断线重来逻辑
    }
};

private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
    @Override
    public void onMessageSuccess(String message) {
        if (messages!=null&&arrayAdapter!=null){
            messages.add(message);
            handler.sendEmptyMessage(1);
        }
    }
};

@SuppressLint("HandlerLeak")
private Handler handler=new Handler(){
    @Override
    public void handleMessage(@NonNull Message msg) {
        arrayAdapter.notifyDataSetChanged();
    }
};

@Override
protected void onDestroy() {
    //解除注册
    if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
        try {
            iAidlInterface.unregisterCallBack(iAidlCallBack);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    //解除绑定服务
    unbindService(serviceConnection);
    super.onDestroy();
}

}

运行效果

源码下载地址

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 0
评论(没有评论)

文心AIGC

2023 年 9 月
 123
45678910
11121314151617
18192021222324
252627282930  
文心AIGC
文心AIGC
人工智能ChatGPT,AIGC指利用人工智能技术来生成内容,其中包括文字、语音、代码、图像、视频、机器人动作等等。被认为是继PGC、UGC之后的新型内容创作方式。AIGC作为元宇宙的新方向,近几年迭代速度呈现指数级爆发,谷歌、Meta、百度等平台型巨头持续布局
文章搜索
热门文章
潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026

潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026

潞晨尤洋:日常办公没必要上私有模型,这三类企业才需要 | MEET2026 Jay 2025-12-22 09...
“昆山杯”第二十七届清华大学创业大赛决赛举行

“昆山杯”第二十七届清华大学创业大赛决赛举行

“昆山杯”第二十七届清华大学创业大赛决赛举行 一水 2025-12-22 17:04:24 来源:量子位 本届...
MiniMax海螺视频团队首次开源:Tokenizer也具备明确的Scaling Law

MiniMax海螺视频团队首次开源:Tokenizer也具备明确的Scaling Law

MiniMax海螺视频团队首次开源:Tokenizer也具备明确的Scaling Law 一水 2025-12...
天下苦SaaS已久,企业级AI得靠「结果」说话

天下苦SaaS已久,企业级AI得靠「结果」说话

天下苦SaaS已久,企业级AI得靠「结果」说话 Jay 2025-12-22 13:46:04 来源:量子位 ...
最新评论
ufabet ufabet มีเกมให้เลือกเล่นมากมาย: เกมเดิมพันหลากหลาย ครบทุกค่ายดัง
tornado crypto mixer tornado crypto mixer Discover the power of privacy with TornadoCash! Learn how this decentralized mixer ensures your transactions remain confidential.
ดูบอลสด ดูบอลสด Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Pretty! This has been a really wonderful post. Many thanks for providing these details.
ดูบอลสด ดูบอลสด Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
Obrazy Sztuka Nowoczesna Obrazy Sztuka Nowoczesna Thank you for this wonderful contribution to the topic. Your ability to explain complex ideas simply is admirable.
ufabet ufabet Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
ufabet ufabet You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
ufabet ufabet Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
热评文章
摩尔线程的野心,不藏了

摩尔线程的野心,不藏了

摩尔线程的野心,不藏了 量子位的朋友们 2025-12-22 10:11:58 来源:量子位 上市后的仅15天...
摩尔线程的野心,不藏了

摩尔线程的野心,不藏了

摩尔线程的野心,不藏了 量子位的朋友们 2025-12-22 10:11:58 来源:量子位 上市后的仅15天...
AI体育教练来了!中国团队打造SportsGPT,完成从数值评估到专业指导的智能转身

AI体育教练来了!中国团队打造SportsGPT,完成从数值评估到专业指导的智能转身

AI体育教练来了!中国团队打造SportsGPT,完成从数值评估到专业指导的智能转身 量子位的朋友们 2025...
AI体育教练来了!中国团队打造SportsGPT,完成从数值评估到专业指导的智能转身

AI体育教练来了!中国团队打造SportsGPT,完成从数值评估到专业指导的智能转身

AI体育教练来了!中国团队打造SportsGPT,完成从数值评估到专业指导的智能转身 量子位的朋友们 2025...
真正面向大模型的AI Infra,必须同时懂模型、系统、产业|商汤大装置宣善明@MEET2026

真正面向大模型的AI Infra,必须同时懂模型、系统、产业|商汤大装置宣善明@MEET2026

真正面向大模型的AI Infra,必须同时懂模型、系统、产业|商汤大装置宣善明@MEET2026 量子位的朋友...