码迷,mamicode.com
首页 > 移动开发 > 详细

android进程间通信:使用AIDL

时间:2015-07-28 18:06:31      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:

http://blog.csdn.net/saintswordsman/article/details/5130947

 

欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认你对这些概念已经有了一些了解,你(大致) 知道它们是什么,它们有什么用,所以为了节约大家的眼力和时间,在此我不复制粘贴网上泛滥的博客或者翻译冗长的android文档。

      关于AIDL的介绍在文档:docs/guide/developing/tools/aidl.html

      关于IBinder的介绍在文档:docs/reference/android/os/IBinder.html

      以及Binder:docs/reference/android/os/Binder.html

      在后文中,我将以我自己的理解向你介绍相关的概念。以我目前粗浅的经验,应用程序使用AIDL的地方,几乎都和Service有关,所以你也需要知道一些关于Service的知识。日后得闲我也会继续写一些关于Service的贴。

      本文将以一个例子来和你分享使用AIDL的基础技能,这个例子里有:

1、一个类mAIDLActivity,继承Activity。里面有三个按钮,text分别为StartService,StopService,CallbackTest。

2、一个类mAIDLService,继承Service。为了充分展示ADIL的功能,它做以下工作:当用户点击CallbackTest按钮时,从mAIDLActivity调用mAIDLService中的Stub 对象的一个方法invokCallBack(),而这个方法又会调用mAIDLActivity中Stub 对象的一个方法performAction(),这个方法在屏幕上显示一个toast。没什么意义,只是展示一下AIDL如何使用。

3、两个AIDL文件:forService.aidl和forActivity.aidl。对应名字,在Service和Activity中分别有对象需要用到它们定义的接口。

4、相关XML文件,略过。关于manifest中Service的语法,见docs/guide/topics/manifest /service-element.html。你也可以简单地在<application></application>中加入

     <service android:name=".mAIDLService" android:process=":remote"> </service>

开发环境为Eclipse。

拣重要的先说,来看看aidl文件的内容:

文件:forActivity.aidl

package com.styleflying.AIDL;  
interface forActivity {  
    void performAction();  
}  

文件:forService.aidl

package com.styleflying.AIDL;  
import com.styleflying.AIDL.forActivity;  
interface forService {  
    void registerTestCall(forActivity cb);  
    void invokCallBack();  
}  

这两个文件和Java文件放置的地方一样,看包名。

在Eclipse中它们将被自动编译为forActivity.java和forService.java,它们存放在gen目录下。为了方便手头无法演练的读者,代码不贴,不用细看。

 

再看mAIDLActivity.java:

package com.styleflying.AIDL;  
import android.app.Activity;  
import android.content.ComponentName;  
import android.content.Context;  
import android.content.Intent;  
import android.content.ServiceConnection;  
import android.os.Bundle;  
import android.os.IBinder;  
import android.os.RemoteException;  
import android.util.Log;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.Toast;  
public class mAIDLActivity extends Activity {  
    private static final String TAG = "AIDLActivity";  
    private Button btnOk;  
    private Button btnCancel;  
    private Button btnCallBack;  

    private void Log(String str) {  
        Log.d(TAG, "------ " + str + "------");  
    }  

    private forActivity mCallback = new forActivity.Stub() {  
        public void performAction() throws RemoteException  
        {  
            Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();  
        }  
    };  

    forService mService;  
    private ServiceConnection mConnection = new ServiceConnection() {  
        public void onServiceConnected(ComponentName className,  
                IBinder service) {  
            mService = forService.Stub.asInterface(service);  
            try {  
                mService.registerTestCall(mCallback);}  
            catch (RemoteException e) {  

            }  
        }  
        public void onServiceDisconnected(ComponentName className) {  
            Log("disconnect service");  
            mService = null;  
        }  
    };  
    @Override  
        public void onCreate(Bundle icicle) {  
            super.onCreate(icicle);  
            setContentView(R.layout.main);  
            btnOk = (Button)findViewById(R.id.btn_ok);  
            btnCancel = (Button)findViewById(R.id.btn_cancel);  
            btnCallBack = (Button)findViewById(R.id.btn_callback);  
            btnOk.setOnClickListener(new OnClickListener() {  
                    public void onClick(View v) {  
                    Bundle args = new Bundle();  
                    Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class);  
                    intent.putExtras(args);  
                    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);  
                    startService(intent);  
                    }  
                    });  
            btnCancel.setOnClickListener(new OnClickListener() {  
                    public void onClick(View v) {  
                    unbindService(mConnection);  
                    //stopService(intent);  
                    }  
                    });  
            btnCallBack.setOnClickListener(new OnClickListener() {  

                    @Override  
                    public void onClick(View v)  
                    {  
                    try  
                    {  
                    mService.invokCallBack();  
                    } catch (RemoteException e)  
                    {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                    }  
                    }  
                    });  
        }  
}

