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

远程服务的接口回调

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.aidl
    package 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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值