Android远程服务AIDL的使用以及配合接口回调使用

来源:互联网 发布:用什么编写python 编辑:程序博客网 时间:2024/06/04 03:53

远程服务的接口回调

Android 开发中的一些场景需要用到进程间通信,一般使用AIDL(Android Interface Definition

Language)。使用AIDL绑定一个远程服务,远程服务可以被其他应用绑定,绑定后可以使用定义在AIDL接口中的方法来进行一些操作,远程服务会另外开启一个进程。

1、简单使用

  • 1.1 就像使用普通的服务一样,首先要创建一个服务类的子类,继承Service。

    RemoteService.java

package com.example.administrator.newpager.service;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.support.annotation.Nullable;import android.util.Log;import android.widget.Toast;/** * auther:wzy * date:2017/1/8 19 :52 * desc:  */public class RemoteService extends Service {    private static final String TAG = "RemoteService";    private RemoteCallbackList<IMyAidlCallBack> mRemoteCallbackList = new RemoteCallbackList<>();    @Nullable    @Override    public IBinder onBind(Intent intent) {        Log.i(TAG, "onBind: ");        return new LocalBinder();    }    @Override    public void onCreate() {        Log.i(TAG, "onCreate: ");        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i(TAG, "onStartCommand: ");        return super.onStartCommand(intent, flags, startId);    }   //Binder类    class LocalBinder extends IRemoteService.Stub {        @Override        public void refreshFromNet() throws RemoteException {            doSomeThingHere();        }    }}

这里与普通服务子类创建的不同之处在于:

普通服务类中Activity需要与Service绑定时,会在onBind()方法里返回一个IBinder的子类,这个子类只是 简单方法,可以是Service子类中的方法,也可以继承一个接口,实现需要重写的方法。

这里的IBinder类则需要继承的是一个创建AIDL后自动生成的一个类,下面会说。

  • 1.2 创建AIDl ,在Android Studio 中直接有创建AIDL的选项

创建AIDL
编写格式像这样:

IRemoteService.java

package com.example.administrator.newpager.service;import com.example.administrator.newpager.service.IMyAidlCallBack;interface IRemoteService  {    void refreshFromNet();}

其中要注意,文件中需要引用其他文件的时候,一定要带上如上的

import com.example.administrator.newpager.service.IMyAidlCallBack;

即使是在同一个包下

  • 1.3 创建好AIDL文件后,执行IDE的ReBuild操作,这时候会生成一个Stub文件,如样例中则会生成IRemoteService.Stub文件,这个文件的内容细节先不去管,1.1中的Stub就是从这里得到的。

Rebuild

  • 1.4 如1.1中代码所示,继承IRemoteService.Stub 类,重写里面的方法,这些方法就是之前AIDL中定义的未实现的方法,实现这些方法很重要,其他应用或者Activity之类的绑定服务 ,就是为了调用这里面的方法来执行一些必要操作。

  • 1.5 在 onBind()方法中返回 IRemoteService.Stub的子类对象。

  • 1.6 在需要调用服务中方法的地方,如一个应用的Activity,这个应用我们称为客户端,在Activity中,就像绑定普通服务一样,执行mContext.bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);

    这里是得到服务对象的重要步骤,bindService是耗时的,因此异步操作从回调中获取远程服务对象。

    mServiceConnection :

    private ServiceConnection mServiceConnection = new ServiceConnection() {      @Override      public void onServiceConnected(ComponentName name, IBinder service) {          mIRemoteService = IRemoteService.Stub.asInterface(service);      }      @Override      public void onServiceDisconnected(ComponentName name) {      }  };
  • 1.7 绑定服务,bindService();

     private void bindService() {//        Intent intent = new Intent("com.example.administrator.newpager.REMOTESERVICE");//        intent.setComponent//                    (new ComponentName("com.example.administrator.newpager.service",//                        "com.example.administrator.newpager.service.RemoteService"));      Intent intent = new Intent(mContext, RemoteService.class);      mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);      showTextView();  }

    绑定服务操作因Intent的不同,有多重绑定途径。

  • 1.8 与普通服务开启的操作一样,这里也需要 在manifest中需要进行配置。

    也由于使用场景不同,这里可以配合Intent添加一些其他参数。

    <service         <!-- 这里可以添加一些Actioncategory-->          android:name=".service.RemoteService"></service>

  • 1.9 在需要调用远程服务中方法的地方调用。

2、远程服务与接口回调配合使用

​ 在有些场景中,调用方如其他应用,需要在进程在运行到某个阶段执行调用方的一些操作,或者远程服务在进行一些异步操作的时候需要将结果回调给调用方,这时候,使用接口回调就能解决,Android中也提供了这样的接口:RemoteCallbackList

  • 2.1 步骤与之前使用远程服务类似,不同的是要多创建一个AIDL文件,用于回调的接口类型。

    // IMyAidlCallBack.aidlpackage com.example.administrator.newpager.service;interface IMyAidlCallBack {   void callBack(int result);}
  • 2.2 在之前的AIDL文件中添加这些

    package com.example.administrator.newpager.service;import com.example.administrator.newpager.service.IMyAidlCallBack;interface IRemoteService  {    void refreshFromNet();  //----添加----//    void registerListener(IMyAidlCallBack callBack);    void unRegisterListener(IMyAidlCallBack callBack);    void doInBackGround();   //-----------//}
  • 2.3 在之前的代码中

    package com.example.administrator.newpager.service;import android.app.Service;import android.content.Intent;import android.os.IBinder;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.support.annotation.Nullable;import android.util.Log;import android.widget.Toast;/*** auther:wzy* date:2017/1/8 19 :52* desc: */public class RemoteService extends Service { private static final String TAG = "RemoteService"; private RemoteCallbackList<IMyAidlCallBack> mRemoteCallbackList = new RemoteCallbackList<>(); @Nullable @Override public IBinder onBind(Intent intent) {     Log.i(TAG, "onBind: ");     return new LocalBinder(); } @Override public void onCreate() {     Log.i(TAG, "onCreate: ");     super.onCreate(); }    //----------------添加------------------------//  //执行耗时操作 public void doInBackGround() {     new Thread() {         @Override         public void run() {             long result = this.getId();             int count = 0;             Log.i(TAG, "mRemoteCallbackList: " +     mRemoteCallbackList+",mRemoteCallbackList.mCallBack:"+mRemoteCallbackList);             count = mRemoteCallbackList.beginBroadcast();             if (count == 0) {                 return;             }             try {                 for (int i = 0; i < count; i++) {                     mRemoteCallbackList.getBroadcastItem(i).callBack((int) result);                 }             } catch (RemoteException e) {                 e.printStackTrace();             } finally {                 mRemoteCallbackList.finishBroadcast();             }         }     }.start(); }    //------------------------------//   @Override public int onStartCommand(Intent intent, int flags, int startId) {     Log.i(TAG, "onStartCommand: ");     return super.onStartCommand(intent, flags, startId); }//Binder类 class LocalBinder extends IRemoteService.Stub {     @Override     public void refreshFromNet() throws RemoteException {     }//-----------------添加-----------------------//     @Override     public void registerListener(IMyAidlCallBack callBack) throws RemoteException {         Log.i(TAG, "callBack:" + callBack);         Log.i(TAG, "mRemoteCallbackList:" + mRemoteCallbackList);         if (mRemoteCallbackList == null) {             Toast.makeText(getApplicationContext(), "mRemoteCallbackList==null", Toast.LENGTH_SHORT).show();             Log.i(TAG, "mRemoteCallbackList==null");             return;         }         mRemoteCallbackList.register(callBack);     }     @Override     public void unRegisterListener(IMyAidlCallBack callBack) throws RemoteException {         mRemoteCallbackList.unregister(callBack);     }     @Override     public void doInBackGround() throws RemoteException {         RemoteService.this.doInBackGround();     }   //---------------------------------// }}

    上面添加的代码中比较关键的两点有:注册和反注册远程回调接口,也就是将回调对象元素加入或移 除mRemoteCallbackList这个对象中的一个集合;执行回调,将回调方法放在需要执行的地方,这里模拟耗时操作,放在了线程执行结束的地方,mRemoteCallbackList.getBroadcastItem(i).callBack((int) result);

    需要注意的是:mRemoteCallbackList.finishBroadcast();这句必须执行,否则有可能会出现状态不合法异常。

  • 2.3 使用它,在需要进行耗时操作,并且调用方需要获取耗时操作的结果,再对其进行处理的地方;需要继承IMyAidlCallBack.aidl自动生成的 IMyAidlCallBack.Stub类,并重写里面的方法。

  try {              mIRemoteService.registerListener(new IMyAidlCallBack.Stub() {                  @Override                  public void callBack(final int result) throws RemoteException {                      new Handler(Looper.getMainLooper()).post(new Runnable() {                          @Override                          public void run() {                              textView.setText("result:" + result + "");                          }                      });                  }              });          } catch (RemoteException e) {              e.printStackTrace();          }

运行结果:

这里写图片描述

代码地址:https://github.com/RosesJack/AIDL_Demo

0 0