AIDL的一点理解

最近参与了一个项目,其中有用到两个APK间进行通信,最终采用的是AIDL,于是自己小研究了下,如有错误,请大家指正。


1.  创建.aidl文件

首先,创建.aidl文件。这个文件类似于声明文件,对于服务器端而言,就是声明你需要对外提供什么接口;对于客户端来说,声明了自己将要用到的接口。所以,不仅服务器端要创建.aidl文件,客户端同样需要。而且是客户端的.aidl文件要和服务器端的一样。所以服务器端一旦公布了对外接口,最好就不要改啦,因为会有很多客户端将用。


下面这两个文件IEmilyService.aidl 是EmilyService.apk 里的定义的,IEmilyServiceCallBack.aidl 这个是EmilySecondClient.apk定义的,因为这个两个apk需要进行双向通信。

但是在两个apk中,这个两个文件是必须都具备的。说白了就是为了方便互相调接口...


IEmilyService.aidl

package com.example.fwk;
import com.example.fwk.IEmilyServiceCallBack;

interface IEmilyService {

    void registerCallback(IEmilyServiceCallBack cb);

    void unregisterCallback(IEmilyServiceCallBack cb);

    void serviceShow();
}


IEmilyServiceCallBack.aidl

package com.example.fwk;

interface IEmilyServiceCallBack {

    void serviceCallBackShow();

}


2. 实现接口并将接口暴露给客户端

这个两个文件在编译后会自动生成.java文件。额,因为我用的是eclipse, 一运行就自己生成了,也没仔细看里面具体都有啥。从文档里得知,里面东西还是很重要的。尤其是一个内部类Stub,它是父类接口的抽象实现,里面定义了.aidl中的所有方法。

mBinder是IEmilyService.Stub的对象,里面实现了IEmilyService.aidl里定义的所有方法。当有客户端连接的时候,也就是来onBind(), 客户端会得到mBinder这个实例。


EmilyService

package com.example.emilyservice;

import com.example.fwk.IEmilyService;
import com.example.fwk.IEmilyServiceCallBack;

import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.app.Service;
import android.content.Intent;
import android.util.Log;

public class EmilyService extends Service {
    private static final String TAG = "EmilyService";

    /*
     * This is a list of callbacks that have been registered with the
     * service.
     */
    final RemoteCallbackList<IEmilyServiceCallBack> mCallbacks =
            new RemoteCallbackList<IEmilyServiceCallBack>();

    /*
     * Implements the interface.
     * 1. The mBinder is an instance of the Stub class (a Binder), which defines the RPC interface for the service.
     * 2. This instance will be exposed to clients, so the clients can interact with the service.
     * 3. If one service takes too much time to complete a request, you should avoid to call it from the main thread,
     * you should call it from a separate thread in the client, in this way to avoid ANR.
     */
    private final IEmilyService.Stub mBinder = new IEmilyService.Stub() {
        public void registerCallback(IEmilyServiceCallBack cb) {
            Log.i(TAG, "___________registerCallback()");
            if (cb != null) mCallbacks.register(cb);
        }

        public void unregisterCallback(IEmilyServiceCallBack cb) {
            Log.i(TAG, "___________unregisterCallback()");
            if (cb != null) mCallbacks.unregister(cb);
        }

        public void serviceShow() throws RemoteException {
            Log.i(TAG, "___________serviceShow()");
            testClients(null);
        }

    };

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return mBinder;
    }

    /*
     * Test the clients.
     */
    public void testClients(IEmilyServiceCallBack cb) {
        if (cb != null) {
            Log.i(TAG, "cb != null");
            try {
                cb.serviceCallBackShow();
            } catch (RemoteException e) {
            }
        } else {
            // Broadcast to all clients the new value.
            final int count = mCallbacks.beginBroadcast();
            for (int i=0; i < count; i++) {
                try {
                    Log.i(TAG, "onServiceShowFinished____i = " + i);
                    mCallbacks.getBroadcastItem(i).serviceCallBackShow();
                } catch (RemoteException e) {
                }
            }
            mCallbacks.finishBroadcast();
        }
    }
}


3. 当一个客户端调bindservice()去连接service的时候,客户端调用onServiceConected()回调方法。

 

Client

package com.example.emilysecondclient;

import com.example.fwk.IEmilyService;
import com.example.fwk.IEmilyServiceCallBack;

import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {
    private static String TAG = "EmilySecondClient";
    private static String ACTION_START_EMILY_SERVICE = "android.intent.action.EMILY_SERVICE";
    private IEmilyService mEmilyService = null;

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

        // When the client call the bindService() to connect to Emily service,
        // the client's onServiceConnected() callback receives IBinder that the
        // client can use to communicate with the service.
        Intent serviceIntent = new Intent(ACTION_START_EMILY_SERVICE);
        bindService(serviceIntent, mEmilyServiceConnection, Context.BIND_AUTO_CREATE);

        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                serviceShowInClient();
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    private final ServiceConnection mEmilyServiceConnection = new ServiceConnection() {
        // Called when the connection with the service is established.
        public void onServiceConnected(ComponentName className, IBinder service) {
            Log.i(TAG, "service connected");
            mEmilyService = IEmilyService.Stub.asInterface(service);
            // We want to monitor the service for as long as we are
            // connected to it.
            try {
                mEmilyService.registerCallback(mCallBack);
            } catch (RemoteException e) {
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            Log.i(TAG, "service disconnected");
            mEmilyService = null;
        }
    };

    private final IEmilyServiceCallBack.Stub mCallBack = new IEmilyServiceCallBack.Stub() {
        public void serviceCallBackShow() throws RemoteException {
            Log.i(TAG, "___________serviceCallBackShow()");
        }

    };

    private void serviceShowInClient() {
        try {
            mEmilyService.serviceShow();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}


以上只贴出来了一个Client的代码,另外一个client代码是类似的。

下面是运行出的log.

 

The log

I/EmilyFirstClient( 4163): service connected
I/EmilyService( 4084): Binder API: registerCallback()
I/EmilyService( 4084): ___________serviceShow()



I/EmilySecondClient( 4206): service connected
I/EmilyService( 4084): Binder API: registerCallback()
I/EmilyService( 4084): ___________serviceShow()




I/EmilyFirstClient( 6830): service connected
I/EmilyService( 6711): ___________registerCallback()
I/EmilyService( 6711): ___________serviceShow()
I/EmilyService( 6711): onServiceShowFinished____i = 0
I/EmilyFirstClient( 6830): ___________serviceCallBackShow()





I/EmilySecondClient( 6931): service connected
I/EmilyService( 6711): ___________registerCallback()
I/EmilyService( 6711): ___________serviceShow()
I/EmilyService( 6711): onServiceShowFinished____i = 0
I/EmilySecondClient( 6931): ___________serviceCallBackShow()

还是要好好研究下:

http://developer.android.com/guide/components/aidl.html 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值