AndroidStudio中使用AIDL实现进程间通信

最近在学习Android开发,学到了使用AIDL进行Android的进程间通信,网上找了些视频资料看了下,都是基于eclipse的,而我使用的是AndroidStudio,那么在AndroidStudio中该如何实现呢?我参考了这哥们的文章,基本实现了两个app之间的通信,下面来看具体实现.

新建了三个module,分别是:aidlmodels(放序列化model的,项目类型为Android Library),aidlservice(远程service),app(调用者)


aidlmodels Module

 先创建aidl文件,然后创建实体类.
右键选中项目-->New-->AIDL-->AIDL File,新建一个aidl文件,我的文件命名为person.这时AndroidStudio就为我们创建好了一个aidl文件夹,里面有我们刚创建的aidl文件

在person.aidl中定义好要创建的实体类.
person.aidl:
// person.aidl
package com.my.open.aidlmodels;
parcelable person;
里面的 parcelable person中的person就是我们要创建的实体类,用于序列化后再进程间传输.

在main-->java中创建person 实体类:
person.java:
package com.my.open.aidlmodels;


import android.os.Parcel;
import android.os.Parcelable;



public class person implements Parcelable {

    private String name;
    //0:男,1:女
    private int sex;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    private String hobby;

    protected person(Parcel in) {
        this.name=in.readString();
        this.sex=in.readInt();
        this.age=in.readInt();
        this.hobby=in.readString();

    }

    public person()
    {

    }

    public static final Creator<person> CREATOR = new Creator<person>() {
        @Override
        public person createFromParcel(Parcel in) {
            return new person(in);
        }

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.sex);
        dest.writeInt(this.age);
        dest.writeString(this.hobby);
    }
}
model类需实现的Parcelable接口
注意:person.java类的包名要和person.aidl的包名相同

最后工程目录结构:


这时,选中工程,按下Ctrl+F9,编译生成一下.


aidlservice Module
先添加对aidlmodels项目的引用,在aidlservice Module的build.gradle文件中添加对aidlmodels项目的引用:

然后同步一下.
远程服务具体要实现哪些功能,我们把这些功能定义在一个接口中,右键选中项目-->New-->AIDL-->AIDL File,新建一个aidl文件,我的文件命名为IPersonActive.aidl
// IPersonActive.aidl
package com.my.open.aidlservice;
import com.my.open.aidlmodels.person;
// Declare any non-default types here with import statements

interface IPersonActive {
    person addPerson(String name,int sex,int age,String hobby);
    person getPerson(String name);
    boolean deletePerson(String name);
}
我定义了几个简单的方法,下一步我们在aidl文件夹下创建一个包,包名和aidlmodels项目中的person.aidl所在的包名相同,把person.aidl文件拷贝到此包下.现在选中项目,按下Ctrl+F9编译一下,应该就可以看到AndroidStudio为我们 生成的IPersonActive文件


接下来就是定义service了,文件如下
package com.my.open.aidlservice;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;

import com.my.open.aidlmodels.person;

import java.util.HashMap;
import java.util.Map;



public class myRemoteService extends Service {
    private Map<String,person> personMap;
    //IPersonActive接口的具体实现
    private class myPersonBinder extends IPersonActive.Stub{

        @Override
        public person addPerson(String name, int sex, int age, String hobby) throws RemoteException {
            if (personMap.keySet().contains(name))
            {
                return null;
            }
            person _person= new person();
            _person.setName(name);
            _person.setSex(sex);
            _person.setAge(age);
            _person.setHobby(hobby);
            personMap.put(name,_person);
            return _person;
        }

        @Override
        public person getPerson(String name) throws RemoteException {
            return personMap.get(name);
        }

        @Override
        public boolean deletePerson(String name) throws RemoteException {
            return null!=personMap.remove(name)?true:false;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        personMap=new HashMap<String,person>();
    }

