AIDL

144
作者 加贝龙
2015.09.10 11:42 字数 779

Android 进程间通信(IPC)之AIDL的认识


之前一直对进程间通信有印象,很模糊,不知道具体是什么,今天自习的研究了一下,所谓进程见通信就是两个Android应用程序之间的通信,Android官方给出的方案是AIDL(Android Interface Definition Language)。之前对此知识点也是很陌生,一直不知道怎么用的,今天就彻底的学习了一下怎么使用的,下面是个人的一些总结,最有一定的认识了,但是还是很基础,高级用法还是不怎么知道呢。

首先我们先创建一个AIDL文件,这个文件语法类似于Java,定义了自己需要的接口,若要在两个进程见通信,两个项目中必须有一模一样的AIDL文件,包括包名。

package com.helong.aidlserver;
interface IStudyService {
    //根据type返回学习的课程
   String studyClass(int type);
}

然后编译器会自动生成一个Java文件IStudyService.java

我们新建一个Service来实现这个studyClass方法,这样其他的应用程序就可以访问这个方法了。

package com.helong.aidlserver;

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

public class StudyService extends Service {
    public StudyService() {
    }
    @Override
    public IBinder onBind(Intent intent) {
        return new IStudyService.Stub() {
            @Override
            public String studyClass(int type) throws RemoteException {
                String studyClass = "";
                switch (type) {
                    case 0:
                        studyClass = "数学";
                        break;
                    case 1:
                        studyClass = "语文";
                        break;
                    default:
                        studyClass = "计算机";
                        break;
                }
                return studyClass;
            };
        };
    }
}

Service的其他方法因为这个小demo用不到我就不重写了

在清单文件中配置Service的时候添加上action,以便于外部通过Intent访问:

<service
    android:name=".StudyService"
    android:enabled="true"
    android:exported="true" >
    <intent-filter>
        <action android:name="com.helong.aidlserver.StudyService"/>
    </intent-filter>
</service>

暂且把这个项目叫做AIDL的服务端把,因为其他应用是调用这个Service。来看看客户端是怎么调用的把;

package com.helong.aidlclient;

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.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import com.helong.aidlserver.IStudyService;


public class MainActivity extends ActionBarActivity {

    IStudyService mStudyService;
    StudyServiceConnection mServiceConn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mServiceConn=new StudyServiceConnection();
        Intent intent=new Intent("com.helong.aidlserver.StudyService");
        //此行代码有待商量
        intent.setPackage("com.helong.aidlserver");
        bindService(intent, mServiceConn,BIND_AUTO_CREATE);
        findViewById(R.id.btn_study).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    String studyClass1 = mStudyService.studyClass(0);
                    String studyClass2 = mStudyService.studyClass(1);
                    Log.i("study", "client type=1:class=" + studyClass1 + " type=2:class=" + studyClass2);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    //实现ServiceConnection
    class StudyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mStudyService=IStudyService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mStudyService=null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConn);
        mServiceConn=null;
    }
}

看一下按下按钮后log打印信息:

client type=1:class=数学 type=2:class=语文

正是我们期待的结果,好啦,还有一点疑问就是我下午做这个小demo的时候,client绑定Serivce的时候intent不需要设置setPackage,但是现在做的时候却需要了,好像是5.0系统要求的

Android