Android进程间通信AIDL的demo

参考:

http://m.blog.csdn.net/article/details?id=51095169

http://blog.csdn.net/zjh1002492540/article/details/50750026

http://lib.csdn.net/article/android/31342

https://blog.csdn.net/ls5718/article/details/51854106 //binder机制的实现

https://blog.csdn.net/u010291868/article/details/73359890 //aidl和binder的区别

https://blog.csdn.net/qq_30379689/article/details/52253413 //博客文章也很不错

https://blog.csdn.net/jinxinliu1/article/details/70174591

https://blog.csdn.net/lb850747906/article/details/63683160

https://blog.csdn.net/codefly/article/details/17058607 //红茶一杯话Binder

https://segmentfault.com/a/1190000002982306 //java层binder进程间通信

 

Binder/AIDL学习起来还是蛮抽象的,还是要通过例子来加深理解,本文参照了几篇文章,在自己的平台上实现了一个简单的demo:两个数相加。

1、什么是Binder,什么是AIDL?

网上和书本上的介绍都很多,主要是为了实现进程间通信,可以参照下面的文章,

http://www.open-open.com/lib/view/open1464181227898.html

https://blog.csdn.net/codefly/article/details/17058607

 

2、Tool:Android Studio2.2.1 + Android5.1的手机

3、总结实现步骤:

1):建server端工程AidlServer,新建aidl文件,在接口里声明一个基本类型的API(实现两个数的加法)

2):建立MyService,实现接口的抽象类Stub(在Stub里定义/实现基本类型API)

3):将接口暴露给client,建立client端工程或module:逻辑实现启动连接远程服务,调服务里的基本类型API

4、具体过程:

AidlServer端

A:建立project:AidlExample,在这个project下面分别NeW->Module,建立两个module:AidlServer和AidlClient。

 

B:aidlserver端,新建aidl文件,在接口里声明一个基本类型的API,Build->make project会生成相应的java 文件。

B1:右键java文件夹,New->AIDL->AIDL File,输入interface name,Finish,生成aidl文件夹和相应的aidl文件。

B2:定义想要的API,比如实现两个数的加法,基本类型的API:int add(in int x,in int y),并将已有的basicTypes mark掉。

IMyAidlInterface.aidl文件的内容:

 

// IMyAidlInterface.aidl
package example.com.aidlserver;

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

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    //void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            //double aDouble, String aString);

     int add(in int x, in int y);
}

 

B3:Build->make project,会再在build->generated->source->aidl->debug下面生成对应aidl的java文件。

IMyAidlInterface.java文件的内容:

 

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file:\AndroidStudioProjects\\AidlExample\\aidlserver\\src\\main\\aidl\\example\\com\\aidlserver\\IMyAidlInterface.aidl
 */
package example.com.aidlserver;
// Declare any non-default types here with import statements

public interface IMyAidlInterface extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements example.com.aidlserver.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "example.com.aidlserver.IMyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an example.com.aidlserver.IMyAidlInterface interface,
 * generating a proxy if needed.
 */
public static example.com.aidlserver.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof example.com.aidlserver.IMyAidlInterface))) {
return ((example.com.aidlserver.IMyAidlInterface)iin);
}
return new example.com.aidlserver.IMyAidlInterface.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_add:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
int _result = this.add(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements example.com.aidlserver.IMyAidlInterface
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public int add(int x, int y) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(x);
_data.writeInt(y);
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int add(int x, int y) throws android.os.RemoteException;
}

C:aidlserver端建立MyService,实现aidl文件里Stub接口和基本类型API。

MainActivity端右键New->Service->Service,输入Class name,Finish.

MyService.java文件内容:

 

package example.com.aidlserver;

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

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        //throw new UnsupportedOperationException("Not yet implemented");
        return mBinder;
    }

    private IBinder mBinder = new IMyAidlInterface.Stub() {
        @Override
        public int add(int x, int y) throws RemoteException {
            return x + y;
        }
    };}}

D:AndroidManifest.xml文件里要配置action,用包名+service。

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="example.com.aidlserver">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="example.com.aidlserver.MyService"/>
            </intent-filter>
        </service>
    </application>

</manifest>


AidlClient端

 

E:将aidlserver->src->main下面的aidl文件夹copy到aidlclient->src->mian下面,保证server和Client的package名和aidl文件一致。

F:修改aidlclient的布局文件:activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="example.com.aidlclient.MainActivity">

    <EditText
        android:id="@+id/num1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入数字" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="+" />

    <EditText
        android:id="@+id/num2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入数字" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="=" />

    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/measure"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="AIDL 远 程计 算" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

 

G:修改aidlclient的逻辑文件MainActivity.java

 

在使用隐式开启服务的时候在5.0及以上版本默认是不能直接通过action开启的,使用意图的时候加上setpackage就可以解决.

package example.com.aidlclient;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import example.com.aidlserver.IMyAidlInterface;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private EditText num1,num2;
    private TextView result,text;
    private Button measure;
    private IMyAidlInterface iMyAidl;

    //连接远程服务
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iMyAidl = IMyAidlInterface.Stub.asInterface(service);
            Log.i("TAG", "bind service successful");
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            iMyAidl = null;
        }
    };

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

        num1 = (EditText) findViewById(R.id.num1);
        num2 = (EditText) findViewById(R.id.num2);
        measure = (Button) findViewById(R.id.measure);
        result = (TextView) findViewById(R.id.result);
        text = (TextView) findViewById(R.id.text);
        measure.setOnClickListener(this);
        bindService();
    }

    @Override
    public void onClick(View v) {
       try {
            int i = iMyAidl.add(Integer.parseInt(num1.getText().toString()),Integer.parseInt(num2.getText().toString()));
            result.setText("" + i);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private void bindService() {
        //使用意图对象绑定开启服务
        Intent intent = new Intent();
        intent.setAction("example.com.aidlserver.MyService");
        //在5.0及以上版本必须要加上这个
        intent.setPackage("example.com.aidlserver");
        bindService(intent,conn, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
}


H:在手机上运行看看,AidlServer.apk和AidlClient.apk都要安装到手机上。这个时候点开aidlclient端的APK界面:

 

输入两个数,运行结果如下:

I:至此client调service的demo完成,例子在手机上验证成功。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值