android进程间通信(AIDL的实现)

AIDL (Android Interface Definition Language)

近期做了一个进程间通信的需求,这里总结一下。具体的需求是这样的:

B应用在详情页需要调起A应用的播放功能,但播放地址是必须在播放器页面再去获取的,但A应用不能调取B应用的请求,只能通过B应用中的请求拿到播放地址传给A应用,A然后进行播放。

  • 这里就需要用到进程间通信(icp:inter process communication:内部进程通信。)了。 业务逻辑大体如下:B在详情页点击播放的时候通过普通的Intent或者scheme方式调起A应用对应的activity,之后A应用会启动B中定义的service,然后通过aidl的方法传递请求参数数据到B中,B拿到请求参数后起线程获取播放地址,然后回传给A应用,A拿到播放地址后再进行播放。

流程图如下(B应用就叫main应用,A应用就叫lite应用):

Paste_Image.png
  • 下面是具体实现:
    1.先在main应用中建立对应的aidl文件,
Paste_Image.png

这样会在我们包名下建出aidl文件,这时,我们需要在build下重新make project一下,这样在build文件夹中就会生成对应的接口文件,如下图:

Paste_Image.png

这样,我们才能在代码中引用这个接口。

这时在IRemoteService.aidl文件中,还只是默认的方法,这里我们需要加上我们自己的方法,这个文件其实就是一个接口文件,所以我们只能写上方法的定义,具体的实现还得再接口的实现中完成。

在IRemoteService.aidl我们加上

/** 
 * @param couldId  视频id 
 * @param callback  获取playurl的回调 
 */String getPlayInfo(String couldId, LiteappCallback callback);

注意:上面方法中的参数LIteappCallback是又lite中需要传给main的回调类,我们需要再次建一个aidl文件,就叫LiteappCallback.aidl,代码如下:

// LiteappCallback.aidlpackage 
com.main.mainapplication;
// Declare any non-default types here with import statements

interface LiteappCallback {    
 /**     
* 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); 
//获取url成功   
void getPlayUrlSuccess(String playUrl);    
//获取url失败
void getPlayUrlFail(String message);
}

其中两个方法的具体实现在需要在lite应用中做的。
---别忘了添加aidl之后需要make project一下,否则你会发现在IRemoteService中用不了。这里还需要注意的是,在aidl中如果引用其他aidl接口类型,需要import,即使是在相同的包结构下。所以我们在IRemoteService的方法中引用LiteappCallback需要导包,在IRemoteService.aidl文件中加入import com.main.mainapplication.LiteappCallback;

至此,aidl基本定义完毕。

2.创建main中的service。
这里我们创建叫liteservice的服务,其中需要实现IRemoteService。

package com.main.mainapplication.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import com.main.mainapplication.IRemoteService;
import com.main.mainapplication.LiteappCallback;
/** 
* Date: 2016-04-15 
* Time: 12:58 
* Description: FIXME 
*/
public class LiteService extends Service{    
@Nullable    
@Override    
public IBinder onBind(Intent intent) { 
       return null;    
}   
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {        
@Override        
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {        }        
@Override        
public String getPlayInfo(String couldId, LiteappCallback callback) throws RemoteException {            
requestPlayUrl(couldId, callback);            
return "http://";        
}    
};    
private void requestPlayUrl(String couldId, LiteappCallback callback) {        //TODO 进行异步操作        
//在异步请求里如果成功执行callback.getPlayUrlSuccess(playurl);        //如果失败之执行callback.getPlayUrlFail(message);    
}
}

其中具体的异步请求就不写了,总之会回调callback的两个方法。由于是异步的处理,所以这里getPlayInfo方法的直接返回结果并没有什么卵用。
别忘了我们需要在main应用的清单文件中注册service:

<service android:name="com.main.mainapplication.service.LiteService">   
    <intent-filter>        
        <action android:name="com.main.mainapplication.intent.action.FORURL"/>    
    </intent-filter>
</service>

这里采用隐式的调起方式。

3.回到lite应用中
首先需要将main中创建的aidl文件copy到lite中,这里需要注意的是aidl的包名也一并copy过来:

Paste_Image.png

同样需要make project生成对应接口文件。
由于只是事例代码,所以我就写在liteApplication的MainActivity中了,

private IRemoteService mRemoteService;

ServiceConnection conn = new ServiceConnection() {    
@Override    
public void onServiceConnected(ComponentName name, IBinder service) {        
mRemoteService = IRemoteService.Stub.asInterface(service);   
System.out.println("bind success" + mRemoteService.toString());    
}    
@Override    
public void onServiceDisconnected(ComponentName name) {    
}
};
private final LiteappCallback.Stub callback = new LiteappCallback.Stub() {    
@Override    
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {  
}    
@Override    
public void getPlayUrlSuccess(String playUrl) throws RemoteException {        
System.out.println("playUrl: " + playUrl);    
}    
@Override    
public void getPlayUrlFail(String message) throws RemoteException {        
System.out.println("message: " + message);    
}
};

这里是先创建ServiceConnection,并且实现LiteappCallback接口,getPlayUrlSuccess功能只是打印该url。这个方法会在main应用中的异步处理中调用。

这里就直接在mainactivity的oncreate方法中绑定服务了,场景不一样,需要另外处理:

Intent intent = new Intent("com.main.mainapplication.intent.action.FORURL");
intent.setPackage("com.main.mainapplication");
System.out.println("开始bind");
bindService(intent, conn, Context.BIND_AUTO_CREATE);

这里注意:Android 5.0一出来后,其中有个特性就是Service Intent must be explitict,也就是说从Lollipop开始,service服务必须采用显式意图方式启动.解决办法就是增加intent.setPackage("com.main.mainapplication");设置包名。才可以绑定service。然后在需要的地方直接调用getPlayInfo方法。

try {    
mRemoteService.getPlayInfo("23456789", callback);
} catch (RemoteException e) { 
e.printStackTrace();
}

此时,同一个手机上都装了main应用和lite应用后,main应用带数据到lite之后,lite通过绑定service,调用getPlayInfo方法,然后会在service中异步请求获取后调用了lite中的getPlayUrlSuccess方法后,成功在lite中拿到了main中请求的url数据,然后lite中再处理播放的逻辑。

至此,aidl实现基本完成。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容