AndroidStudio 使用AIDL

来源:互联网 发布:淘宝网店铺招牌图片 编辑:程序博客网 时间:2024/04/20 05:46

一直以来都认为AIDL的应用离我很遥远,甚至不知道如何去用,也就懒得去学,之前的项目中也看到过aidl文件,只是懒得去看而已,现在感觉自己真的是无药可救了,如果只止步于学习一些UI调整的东西谈何进步,不过有些东西也真是逼着去学的,要学的东西太多了,只要隔着一段时间不用的话,估计学习的东西又都忘完了,不说了,开始讲正事,也算给自己留个笔记,长时间不用再回来看看。

1、为什么要有AIDL?

对于AIDL有一些人(包括我自己)的浅显概念就是:AIDL可以跨进程访问其他应用程序,和其他应用程序通讯,那我告诉你,很多技术都可以访问,如广播(应用A在AndroidManifest.xml中注册指定Action的广播)应用B发送指定Action的广播,A就能收到信息,这样也能看成不同应用之间完成了通讯(但是这种通讯是单向的);还如ContentProvider,通过URI接口暴露数据给其他应用访问;但是这种都算不上是应用之间的通讯。可能最让人迷惑的是Android推出来了Messenger,它就是完成应用之间的通讯的。那么为什么还要有AIDL呢,官方文档介绍AIDL中有这么一句话:

Note: Using AIDL is necessary only if you allow clients from different applications to access your service for IPC and want to handle multithreading in your service. If you do not need to perform concurrent IPC across different applications, you should create your interface by implementing a Binder or, if you want to perform IPC, but do not need to handle multithreading, implement your interface using a Messenger. Regardless, be sure that you understand Bound Services before implementing an AIDL.

第一句最重要,“只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL”,其他情况下你都可以选择其他方法,如使用Messenger,也能跨进程通讯。可见AIDL是处理多线程、多客户端并发访问的。而Messenger是单线程处理。还是官方文档说的明白,一句话就可以理解为什么要有AIDL。一直认为理论应与实践相结合,这样才利于学习,由于现在用的是android studio ,所以就用的AS开发的一个AIDL小demo。

2、AIDL使用

2.1、在android studio中创建一个工程

2.2、创建两个module  比如我的: aidlserver和app这样就能实现两个进程了。

   图1

2.3、在aidlserver中的创建aidl文件见下图

   图2

   2.3.1、在你新建的aidl中声明你的服务方法,此处声明了add和min两个方法,代码如下

  
 // ICalcAIDL.aidlpackage com.liujc.aidlserver;// Declare any non-default types here with import statementsinterface ICalcAIDL {    /**     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */    int add(int x , int y);    int min(int x , int y );}

   2.3.2、在工具栏中build该module,生成ICalcAIDL对应的java代码,如下

   图3  
   图4

   2.3.3、在对用的java文件夹下创建对应的service,例如图中的CalcService,代码如下:

package com.liujc.aidlserver;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteException;import android.util.Log;public class CalcService extends Service {    private static final String TAG = "server";    public void onCreate()    {        Log.e(TAG, "onCreate");    }    public IBinder onBind(Intent t)    {        Log.e(TAG, "onBind");        return mBinder;    }    public void onDestroy()    {        Log.e(TAG, "onDestroy");        super.onDestroy();    }    public boolean onUnbind(Intent intent)    {        Log.e(TAG, "onUnbind");        return super.onUnbind(intent);    }    public void onRebind(Intent intent)    {        Log.e(TAG, "onRebind");        super.onRebind(intent);    }    private final ICalcAIDL.Stub mBinder = new ICalcAIDL.Stub()    {        @Override        public int add(int x, int y) throws RemoteException        {            return x + y;        }        @Override        public int min(int x, int y) throws RemoteException        {            return x - y;        }    };}

 2.3.4、在mainifest文件中声明service,如下:

<service android:name=".CalcService"                android:process=":remote">            <intent-filter>                <action android:name="com.liujc.aidlserver.CalcService" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </service>

2.4、将aidlserver中的aidl包,直接copy到app中(客户端的aidl包必须和服务端一致,否则会序列化失败,无法bindservice),如下图,同时也要和步骤2.3.2一样生成相应的java代码。

   图5  

2.5、实现客户端和服务端的绑定代码

package com.liujc.utdemo;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.content.pm.PackageManager;import android.content.pm.ResolveInfo;import android.os.IBinder;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Toast;import com.liujc.aidlserver.ICalcAIDL;import java.util.List;public class MainActivity extends Activity {    private ICalcAIDL mCalcAidl;    private ServiceConnection mServiceConn = new ServiceConnection()    {        @Override        public void onServiceDisconnected(ComponentName name)        {            Log.e("client", "onServiceDisconnected");            mCalcAidl = null;        }        @Override        public void onServiceConnected(ComponentName name, IBinder service)        {            Log.e("client", "onServiceConnected");            mCalcAidl = ICalcAIDL.Stub.asInterface(service);        }    };    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    /**     * 点击BindService按钮时调用     * @param view     */    public void bindService(View view)    {        Intent intent = new Intent("com.liujc.aidlserver.CalcService");//        intent.setAction("com.liujc.aidlserver.CalcService");        final Intent eintent = new Intent(createExplicitFromImplicitIntent(this,intent));        bindService(eintent, mServiceConn, Context.BIND_AUTO_CREATE);    }    /**     * 点击unBindService按钮时调用     * @param view     */    public void unbindService(View view)    {        if (mServiceConn != null)        unbindService(mServiceConn);    }    /**     * 点击12+12按钮时调用     * @param view     */    public void addInvoked(View view) throws Exception    {        if (mCalcAidl != null)        {            int addRes = mCalcAidl.add(12, 12);            Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();        } else        {            Toast.makeText(this, "服务器被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)                    .show();        }    }    /**     * 点击50-12按钮时调用     * @param view     */    public void minInvoked(View view) throws Exception    {        if (mCalcAidl != null)        {            int addRes = mCalcAidl.min(58, 12);            Toast.makeText(this, addRes + "", Toast.LENGTH_SHORT).show();        } else        {            Toast.makeText(this, "服务端未绑定或被异常杀死,请重新绑定服务端", Toast.LENGTH_SHORT)                    .show();        }    }    public  Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {        // Retrieve all services that can match the given intent        PackageManager pm = context.getPackageManager();        List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);        // Make sure only one match was found        if (resolveInfo == null || resolveInfo.size() != 1) {            return null;        }        // Get component info and create ComponentName        ResolveInfo serviceInfo = resolveInfo.get(0);        String packageName = serviceInfo.serviceInfo.packageName;        String className = serviceInfo.serviceInfo.name;        ComponentName component = new ComponentName(packageName, className);        // Create a new intent. Use the old one for extras and such reuse        Intent explicitIntent = new Intent(implicitIntent);        // Set the component to be explicit        explicitIntent.setComponent(component);        return explicitIntent;    }}
 
 OK,今天先到这里,后续再看下Messenger类和Binder。源码


0 0
原创粉丝点击