Android 跨进程通信Aidl的使用及注意事项

Posted 独立开发者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 跨进程通信Aidl的使用及注意事项相关的知识,希望对你有一定的参考价值。

博客首发公众号地址:coolspan

前提

在其他进程开辟使用内存,不会影响当前App进程;进而,也会很大一部分避免App被垃圾回收机制回收;
QQ的网路通信使用的就是跨进程通讯。

创建Aidl接口文件

创建一个File,命名为:xxx.aidl;此处命名为:IIncrementUpdateServer.aidl,具体请看下图aidl文件所在位置:

创建完成后,如下所示:

IIncrementUpdateServer.aidl内容定义如下:

//此方法是创建aidl自带的方法,告知你可以使用那些数据类型
 void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

自定义的aidl接口,根据情况,定义跨进程所需接口:

    void start();
    void reload();
    void stop();

创建服务Service

创建service,此处命名为:IIncrementUpdateService,继承于Service,具体如下:

package cn.coolspan.open.android_increment_update.service;

import android.app.Service;

/**
 * Coolspan on 2016/7/5 00:00
 *
 * @author 乔晓松 965266509@qq.com
 */
public class IIncrementUpdateService extends Service 

    private PriorityBlockingQueue<Integer> mHotUpdateRequestQueue;

    @Override
    public void onCreate() 
        super.onCreate();
        //TODO:初始化启动服务后所需的数据
    

    @Nullable
    @Override
    public IBinder onBind(Intent intent) 
        return new IncreamentUpdateImpl();
    

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        if (intent != null) 
            Log.e("IncreamentUpdateImpl", "onStartCommand:" + intent.getDataString());
         else 
            //do nothing
        
        return super.onStartCommand(intent, flags, startId);
    

    private class IncreamentUpdateImpl extends IIncrementUpdateServer.Stub 

        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException 
            //do nothing
        

        @Override
        public void start() throws RemoteException 
            Log.e("IncreamentUpdateImpl", "start");
        

        @Override
        public void reload() throws RemoteException 
            Log.e("IncreamentUpdateImpl", "reload");
        

        @Override
        public void stop() throws RemoteException 
            Log.e("IncreamentUpdateImpl", "stop");
        
    

注意

onBind方法中,通过new实例化了一个IncreamentUpdateImpl实例对象,和Service进行绑定;IncreamentUpdateImpl继承于IIncrementUpdateServer.Stub;当然,你也可以直接实例化IIncrementUpdateServer.Stub进行绑定;

在AndroidManifest.xml中静态申明Service,如下:

    <service
        android:name=".service.IIncrementUpdateService"
        android:exported="true"
        android:process=":bspatch">
        <intent-filter>
            <action android:name="cn.coolspan.IncrementUpdateService" />
        </intent-filter>
    </service>    

注意:

action定义为:cn.coolspan.IncrementUpdateService,需和调用之处一致。

到此,Aidl与Service都定义完成;接着,就是如何使用。

使用方式

我是在Activity中进行调用的,如下:
首先,创建ServiceConnection获取到Service:

IIncrementUpdateServer mService;

private ServiceConnection mServiceConnection = new ServiceConnection() 

    @Override
    public void onServiceDisconnected(ComponentName name) 
        // TODO Auto-generated method stub
        Log.e("ServiceConnection", "disconnect service");
        mService = null;
    

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) 
        // TODO Auto-generated method stub
        Log.e("ServiceConnection", "connect service");
        mService = IIncrementUpdateServer.Stub.asInterface(service);
        try 
            if (mService != null)
                mService.start();
         catch (RemoteException e) 
            e.printStackTrace();
        
    
;

然后,绑定Service:

@Override
protected void onResume() 
    super.onResume();
    Bundle args = new Bundle();
    Intent intent = new Intent("cn.coolspan.IncrementUpdateService");
    //测试出现在高版本的系统会出现异常:Service Intent must be explicit
    //解决方式:就是指定Intent package
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
        intent.setPackage("cn.coolspan.open.android_increment_update");
    
    intent.putExtras(args);
    bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);    

解除绑定:

@Override
protected void onPause() 
    super.onPause();
    unbindService(mServiceConnection);

```java
最后调用:




<div class="se-preview-section-delimiter"></div>

```java
mService.start();

结果,就会输入Service中的Log信息。

connect service
start

遇到的坑

1、如果在onCreate中进行bindService,在Destroy中unBindService,当Activity暂停的时候就会出现以下异常信息

 Activity cn.coolspan.open.android_increment_update.MainActivity has leaked ServiceConnection cn.coolspan.open.android_increment_update.MainActivity$1@421de608 that was originally bound here
                                                                                           android.app.ServiceConnectionLeaked: Activity cn.coolspan.open.android_increment_update.MainActivity has leaked ServiceConnection cn.coolspan.open.android_increment_update.MainActivity$1@421de608 that was originally bound here

我的解决方法:

把bindService放到onResume中,unBindService放在onPause中;

2、java.lang.IllegalArgumentException: Service Intent must be explicit: Intent act=cn.coolspan.IncrementUpdateService (has extras)

解决方法:在onResume方法中的注释部分以解决,对Intent设置package

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
    intent.setPackage("cn.coolspan.open.android_increment_update");

暂时就遇到这2个坑,如果其他的问题,我会陆续更新到此文章中;

文章出处:

Coolspan CSDN博客:http://blog.csdn.net/qxs965266509

欢迎关注我的公众号,实时给你推送文章,谢谢支持;

微信搜索公众号:coolspan

或保存以下二维码进行微信扫描:

以上是关于Android 跨进程通信Aidl的使用及注意事项的主要内容,如果未能解决你的问题,请参考以下文章

Android跨进程通信——AIDL原理解析

Android 跨进程通信-从源码分析AIDL跨进程通信实现

Android IPCAIDL实现跨进程通信

Android跨进程通信Binder机制与AIDL实例

Android跨进程通信Binder机制与AIDL实例

Android AIDL 跨进程通信超详版