当前位置:   article > 正文

【Android】使用AIDL实现进程间传递对象案例_aidl 传interface对象

aidl 传interface对象

1 前言

        在 Android——使用AIDL实现进程间通讯简单案例 中介绍了使用 AIDL 在进程间传递字符串,对于8种基本数据类型( byte、short、int、long、float、double、boolean、char )和 CharSequence(包含 String )、List、Map,用法同理。

需要注意:List 和 Map 中的所有元素必须是 AIDL 支持的类型,List 支持泛型,Map 不支持泛型。

        本文将介绍使用 AIDL 实现自定义 User 对象间的传递,User 包含 name(String)和 age(int)2个属性。

        本文全部代码见→使用AIDL实现进程间传递对象案例

2 项目结构

        注意事项:

  • User.java 和 User.aidl 的包名必须一致
  • aidl_C 和 aidl_S 下的 User.java 文件内容必须一致
  • aidl_C 和 aidl_S 下的 aidl 文件及其包名必须一致

3 服务端 aidl_s 代码

        (1)传输类定义

        User.java

  1. package commu;
  2. import android.os.Parcel;
  3. import android.os.Parcelable;
  4. public class User implements Parcelable{
  5. private String name;
  6. private int age;
  7. public User(String name, int age) {
  8. this.name = name;
  9. this.age = age;
  10. }
  11. protected User(Parcel in) {
  12. name = in.readString();
  13. age = in.readInt();
  14. }
  15. public static final Creator<User> CREATOR = new Creator<User>() {
  16. @Override
  17. public User createFromParcel(Parcel in) {
  18. return new User(in);
  19. }
  20. @Override
  21. public User[] newArray(int size) {
  22. return new User[size];
  23. }
  24. };
  25. @Override
  26. public int describeContents() {
  27. return 0;
  28. }
  29. @Override
  30. public void writeToParcel(Parcel dest, int flags) {
  31. dest.writeString(name);
  32. dest.writeInt(age);
  33. }
  34. public String getName() {
  35. return name;
  36. }
  37. public int getAge() {
  38. return age;
  39. }
  40. @Override
  41. public String toString() {
  42. return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
  43. }
  44. }

        (2)传输类声明

        User.aidl

  1. package commu;
  2. parcelable User;

        注意: 声明 parcelable,不是 Parcelable

        (3)通讯接口

        MessageManager.aidl

  1. package commu;
  2. import commu.User;
  3. interface MessageManager {
  4. void sendMsg(in User user);
  5. User getMsg();
  6. }

        (4)服务

        MyService.java

  1. package com.zhyan8.aidl_s;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.os.RemoteException;
  6. import android.util.Log;
  7. import commu.MessageManager;
  8. import commu.User;
  9. public class MyService extends Service {
  10. @Override
  11. public IBinder onBind(Intent intent) {
  12. return mBind;
  13. }
  14. MessageManager.Stub mBind = new MessageManager.Stub() {
  15. @Override
  16. public void sendMsg(User user) throws RemoteException {
  17. Log.d("MyService", "客户端发来消息: " + user.toString());
  18. System.out.println(user.toString());
  19. }
  20. @Override
  21. public User getMsg() throws RemoteException {
  22. return new User("小红",23); //客户端待接收的消息
  23. }
  24. };
  25. }

        (5)注册服务

        在 AndroidManifest.xml 文件中 application 节点下注册 service,如下。

  1. <service
  2. android:name=".MyService"
  3. android:enabled="true"
  4. android:exported="true">
  5. <intent-filter>
  6. <action android:name="com.xxx.aidl"/>
  7. </intent-filter>
  8. </service>

        (6)主Acitvity

        MainActivity.java

  1. package com.zhyan8.aidl_s;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. public class MainActivity extends AppCompatActivity {
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. }
  10. }

