频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
Android AIDL传递对象数据
2017-09-12 10:37:17      个评论    来源:saviour的博客  
收藏   我要投稿

AIDL (Android Interface definition language)是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口

ICP :interprocess communication :内部进程通信;

AIDL 其实大家并不陌生,应用里面应用场景很多,如一键分享功能,将数据分享到第三方平台,这都需要用到跨进程通信,这里我主要介绍如何用AIDL传递对象型数据;

这里需要创建两个moudle ,一个用来模拟服务应用(被调用方),一个用来模拟客户应用(调用方),这里我使用的是 Android studio IDE , 在mian 文件夹下创建 aidl 文件夹,在里面创建两个 adil 文件, 一个是 提供服务的aidl 文件,另一个是 自定义的对象aidl 文件,另外再在里面创建一个 对象文件,bean类,你可以把这个java文件直接

放在aidl 文件夹下,也可以放在java 文件夹下(不过必须确保所在包名和 aidl文件的包名一致),然后把aidl 目录还有java bean 文件直接复制到 客户端(client moudle)相同的位置,结构图如下:

\ \

直接上文件代码了;

IMsg.aidl
// IMsg.aidl
package com.example.server;

// Declare any non-default types here with import statements
import com.example.server.User;

interface IMsg {

/*如果传递自定义对象, 必须加上 in , out ,inout 修饰符之一;
  意思如下: in 表示从客户端向服务端传递数据 
           out 表示从服务端向客户端传递数据
           inout 则表示双向都可以传递
*/

    void sendMsg(in User user);
}
User.aidl
//User.aidl
package com.example.server;

// Declare any non-default types here with import statements

parcelable User;

User.java

这里要注意一下,如果你用到 out 修饰符,需要在 User.java 里面添加 readFromParcel(Parcel source);方法,如果不手动添加, IMsg.java 文件会报错;

package com.example.server;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

/**
 * Created by JR on 2017/8/28.
 */

public class User implements Parcelable {

    public String name;
    public int age;
    private static final String TAG = "Main";

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }


    public static final Creator CREATOR = new Creator() {
        @Override
        public User createFromParcel(Parcel in) {
            //Log.d(TAG, "client: --------"+in.readString()+"-------------"+in.readInt());
            //这里需要注意, in.readXXX();方法执行完后,IMsg.java 文件里面会执行 recycle();操作,就是清空数据
            //如果数据被清空,你的服务里面就收不到 传递的数据,服务里面会接收到一个空对象 User={"name"= null,"age" = 0};
           return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    public User(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.age);
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
同步编译一下,会在build 目录下生成对应的 IMsg.java 接口文件

\

在 server 端创建一个 服务;

RemoteService.java
package com.example.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;


/**
 * Created by JR on 2017/8/28.
 */

public class RemoteService extends Service {

    private static final String TAG = "MainActivity";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ------------------服务开启");
    }

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

    class MyBinder extends IMsg.Stub {

        @Override
        public void sendMsg(User user) throws RemoteException {
            Log.d(TAG, "user:" + user.toString());
        }
    }
}
在服务端的manifiest文件里面注册服务,并添加一个action;

            
                
            
        
上面 服务端的就配置完成了,接下来开始配置 客户端;
客户端MainActivity.java
package com.example.jr.myaidl;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;

import com.example.server.IMsg;
import com.example.server.User;

public class MainActivity extends Activity {

    public static final String SERVICE_PACKAGE_NAME = "com.example.server";//远程服务所在包名
    public static final String SERVICE_REFERENCE_NAME = "com.example.server.RemoteService";//远程服务全名
    private IMsg iMsg;
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void bind(View v) {
            Intent intent = new Intent();
            intent.setAction("remote");//对应 服务端service 的action
            intent.setComponent(new ComponentName(SERVICE_PACKAGE_NAME,SERVICE_REFERENCE_NAME));
            bindService(intent,connection,BIND_AUTO_CREATE);
            Log.d(TAG, "bind: ------------------"+"绑定成功");
    }

    public void unbind(View v){
        unbindService(connection);
        Log.d(TAG, "unbind: -----------------------解除绑定");
    }

    public void send(View v){
        try {
            iMsg.sendMsg(new User("张三",18));
            Log.d(TAG, "send: --------------------发送信息.....");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMsg = IMsg.Stub.asInterface(service);
            Log.d(TAG, "onServiceConnected: ------------链接成功");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            iMsg = null;
            Log.d(TAG, "onServiceDisconnected: ----------------链接断开");
        }
    };
}
接下里就是测试了,先将server 服务端运行起来,再运行客户端client (必须保证服务运行),在客户端先连接服务端,再发送数据,服务端就能收到数据了.如果想从服务端拿数据,就用 out 修饰符,加上 IMsg.java 里面提示的方法,运行起来,就可以了,就介绍到这里!
点击复制链接 与好友分享!回本站首页
上一篇:Android布局优化:优化布局层级
下一篇:Android面试——AsyncTask
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训

版权所有: 红黑联盟--致力于做实用的IT技术学习网站