文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-06-06 13:55

关注

前言:

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 {
    
    void registerCallBack(IAidlCallBack iAidlCallBack);
    void unregisterCallBack(IAidlCallBack iAidlCallBack);
    void sendMessage(String message);
    List getMessages();
}

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

interface IAidlCallBack {
    
    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 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;

@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 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();
    }
}

运行效果

源码下载地址

https://github.com/pengkongkong/TestAidlDemo1
作者:养猫误码


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