Android——使用AIDL实现进程间传递对象案例
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
package commu;import android.os.Parcel;import android.os.Parcelable;public class User implements Parcelable{ private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } protected User(Parcel in) { name = in.readString(); age = in.readInt(); } public static final Creator CREATOR = new Creator() { @Override public User createFromParcel(Parcel in) { return new User(in); } @Override public User[] newArray(int size) { return new User[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
(2)传输类声明
User.aidl
package commu;parcelable User;
注意: 声明 parcelable,不是 Parcelable
(3)通讯接口
MessageManager.aidl
package commu;import commu.User;interface MessageManager { void sendMsg(in User user); User getMsg();}
(4)服务
MyService.java
package com.zhyan8.aidl_s;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;import commu.MessageManager;import commu.User;public class MyService extends Service { @Override public IBinder onBind(Intent intent) { return mBind; } MessageManager.Stub mBind = new MessageManager.Stub() { @Override public void sendMsg(User user) throws RemoteException { Log.d("MyService", "客户端发来消息: " + user.toString()); System.out.println(user.toString()); } @Override public User getMsg() throws RemoteException { return new User("小红",23); //客户端待接收的消息 } };}
(5)注册服务
在 AndroidManifest.xml 文件中 application 节点下注册 service,如下。
(6)主Acitvity
MainActivity.java
package com.zhyan8.aidl_s;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
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
<?xml version="1.0" encoding="utf-8"?>
界面如下:
(3)主Activity
MainActivity.java
package com.zhyan8.aidl_c;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.view.inputmethod.InputMethodManager;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import commu.MessageManager;import commu.User;public class MainActivity extends AppCompatActivity { private MessageManager mMessageManager; private EditText et_name; private EditText et_age; private Button btn_send; private TextView tv_name; private TextView tv_age; private Button btn_recv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } public void init() { et_name = (EditText) findViewById(R.id.et_name); et_age = (EditText) findViewById(R.id.et_age); btn_send = (Button) findViewById(R.id.btn_send); tv_name = (TextView) findViewById(R.id.tv_name); tv_age = (TextView) findViewById(R.id.tv_age); btn_recv = (Button) findViewById(R.id.btn_recv); btn_send.setOnClickListener(cl); btn_recv.setOnClickListener(cl); } View.OnClickListener cl = new View.OnClickListener(){ @Override public void onClick(View v) { hideInputMethod(MainActivity.this, v); //关闭输入法 if (v.getId()==R.id.btn_send) { try { String name_t = et_name.getText().toString(); int age_t = Integer.parseInt(et_age.getText().toString()); User user = new User(name_t, age_t); sendMsg(user); } catch (Exception e) { Toast.makeText(MainActivity.this, "请输入姓名和年龄", Toast.LENGTH_SHORT).show(); } }else if(v.getId()==R.id.btn_recv) { User user = getMsg(); tv_name.setText(user.getName()); tv_age.setText("" + user.getAge()); } } }; private void sendMsg(User user){ if (mMessageManager==null) { attemptToBindService(); } try { mMessageManager.sendMsg(user); } catch (RemoteException e) { e.printStackTrace(); } } private User getMsg(){ if (mMessageManager==null) { attemptToBindService(); } try { User user = mMessageManager.getMsg(); return user; } catch (RemoteException e) { e.printStackTrace(); } return null; } private void attemptToBindService() { Intent intent = new Intent(); intent.setAction("com.xxx.aidl"); intent.setPackage("com.zhyan8.aidl_s"); bindService(intent, conn, Context.BIND_AUTO_CREATE); } ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mMessageManager = MessageManager.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mMessageManager = null; } }; private void hideInputMethod(Activity act, View v) { //关闭输入法 InputMethodManager imm = (InputMethodManager) act.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(),0); } @Override protected void onStart() { super.onStart(); if (mMessageManager==null) { attemptToBindService(); } } @Override protected void onStop() { super.onStop(); if (mMessageManager!=null) { unbindService(conn); } }}
5 效果展示
(1)发送消息
在2个 EditView 中分别输入::小明、20,点击【发送】按钮,在服务端可以收到发送的消息,如下。
(2)接收消息
点击【接收】按钮,客户端 aidl_C 界面可以看到服务端 aidl_S 传过来的 user 信息,如下。
更多相关文章
- eclipse 上调试android的自带应用方法 一
- android 增加新按键
- Android(安卓)USB OTG U盘读写相关使用最全总结
- Android(安卓)Activity与Service通信
- Android(安卓)Repo的manifest XML文件格式
- 动态加载Dex的原理
- (Android)为什么我们不需要导入android support v4包?
- android点滴(26)之让线程拥有自己的消息循环
- Android入门:查看服务器图片应用