很短,相信大家很容易看明白。注意mConnection,它的onServiceConnected()中有一句mService = forService.Stub.asInterface(service);给mService赋值了,这个mService是一个 forService,而service是onServiceConnected()传进来的参数,onServiceConnected()会在连接 Service的时候被系统调用,这个service参数的值来自哪里呢?

看mAIDLService.java:

package com.styleflying.AIDL;  
import android.app.Service;  
import android.content.Intent;  
import android.os.IBinder;  
import android.os.RemoteCallbackList;  
import android.os.RemoteException;  
import android.util.Log;  
public class mAIDLService extends Service {  
    private static final String TAG = "AIDLService";    
    private forActivity callback;  
    private void Log(String str) {  
        Log.d(TAG, "------ " + str + "------");  
    }  
    @Override  
        public void onCreate() {  
            Log("service create");  
        }  
    @Override  
        public void onStart(Intent intent, int startId) {  
            Log("service start id=" + startId);  
        }  

    @Override  
        public IBinder onBind(Intent t) {  
            Log("service on bind");  
            return mBinder;  
        }  
    @Override  
        public void onDestroy() {  
            Log("service on destroy");  
            super.onDestroy();  
        }  
    @Override  
        public boolean onUnbind(Intent intent) {  
            Log("service on unbind");  
            return super.onUnbind(intent);  
        }  
    public void onRebind(Intent intent) {  
        Log("service on rebind");  
        super.onRebind(intent);  
    }  
    private final forService.Stub mBinder = new forService.Stub() {  
        @Override  
            public void invokCallBack() throws RemoteException  
            {  
                callback.performAction();  

            }  
        @Override  
            public void registerTestCall(forActivity cb) throws RemoteException  
            {  
                callback = cb;  

            }  

    };  
}

注意onBind(),它的返回类型为IBinder,返回了一个mBinder,看看mBinder的定义:

    private final forService.Stub mBinder = new forService.Stub() {

        @Override
        public void invokCallBack() throws RemoteException
        {
            callback.performAction();
         }

        @Override
        public void registerTestCall(forActivity cb) throws RemoteException
        {
            callback = cb;

        }

       };

它是实现了我们在AIDL中定义的方法,这个mBinder最终返回给了mAIDLActivity中的mService,于是在 mAIDLActivity中可以使用mBinder中的方法了。在mAIDLActivity中也有一个类似mBinder的对象,看看定义:   

        private forActivity mCallback = new forActivity.Stub()

    {
        public void performAction() throws RemoteException
        {
            Toast.makeText(mAIDLActivity.this, "this toast is called from service", 1).show();
        }
      };

我们要在界面上显示一个toast,就是在这里实现的。这个对象,在mConnection的onServiceConnected()被调用时, 通过调用mService(也就是远程的mAIDLService中的mBinder)的registerTestCall(),传递给了 mAIDLService,于是在mAIDLService中可以调用performAction()了。

很啰嗦,只为了能把这个细节说清楚。请大家认真看,我尽量避免错别字、混乱的大小写和逻辑不清的语法,相信你会看明白。是不是很简单?再啰嗦一下,做一个大致总结,我们使用AIDL是要做什么呢:

让Acticity(或者说一个进程/一个类?)和Service(或者说远端进程/远端类/对象?)获取对方的一个Stub对象,这个对象在定义 时实现了我们在AIDL中定义的方法,于是这些远程对象中的方法可以在本地使用了。如果这种使用(通信)是单向的,比如只是Activity需要通知 Service做什么,那么只要Service中有一个Stub对象,并且传给Acticity就够了。

至于如何获得远程的Stub,参看上面的代码,看mConnection、registerTestCall、onRebind,它们展示了一种方法。

另外,有时候我们可能在一个类中有多个Stub对象,它们都要给远程交互的类的实例,这个时候可以考虑使用RemoteCallbackList<>(docs/reference/android/os/RemoteCallbackList.html)。

 

android进程间通信:使用AIDL

标签:

原文地址:http://www.cnblogs.com/welhzh/p/4683465.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!