当前位置:   article > 正文

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

android aidl 互相收发数据

前言:

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

1.AIDL支持的基本数据类型

  1. 八种基本数据类型:byte、char、short、int、long、float、double、boolean
  2. String,CharSequence
  3. 实现了Parcelable接口的数据类型
  4. List 类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象
  5. Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

2.服务端的实现

   创建工程,以及所需aidl文件

  • 使用Android Studio新建一个工程,命名为TestAidlDemo1
  • 右键New一个AIDL文件,取名为IAidlInterface,AS会自动在工程目录生成一个路径完全一样的aidl文件夹
  • 既然是要回调消息,那就还需要一个回调接口,同样的方法,创建IAidlCallBack.aidl文件,那么接下来就进行代码编写

实现代码逻辑

  • 编写IAidlInterface.aldi代码,因为我们需要回调消息,那么我们需要注册回调以及注销回调接口,一个发送消息的接口,一个获取历史消息的接口,代码如下(AIDL文件不会自动导包,一些不是基本支持数据类型需要我们自己手动import,)
    1. import com.pgc.testaidldemo1.IAidlCallBack;
    2. interface IAidlInterface {
    3. /**
    4. * Demonstrates some basic types that you can use as parameters
    5. * and return values in AIDL.
    6. */
    7. void registerCallBack(IAidlCallBack iAidlCallBack);
    8. void unregisterCallBack(IAidlCallBack iAidlCallBack);
    9. void sendMessage(String message);
    10. List<String> getMessages();
    11. }

     

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

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

     

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

    private RemoteCallbackList<IAidlCallBack> callbackList= new RemoteCallbackList<>();

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

    1. final int num=callbackList.beginBroadcast();
    2. for (int i=0;i<num;i++){
    3. IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
    4. iAidlCallBack.onMessageSuccess(message);
    5. }
    6. callbackList.finishBroadcast();

     接下来实例化binder对象并返回给客户端,

    1. @Override
    2. public IBinder onBind(Intent intent) {
    3. return binder;
    4. }
    5. private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
    6. @Override
    7. public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
    8. callbackList.register(iAidlCallBack);
    9. }
    10. @Override
    11. public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
    12. callbackList.unregister(iAidlCallBack);
    13. }
    14. @Override
    15. public void sendMessage(String message) throws RemoteException {
    16. messages.add(message);
    17. final int num=callbackList.beginBroadcast();
    18. for (int i=0;i<num;i++){
    19. IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
    20. iAidlCallBack.onMessageSuccess(message);
    21. }
    22. callbackList.finishBroadcast();
    23. }
    24. @Override
    25. public List<String> getMessages() throws RemoteException {
    26. return messages;
    27. }
    28. };

      

  • 在AndroidManifest.xml注册Service

    1. <service android:name=".AidlService"
    2. android:enabled="true"
    3. android:exported="true"
    4. >
    5. <intent-filter android:priority="1000">
    6. <action android:name="AIDL.service"></action>
    7. </intent-filter>
    8. </service>

     

  • AidlService全部代码

    1. package com.pgc.testaidldemo1;
    2. import android.annotation.SuppressLint;
    3. import android.app.Service;
    4. import android.content.Intent;
    5. import android.os.IBinder;
    6. import android.os.RemoteCallbackList;
    7. import android.os.RemoteException;
    8. import androidx.annotation.Nullable;
    9. import java.util.ArrayList;
    10. import java.util.List;
    11. /**
    12. * Created by PengGuiChu on 2020/4/11.
    13. */
    14. @SuppressLint("Registered")
    15. public class AidlService extends Service {
    16. private RemoteCallbackList<IAidlCallBack> callbackList= new RemoteCallbackList<>();
    17. private List<String> messages=new ArrayList<>();
    18. @Nullable
    19. @Override
    20. public IBinder onBind(Intent intent) {
    21. return binder;
    22. }
    23. private final IAidlInterface.Stub binder=new IAidlInterface.Stub() {
    24. @Override
    25. public void registerCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
    26. callbackList.register(iAidlCallBack);
    27. }
    28. @Override
    29. public void unregisterCallBack(IAidlCallBack iAidlCallBack) throws RemoteException {
    30. callbackList.unregister(iAidlCallBack);
    31. }
    32. @Override
    33. public void sendMessage(String message) throws RemoteException {
    34. messages.add(message);
    35. final int num=callbackList.beginBroadcast();
    36. for (int i=0;i<num;i++){
    37. IAidlCallBack iAidlCallBack=callbackList.getBroadcastItem(i);
    38. iAidlCallBack.onMessageSuccess(message);
    39. }
    40. callbackList.finishBroadcast();
    41. }
    42. @Override
    43. public List<String> getMessages() throws RemoteException {
    44. return messages;
    45. }
    46. };
    47. @Override
    48. public void onCreate() {
    49. super.onCreate();
    50. }
    51. }

     

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

    1. Intent intent=new Intent(getApplicationContext(),AidlService.class);
    2. bindService(intent,serviceConnection,BIND_AUTO_CREATE);

    然后实例化ServiceConnection

    1. private ServiceConnection serviceConnection=new ServiceConnection() {
    2. @Override
    3. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    4. }
    5. @Override
    6. public void onServiceDisconnected(ComponentName componentName) {
    7. }
    8. };

    然后在onServiceConnected中获取binder

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

    DeathRecipient实例

    1. private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    2. //当承载IBinder的进程消失时接收回调的接口
    3. @Override
    4. public void binderDied() {
    5. if (null == iAidlInterface) {
    6. return;
    7. }
    8. try {
    9. iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
    10. } catch (RemoteException e) {
    11. e.printStackTrace();
    12. }
    13. iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
    14. iAidlInterface = null;
    15. }
    16. };

    iAidlCallBack实例

    1. private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
    2. @Override
    3. public void onMessageSuccess(String message) {
    4. if (messages!=null&&arrayAdapter!=null){
    5. messages.add(message);
    6. handler.sendEmptyMessage(1);
    7. }
    8. }
    9. };

     MainActivity全部代码

    1. package com.pgc.testaidldemo1;
    2. import android.annotation.SuppressLint;
    3. import android.content.ComponentName;
    4. import android.content.Intent;
    5. import android.content.ServiceConnection;
    6. import android.os.Bundle;
    7. import android.os.Handler;
    8. import android.os.IBinder;
    9. import android.os.Message;
    10. import android.os.RemoteException;
    11. import android.view.View;
    12. import android.widget.ArrayAdapter;
    13. import android.widget.ListView;
    14. import androidx.annotation.NonNull;
    15. import androidx.appcompat.app.AppCompatActivity;
    16. import java.util.ArrayList;
    17. import java.util.List;
    18. import butterknife.BindView;
    19. import butterknife.ButterKnife;
    20. import butterknife.OnClick;
    21. public class MainActivity extends AppCompatActivity {
    22. @BindView(R.id.list_view)
    23. ListView listView;
    24. private IAidlInterface iAidlInterface;
    25. private int num;
    26. private List<String> messages=new ArrayList<>();
    27. private ArrayAdapter arrayAdapter;
    28. @Override
    29. protected void onCreate(Bundle savedInstanceState) {
    30. super.onCreate(savedInstanceState);
    31. setContentView(R.layout.activity_main);
    32. ButterKnife.bind(this);
    33. Intent intent=new Intent(getApplicationContext(),AidlService.class);
    34. bindService(intent,serviceConnection,BIND_AUTO_CREATE);
    35. }
    36. @OnClick(R.id.send_message)
    37. public void onViewClicked(View view) {
    38. if (iAidlInterface!=null){
    39. try {
    40. iAidlInterface.sendMessage("消息"+num);
    41. num++;
    42. } catch (RemoteException e) {
    43. e.printStackTrace();
    44. }
    45. }
    46. }
    47. private ServiceConnection serviceConnection=new ServiceConnection() {
    48. @Override
    49. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    50. iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
    51. try {
    52. iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);//监听进程是否消失
    53. iAidlInterface.registerCallBack(iAidlCallBack);//注册消息回调
    54. messages.addAll(iAidlInterface.getMessages());//获取历史消息
    55. listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
    56. } catch (RemoteException e) {
    57. e.printStackTrace();
    58. }
    59. }
    60. @Override
    61. public void onServiceDisconnected(ComponentName componentName) {
    62. }
    63. };
    64. private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    65. //当承载IBinder的进程消失时接收回调的接口
    66. @Override
    67. public void binderDied() {
    68. if (null == iAidlInterface) {
    69. return;
    70. }
    71. try {
    72. iAidlInterface.unregisterCallBack(iAidlCallBack);//注销
    73. } catch (RemoteException e) {
    74. e.printStackTrace();
    75. }
    76. iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
    77. iAidlInterface = null;
    78. }
    79. };
    80. private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
    81. @Override
    82. public void onMessageSuccess(String message) {
    83. if (messages!=null&&arrayAdapter!=null){
    84. messages.add(message);
    85. handler.sendEmptyMessage(1);
    86. }
    87. }
    88. };
    89. @SuppressLint("HandlerLeak")
    90. private Handler handler=new Handler(){
    91. @Override
    92. public void handleMessage(@NonNull Message msg) {
    93. arrayAdapter.notifyDataSetChanged();
    94. }
    95. };
    96. @Override
    97. protected void onDestroy() {
    98. //解除注册
    99. if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
    100. try {
    101. iAidlInterface.unregisterCallBack(iAidlCallBack);
    102. } catch (RemoteException e) {
    103. e.printStackTrace();
    104. }
    105. }
    106. //解除绑定服务
    107. unbindService(serviceConnection);
    108. super.onDestroy();
    109. }
    110. }

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