    @Override
    public int onStartCommand(Intent intent,int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new myPersonBinder();
    }
}
别忘了在AndroidManifest.xml文件中定义好service
aidlservice module项目结构:
app Module
先在app module的build.gradle文件中添加对aidlmodels module的引用.
接下来,同前面一样,新建一个aidl文件夹,将aidlmodels models中的person.aidl文件和aidlservice module中的IPersonActive.aidl文件拷贝到app Module的aidl文件夹下,各个aidl文件的包名也要和它们在原module中的包名相同.
然后按Ctrl+F9编译一下.
接下来就是客户端的具体实现了,App module 的MainActivity.java文件如下:

package com.my.open.ipcdemo;

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.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import com.my.open.aidlmodels.person;
import com.my.open.aidlservice.IPersonActive;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            System.out.println("Service is Connected.....");
            remoteService = IPersonActive.Stub.asInterface(service);
            isBind = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            System.out.println("service is Disconnected.........");
            isBind = false;
        }
    };
    private IPersonActive remoteService;
    private EditText etName;
    private Spinner spSex;
    private EditText etAge;
    private EditText etHobby;
    private Intent _intent;
    private boolean isBind = false;

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

        etName = (EditText) findViewById(R.id.etName);
        spSex = (Spinner) findViewById(R.id.spSex);
        etAge = (EditText) findViewById(R.id.etAge);
        etHobby = (EditText) findViewById(R.id.etHobby);
        Button btnBindService = (Button) findViewById(R.id.btnBindService);
        Button btnUnBindService = (Button) findViewById(R.id.btnUnBindService);
        Button btnAdd = (Button) findViewById(R.id.btnAdd);
        Button btnDel = (Button) findViewById(R.id.btnDel);
        Button btnQuery = (Button) findViewById(R.id.btnQuery);

        btnBindService.setOnClickListener(this);
        btnUnBindService.setOnClickListener(this);
        btnAdd.setOnClickListener(this);
        btnDel.setOnClickListener(this);
        btnQuery.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.btnBindService:
                _intent = new Intent();
                _intent.setAction("com.my.open.aidlservice");
                bindService(_intent, conn, Context.BIND_AUTO_CREATE);
                break;
            case R.id.btnUnBindService:
                if (isBind)
                {
                    unbindService(conn);
                    isBind = false;
                }else
                    Toast.makeText(this, "服务未绑定,无需解绑", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btnAdd:
                addPersonToService();
                break;
            case R.id.btnDel:
                delPersonFromService();
                break;
            case R.id.btnQuery:
                queryPersonFromService();
                break;

            default:
                break;
        }
    }

    //根据EditView控件etName中输入的名称查找记录
    private void queryPersonFromService() {
        if (!isBind) {
            Toast.makeText(this, "远程服务没有绑定或被系统kill", Toast.LENGTH_SHORT).show();
            return;
        }
        String name = etName.getText().toString().trim();
        if (TextUtils.isEmpty(name)) {
            Toast.makeText(this, "姓名不能为空!", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            person _person = remoteService.getPerson(name);
            if (null != _person) {
                etAge.setText(String.valueOf(_person.getAge()));
                etHobby.setText(_person.getHobby());
                int position = _person.getSex();
                spSex.setSelection(position);
                Toast.makeText(this, "查询数据成功!", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "查询的记录不存在", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            Toast.makeText(this, "查询记录出现异常:" + e.getMessage(), Toast.LENGTH_SHORT).show();

        }
    }
    
    //根据EditView控件etName中输入的名称删除记录
private void delPersonFromService() { if (!isBind) { Toast.makeText(this, "远程服务没有绑定或被系统kill", Toast.LENGTH_SHORT).show(); return; } String name = etName.getText().toString().trim(); if (TextUtils.isEmpty(name)) { Toast.makeText(this, "姓名不能为空!", Toast.LENGTH_SHORT).show(); return; } try { boolean success=remoteService.deletePerson(name); if (success) { Toast.makeText(this, "删除数据成功!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "删除的记录不存在", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { Toast.makeText(this, "删除记录出现异常:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } } private void addPersonToService() { if (!isBind) { Toast.makeText(this, "远程服务没有绑定或被系统kill", Toast.LENGTH_SHORT).show(); return; } String name = etName.getText().toString().trim(); int sex = spSex.getSelectedItemPosition(); String strAge=etAge.getText().toString().trim(); int age = Integer.valueOf(strAge); String hobby = etHobby.getText().toString().trim(); if (TextUtils.isEmpty(name)) { Toast.makeText(this, "请输入姓名!", Toast.LENGTH_SHORT).show(); return; } try { person _person = remoteService.addPerson(name, sex, age, hobby); if (null==_person) { Toast.makeText(this, "姓名已存在,请更改", Toast.LENGTH_SHORT).show(); return; } etName.setText(""); spSex.setSelection(0); etAge.setText("0"); etHobby.setText(""); etName.requestFocus(); Toast.makeText(this, "新增数据成功!", Toast.LENGTH_SHORT).show(); } catch (Exception e) { Toast.makeText(this, "新增数据出现异常:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } }}



activity_main.xml布局文件如下(太丑了,demo就凑合着用)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.my.open.ipcdemo.MainActivity">

    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <Button android:id="@+id/btnBindService"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="绑定远程服务">
        </Button>
        <Button android:id="@+id/btnUnBindService"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="解除绑定">
        </Button>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="姓名"/>
            <EditText
                android:id="@+id/etName"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"/>
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="性别"/>
            <Spinner
                android:id="@+id/spSex"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:entries="@array/sex"></Spinner>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="年龄"/>
            <EditText
                android:id="@+id/etAge"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:inputType="number"
                android:text="0"/>
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="爱好"/>
            <EditText
                android:id="@+id/etHobby"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"/>
        </LinearLayout>
        <Button
            android:id="@+id/btnAdd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="保存"/>

        <Button
            android:id="@+id/btnDel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="删除"/>
        <Button
            android:id="@+id/btnQuery"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="查询"/>

    </LinearLayout>

</android.support.constraint.ConstraintLayout>

  性别下拉框的item resource定义在values目录的sex_item.xml文件中,内容如下
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="sex">
        <item>男</item>
        <item>女</item>
    </string-array>
</resources>
app module的项目结构:



由于本人刚接触Android开发,水平非常有限,所以这个demo还有不足之处,仅仅实现了最简单的进程间的通信,但也希望对那些刚刚接触AndroidStudio的同学们有帮助.
demo 下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值