4 客户端 aidl_c 代码

        (1)复制 User 类及 aidl 文件

        将 aidl_S 中 java 和 aidl 目录下的 commu 包及其中的 aidl 文件(User.aidl、MessageManager.aidl) 和 User.java 文件复制到 aidl_C 中相应目录下,见第2节中项目结构图 。

        (2)布局

        activity_main.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:paddingBottom="@dimen/activity_vertical_margin"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. android:orientation="vertical"
  11. tools:context="com.zhyan8.aidl_c.MainActivity">
  12. <LinearLayout
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:orientation="horizontal">
  16. <TextView
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"
  19. android:text="姓名:"
  20. android:textSize="30sp"/>
  21. <EditText
  22. android:id="@+id/et_name"
  23. android:layout_width="match_parent"
  24. android:layout_height="40dp"
  25. android:textSize="30sp"
  26. android:background="#ffcc66"/>
  27. </LinearLayout>
  28. <LinearLayout
  29. android:layout_width="match_parent"
  30. android:layout_height="wrap_content"
  31. android:orientation="horizontal"
  32. android:layout_marginTop="20dp">
  33. <TextView
  34. android:layout_width="wrap_content"
  35. android:layout_height="wrap_content"
  36. android:text="年龄:"
  37. android:textSize="30sp"/>
  38. <EditText
  39. android:id="@+id/et_age"
  40. android:layout_width="match_parent"
  41. android:layout_height="40dp"
  42. android:textSize="30sp"
  43. android:inputType="number"
  44. android:background="#ffcc66"/>
  45. </LinearLayout>
  46. <Button
  47. android:id="@+id/btn_send"
  48. android:layout_width="match_parent"
  49. android:layout_height="80dp"
  50. android:text="发送"
  51. android:textSize="30sp"
  52. android:layout_marginTop="30dp"/>
  53. <LinearLayout
  54. android:layout_width="match_parent"
  55. android:layout_height="wrap_content"
  56. android:orientation="horizontal"
  57. android:layout_marginTop="50dp">
  58. <TextView
  59. android:layout_width="wrap_content"
  60. android:layout_height="wrap_content"
  61. android:text="姓名:"
  62. android:textSize="30sp"/>
  63. <TextView
  64. android:id="@+id/tv_name"
  65. android:layout_width="match_parent"
  66. android:layout_height="40dp"
  67. android:textSize="30sp"
  68. android:background="#ffcc66"/>
  69. </LinearLayout>
  70. <LinearLayout
  71. android:layout_width="match_parent"
  72. android:layout_height="wrap_content"
  73. android:orientation="horizontal"
  74. android:layout_marginTop="20dp">
  75. <TextView
  76. android:layout_width="wrap_content"
  77. android:layout_height="wrap_content"
  78. android:text="年龄:"
  79. android:textSize="30sp"/>
  80. <TextView
  81. android:id="@+id/tv_age"
  82. android:layout_width="match_parent"
  83. android:layout_height="40dp"
  84. android:textSize="30sp"
  85. android:background="#ffcc66"/>
  86. </LinearLayout>
  87. <Button
  88. android:id="@+id/btn_recv"
  89. android:layout_width="match_parent"
  90. android:layout_height="80dp"
  91. android:text="接收"
  92. android:textSize="30sp"
  93. android:layout_marginTop="30dp"/>
  94. </LinearLayout>

        界面如下:

        (3)主Activity

        MainActivity.java

  1. package com.zhyan8.aidl_c;
  2. import android.app.Activity;
  3. import android.content.ComponentName;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.ServiceConnection;
  7. import android.os.Bundle;
  8. import android.os.IBinder;
  9. import android.os.RemoteException;
  10. import android.support.v7.app.AppCompatActivity;
  11. import android.view.View;
  12. import android.view.inputmethod.InputMethodManager;
  13. import android.widget.Button;
  14. import android.widget.EditText;
  15. import android.widget.TextView;
  16. import android.widget.Toast;
  17. import commu.MessageManager;
  18. import commu.User;
  19. public class MainActivity extends AppCompatActivity {
  20. private MessageManager mMessageManager;
  21. private EditText et_name;
  22. private EditText et_age;
  23. private Button btn_send;
  24. private TextView tv_name;
  25. private TextView tv_age;
  26. private Button btn_recv;
  27. @Override
  28. protected void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.activity_main);
  31. init();
  32. }
  33. public void init() {
  34. et_name = (EditText) findViewById(R.id.et_name);
  35. et_age = (EditText) findViewById(R.id.et_age);
  36. btn_send = (Button) findViewById(R.id.btn_send);
  37. tv_name = (TextView) findViewById(R.id.tv_name);
  38. tv_age = (TextView) findViewById(R.id.tv_age);
  39. btn_recv = (Button) findViewById(R.id.btn_recv);
  40. btn_send.setOnClickListener(cl);
  41. btn_recv.setOnClickListener(cl);
  42. }
  43. View.OnClickListener cl = new View.OnClickListener(){
  44. @Override
  45. public void onClick(View v) {
  46. hideInputMethod(MainActivity.this, v); //关闭输入法
  47. if (v.getId()==R.id.btn_send) {
  48. try {
  49. String name_t = et_name.getText().toString();
  50. int age_t = Integer.parseInt(et_age.getText().toString());
  51. User user = new User(name_t, age_t);
  52. sendMsg(user);
  53. } catch (Exception e) {
  54. Toast.makeText(MainActivity.this, "请输入姓名和年龄", Toast.LENGTH_SHORT).show();
  55. }
  56. }else if(v.getId()==R.id.btn_recv) {
  57. User user = getMsg();
  58. tv_name.setText(user.getName());
  59. tv_age.setText("" + user.getAge());
  60. }
  61. }
  62. };
  63. private void sendMsg(User user){
  64. if (mMessageManager==null) {
  65. attemptToBindService();
  66. }
  67. try {
  68. mMessageManager.sendMsg(user);
  69. } catch (RemoteException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. private User getMsg(){
  74. if (mMessageManager==null) {
  75. attemptToBindService();
  76. }
  77. try {
  78. User user = mMessageManager.getMsg();
  79. return user;
  80. } catch (RemoteException e) {
  81. e.printStackTrace();
  82. }
  83. return null;
  84. }
  85. private void attemptToBindService() {
  86. Intent intent = new Intent();
  87. intent.setAction("com.xxx.aidl");
  88. intent.setPackage("com.zhyan8.aidl_s");
  89. bindService(intent, conn, Context.BIND_AUTO_CREATE);
  90. }
  91. ServiceConnection conn = new ServiceConnection() {
  92. @Override
  93. public void onServiceConnected(ComponentName name, IBinder service) {
  94. mMessageManager = MessageManager.Stub.asInterface(service);
  95. }
  96. @Override
  97. public void onServiceDisconnected(ComponentName name) {
  98. mMessageManager = null;
  99. }
  100. };
  101. private void hideInputMethod(Activity act, View v) { //关闭输入法
  102. InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE);
  103. imm.hideSoftInputFromWindow(v.getWindowToken(),0);
  104. }
  105. @Override
  106. protected void onStart() {
  107. super.onStart();
  108. if (mMessageManager==null) {
  109. attemptToBindService();
  110. }
  111. }
  112. @Override
  113. protected void onStop() {
  114. super.onStop();
  115. if (mMessageManager!=null) {
  116. unbindService(conn);
  117. }
  118. }
  119. }