3.客户端实现

   创建client工程

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

       

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

     

  • client的MainActivity全部代码

    1. package com.pgc.client;
    2. import android.annotation.SuppressLint;
    3. import android.content.ComponentName;
    4. import android.content.Intent;
    5. import android.content.ServiceConnection;
    6. import android.os.Bundle;
    7. import android.os.Handler;
    8. import android.os.IBinder;
    9. import android.os.Message;
    10. import android.os.RemoteException;
    11. import android.view.View;
    12. import android.widget.ArrayAdapter;
    13. import android.widget.ListView;
    14. import androidx.annotation.NonNull;
    15. import androidx.appcompat.app.AppCompatActivity;
    16. import com.pgc.testaidldemo1.IAidlCallBack;
    17. import com.pgc.testaidldemo1.IAidlInterface;
    18. import java.util.ArrayList;
    19. import java.util.List;
    20. import butterknife.BindView;
    21. import butterknife.ButterKnife;
    22. import butterknife.OnClick;
    23. public class MainActivity extends AppCompatActivity {
    24. @BindView(R.id.list_view)
    25. ListView listView;
    26. private IAidlInterface iAidlInterface;
    27. private int num;
    28. private List<String> messages=new ArrayList<>();
    29. private ArrayAdapter arrayAdapter;
    30. @Override
    31. protected void onCreate(Bundle savedInstanceState) {
    32. super.onCreate(savedInstanceState);
    33. setContentView(R.layout.activity_main);
    34. ButterKnife.bind(this);
    35. Intent intent=new Intent();
    36. String ACTION = "AIDL.service";
    37. intent.setAction(ACTION);
    38. intent.setPackage("com.pgc.testaidldemo1");
    39. bindService(intent,serviceConnection,BIND_AUTO_CREATE);
    40. }
    41. @OnClick(R.id.send_message)
    42. public void onViewClicked(View view) {
    43. if (iAidlInterface!=null){
    44. try {
    45. iAidlInterface.sendMessage("消息"+num);
    46. num++;
    47. } catch (RemoteException e) {
    48. e.printStackTrace();
    49. }
    50. }
    51. }
    52. private ServiceConnection serviceConnection=new ServiceConnection() {
    53. @Override
    54. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    55. iAidlInterface=IAidlInterface.Stub.asInterface(iBinder);
    56. try {
    57. iAidlInterface.asBinder().linkToDeath(mDeathRecipient, 0);
    58. iAidlInterface.registerCallBack(iAidlCallBack);
    59. messages.addAll(iAidlInterface.getMessages());
    60. listView.setAdapter(arrayAdapter=new ArrayAdapter<>(getApplicationContext(),android.R.layout.simple_list_item_1,messages));
    61. } catch (RemoteException e) {
    62. e.printStackTrace();
    63. }
    64. }
    65. @Override
    66. public void onServiceDisconnected(ComponentName componentName) {
    67. }
    68. };
    69. private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
    70. //当承载IBinder的进程消失时接收回调的接口
    71. @Override
    72. public void binderDied() {
    73. if (null == iAidlInterface) {
    74. return;
    75. }
    76. iAidlInterface.asBinder().unlinkToDeath(mDeathRecipient, 0);
    77. iAidlInterface = null;
    78. //断线重来逻辑
    79. }
    80. };
    81. private IAidlCallBack iAidlCallBack=new IAidlCallBack.Stub() {
    82. @Override
    83. public void onMessageSuccess(String message) {
    84. if (messages!=null&&arrayAdapter!=null){
    85. messages.add(message);
    86. handler.sendEmptyMessage(1);
    87. }
    88. }
    89. };
    90. @SuppressLint("HandlerLeak")
    91. private Handler handler=new Handler(){
    92. @Override
    93. public void handleMessage(@NonNull Message msg) {
    94. arrayAdapter.notifyDataSetChanged();
    95. }
    96. };
    97. @Override
    98. protected void onDestroy() {
    99. //解除注册
    100. if (null != iAidlInterface && iAidlInterface.asBinder().isBinderAlive()) {
    101. try {
    102. iAidlInterface.unregisterCallBack(iAidlCallBack);
    103. } catch (RemoteException e) {
    104. e.printStackTrace();
    105. }
    106. }
    107. //解除绑定服务
    108. unbindService(serviceConnection);
    109. super.onDestroy();
    110. }
    111. }

     

  • 运行效果

源码下载地址

https://github.com/pengkongkong/TestAidlDemo1

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/122659
推荐阅读
相关标签
  

闽ICP备14008679号