Android AIDL <1>
本篇文章主要是讲述aidl接口被其他APP使用的情况,当然顺便也给出了所在aidl的APP的使用.
开发AIDL步骤:
<1> : 首先AIDL接口里面的方法是在Android 组件Service中实现的,首先新建Android工程,让后新建一个包,用于放AIDL的文件,
在这个包下面,新建一个aidl的文件"aidluse.aidl",不要忘记扩展名,文件名将会是AIDL接口的接口名称,具体内容如下:
package service; interface aidluse{ void show(String s); String getInfor(); }
文件的写法与java接口写法差不多,但是不能够有public之类的关键词,一般的数据类型如int,String,long不需要引入对应的java包,但是如果要使用parcel对象,就需要引入它对应的包,基本接口可以大致这么做:
package aidl文件所在的包名(全路径包名); import java.io.InputStream;(加入说下面要用到InputStream,那么导入对应的java包) interface aidl文件的文件名{ /*接口里面的方法,只要不加public/private/protected基本上不会有什么问题*/ /*下面可以给出一个事例写法*/ int getId(); }
AIDL文件如果没有错误,那么eclipse将会在gen下自动产生一个aidluse.java的文件.
<2> : AIDL接口一般在android组件Service中实现其具体方法,由于其本身对应实例aidl.stud是一个IBinder对象,那么在使用时通过链接时获得这个IBinder对象就可以调用aidl的方法了.
可以这样来搞,首先新建一个继承Service的类,然后在这个类中实现aidl接口中的方法:
// remote binder //AIDL接口中的具体方法实现 public final aidluse.Stub mRemoteBinder = new aidluse.Stub() { @Override public void show(String s) throws RemoteException { // TODO Auto-generated method stub Log.i(TAG, "you have already call aidl show function !"); } @Override public String getInfor() throws RemoteException { // TODO Auto-generated method stub return "get information successfully !".toString(); } };
实现了这个AIDL接口,那么就需要返回这个aidluse.Stud对象,要返回这个对象,是通过Service类重载下来的这个方法实现的,当Service一旦被绑定时,这个立刻将会返回这个IBinder,即将调用下面的方法:
public IBinder onBind(Intent arg0){ return yourbinderobject; }
具体应用中是这么写的:
@Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub String aidlname = arg0.getAction(); Log.i(TAG, "name : " + aidlname); Toast.makeText(aidlService.this, "name : "+aidlname, Toast.LENGTH_SHORT).show(); // if (aidlname.toString().equalsIgnoreCase("")) { return mRemoteBinder; // } else if (aidlname.toString().equalsIgnoreCase("")) { // return mLocalBinder; // } }
其中里面的if被注释掉了,如果不被注释掉的话,它就相当于过滤或者选择调用返回IBinder对象了,但是要注意这个aidlname,这个对象是否有值,实际上要看BindService(...)中第一个参数new Intent(...)参数的写法,比如说,如果是如下写法:
new Intent(context,aidlService.class)
如果是上面的作为参数传递给BindService方法,那么aidlname=null;那就Service中的if语句就区分不出来了,那么要怎么写呢?可以这样:
new Intent("service.aidlService");
这样的写的话,aidlname="service.aidlService",但是这两种写法实际上发挥的作用可能存在差异.
具有筛选功能,即意味着可以在一个Service实现多个aidl的接口.
OK,下面给出整个aidlService类的source code:
package service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.widget.Toast; public class aidlService extends Service { private static final String TAG = "aidlService"; private IBinder mLocalBinder = new LocalBinder(); //放回绑定了AIDL的IBinder对象 //应用中获得这个绑定了实现AIDL接口类的IBinder对象 //就可以调用AIDL里面的方法了 @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub String aidlname = arg0.getAction(); Log.i(TAG, "name : " + aidlname); Toast.makeText(aidlService.this, "name : "+aidlname, Toast.LENGTH_SHORT).show(); // if (aidlname.toString().equalsIgnoreCase("")) { return mRemoteBinder; // } else if (aidlname.toString().equalsIgnoreCase("")) { // return mLocalBinder; // } } // local binder //这里可返回本地service里面的方法 //被其他方法调用时 class LocalBinder extends Binder { aidlService localService() { return aidlService.this; } } // remote binder //AIDL接口中的具体方法实现 public final aidluse.Stub mRemoteBinder = new aidluse.Stub() { @Override public void show(String s) throws RemoteException { // TODO Auto-generated method stub Log.i(TAG, "you have already call aidl show function !"); } @Override public String getInfor() throws RemoteException { // TODO Auto-generated method stub return "get information successfully !".toString(); } }; @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); } @Override public void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); } @Override public void onStart(Intent intent, int startId) { // TODO Auto-generated method stub super.onStart(intent, startId); } }
<3> 如何被调用,首先要声明一个aidluse接口的对象:
private aidluse mService;
<4> 然后连接实现aidl的Service上面:
private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { // TODO Auto-generated method stub mService = aidluse.Stub.asInterface(arg1); } @Override public void onServiceDisconnected(ComponentName arg0) { // TODO Auto-generated method stub if(mService!=null){ mService=null; } } };
<5> 要想在Activity中使用,还需要绑定这个连接(可以在onCreate(),onResume()中进行),如果Activity结束),也要接解绑定这个连接(可以在finish(),destroy(),也可以stop()中),具体绑定和解绑如下:
this.bindService(new Intent(this, aidlService.class), connection, Context.BIND_AUTO_CREATE);
这样的写法,aidlname=null,所以去掉了if筛选功能.
解绑如下:
this.unbindService(connection);
整个代码如下:
package com.example.androidaidlsdemo; import service.aidlService; import service.aidluse; 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.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { private aidluse mService; private Button mShowBtn; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName arg0, IBinder arg1) { // TODO Auto-generated method stub mService = aidluse.Stub.asInterface(arg1); } @Override public void onServiceDisconnected(ComponentName arg0) { // TODO Auto-generated method stub if(mService!=null){ mService=null; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.bindService(new Intent(this, aidlService.class), connection, Context.BIND_AUTO_CREATE); mShowBtn=(Button)findViewById(R.id.show); mShowBtn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub try { mService.show("you are right !"); Toast.makeText(MainActivity.this, mService.getInfor(), Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } @Override public void finish() { // TODO Auto-generated method stub super.finish(); this.unbindService(connection); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
<6> 运行之前,由于Service也是Android的四大组件之一,所以需要在AndroidManifest.xml进行配置:
<service android:name="service.aidlService" android:exported="true" > <intent-filter> <action android:name="service.aidlService" > </action> </intent-filter> </service>
如果没有特别的要求,就相当于写Activity的是一样的.
<7> 上面瞎扯了那么多,都不是这篇文章的重点,重点是如何让其他APP调用这个AIDL接口.上面全部是铺垫.
要想调用,那么新建一个android工程后,第一件事就是讲前面那个APP的service包和包下的文件拷贝放到新建工程中,由于上面的那个
service包包含了aidl文件盒继承Service的类文件,那么拷贝以后,那个继承Service的java文件不是我们需要的,就要删掉,删掉以后,刷新工程,
如果不出意外,工程下的gen目录下会自动产生aidluse.java的文件.
<8> 进行完上面一个步骤,即可以直接使用了,当然在运行之前,需要先运行前面个APP,让其将service服务启动起来.
具体操作和前面APP差不多:
package com.example.androidaidldemo; import service.aidluse; 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.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { private aidluse mService; private Button mButton; private ServiceConnection connection=new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub mService=aidluse.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub if(mService!=null){ mService=null; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.bindService(new Intent("service.aidlService"), connection, Context.BIND_AUTO_CREATE); mButton=(Button)findViewById(R.id.button1); mButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub try { Toast.makeText(MainActivity.this, mService.getInfor(), Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); } @Override public void finish() { // TODO Auto-generated method stub super.finish(); this.unbindService(connection); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }

浙公网安备 33010602011771号