5 效果展示

        (1)发送消息

        在2个 EditView 中分别输入::小明、20,点击【发送】按钮,在服务端可以收到发送的消息,如下。

        (2)接收消息

        点击【接收】按钮,客户端 aidl_C 界面可以看到服务端 aidl_S 传过来的 user 信息,如下。

 6 附件

        以下是点击【Make Build】后自动生成的代码,路径为【aild_C\build\generated\source\aidl\debug\commu\ 】

        MessageManager.java

  1. package commu;
  2. public interface MessageManager extends android.os.IInterface {
  3. public static class Default implements commu.MessageManager {
  4. @Override
  5. public void sendMsg(commu.User user) throws android.os.RemoteException {
  6. }
  7. @Override
  8. public commu.User getMsg() throws android.os.RemoteException {
  9. return null;
  10. }
  11. @Override
  12. public android.os.IBinder asBinder() {
  13. return null;
  14. }
  15. }
  16. public static abstract class Stub extends android.os.Binder implements commu.MessageManager {
  17. private static final java.lang.String DESCRIPTOR = "commu.MessageManager";
  18. public Stub() {
  19. this.attachInterface(this, DESCRIPTOR);
  20. }
  21. public static commu.MessageManager asInterface(android.os.IBinder obj) {
  22. if ((obj == null)) {
  23. return null;
  24. }
  25. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  26. if (((iin != null) && (iin instanceof commu.MessageManager))) {
  27. return ((commu.MessageManager) iin);
  28. }
  29. return new commu.MessageManager.Stub.Proxy(obj);
  30. }
  31. @Override
  32. public android.os.IBinder asBinder() {
  33. return this;
  34. }
  35. @Override
  36. public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
  37. java.lang.String descriptor = DESCRIPTOR;
  38. switch (code) {
  39. case INTERFACE_TRANSACTION: {
  40. reply.writeString(descriptor);
  41. return true;
  42. }
  43. case TRANSACTION_sendMsg: {
  44. data.enforceInterface(descriptor);
  45. commu.User _arg0;
  46. if ((0 != data.readInt())) {
  47. _arg0 = commu.User.CREATOR.createFromParcel(data);
  48. } else {
  49. _arg0 = null;
  50. }
  51. this.sendMsg(_arg0);
  52. reply.writeNoException();
  53. return true;
  54. }
  55. case TRANSACTION_getMsg: {
  56. data.enforceInterface(descriptor);
  57. commu.User _result = this.getMsg();
  58. reply.writeNoException();
  59. if ((_result != null)) {
  60. reply.writeInt(1);
  61. _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
  62. } else {
  63. reply.writeInt(0);
  64. }
  65. return true;
  66. }
  67. default: {
  68. return super.onTransact(code, data, reply, flags);
  69. }
  70. }
  71. }
  72. private static class Proxy implements commu.MessageManager {
  73. private android.os.IBinder mRemote;
  74. Proxy(android.os.IBinder remote) {
  75. mRemote = remote;
  76. }
  77. @Override
  78. public android.os.IBinder asBinder() {
  79. return mRemote;
  80. }
  81. public java.lang.String getInterfaceDescriptor() {
  82. return DESCRIPTOR;
  83. }
  84. @Override
  85. public void sendMsg(commu.User user) throws android.os.RemoteException {
  86. android.os.Parcel _data = android.os.Parcel.obtain();
  87. android.os.Parcel _reply = android.os.Parcel.obtain();
  88. try {
  89. _data.writeInterfaceToken(DESCRIPTOR);
  90. if ((user != null)) {
  91. _data.writeInt(1);
  92. user.writeToParcel(_data, 0);
  93. } else {
  94. _data.writeInt(0);
  95. }
  96. boolean _status = mRemote.transact(Stub.TRANSACTION_sendMsg, _data, _reply, 0);
  97. if (!_status && getDefaultImpl() != null) {
  98. getDefaultImpl().sendMsg(user);
  99. return;
  100. }
  101. _reply.readException();
  102. } finally {
  103. _reply.recycle();
  104. _data.recycle();
  105. }
  106. }
  107. @Override
  108. public commu.User getMsg() throws android.os.RemoteException {
  109. android.os.Parcel _data = android.os.Parcel.obtain();
  110. android.os.Parcel _reply = android.os.Parcel.obtain();
  111. commu.User _result;
  112. try {
  113. _data.writeInterfaceToken(DESCRIPTOR);
  114. boolean _status = mRemote.transact(Stub.TRANSACTION_getMsg, _data, _reply, 0);
  115. if (!_status && getDefaultImpl() != null) {
  116. return getDefaultImpl().getMsg();
  117. }
  118. _reply.readException();
  119. if ((0 != _reply.readInt())) {
  120. _result = commu.User.CREATOR.createFromParcel(_reply);
  121. } else {
  122. _result = null;
  123. }
  124. } finally {
  125. _reply.recycle();
  126. _data.recycle();
  127. }
  128. return _result;
  129. }
  130. public static commu.MessageManager sDefaultImpl;
  131. }
  132. static final int TRANSACTION_sendMsg = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  133. static final int TRANSACTION_getMsg = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
  134. public static boolean setDefaultImpl(commu.MessageManager impl) {
  135. if (Stub.Proxy.sDefaultImpl == null && impl != null) {
  136. Stub.Proxy.sDefaultImpl = impl;
  137. return true;
  138. }
  139. return false;
  140. }
  141. public static commu.MessageManager getDefaultImpl() {
  142. return Stub.Proxy.sDefaultImpl;
  143. }
  144. }
  145. public void sendMsg(commu.User user) throws android.os.RemoteException;
  146. public commu.User getMsg() throws android.os.RemoteException;
  147. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/245312
推荐阅读
相关标签
  

闽ICP备14008679号