Android实现跨进程接口回掉的方法

 更新时间:2019年05月08日 14:30:10   作者:H.Y.   我要评论
这篇文章主要给大家介绍了关于Android如何实现跨进程接口回掉的相关资料,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

        同一个进程内实现接口回掉很简单,这里不做叙述,本文主要讲的是跨进程的接口回掉实现方式。有一种跨进程通信的方式就是使用AIDL,但是单纯的AIDL通信只可以实现客户端访问服务端主动获取Binder对象,如果服务端有变化无法及时通知客户端。现在可以通过AIDL跨进程接口回掉来解决服务端发生变化通知客户端的问题。

         谷歌提供了RemoteCallbackList来实现对IInterface的管理。public class RemoteCallbackList<E extends IInterface>

首先定义两个AIDL文件:

1.ITestCallBack.aidl

interface ITestCallBack {
 /**
  * Demonstrates some basic types that you can use as parameters
  * and return values in AIDL.
  */
 void onTagValid(in String tag);

}

2.ITestInterface.aidl    在注册和反祖册方法中,需要传入ITestCallBack的对象

interface ITestInterface {
 /**
  * Demonstrates some basic types that you can use as parameters
  * and return values in AIDL.
  */
  boolean isTagValid(in String tag);

  void registerCallback(in String tag, in ITestCallBack callback);

  void unRegisterCallback(in String tag, in ITestCallBack callback);
}

服务端:

         创建Service,并且在service中定义RemoteCallbackList集合,实现ITestInterface.Stub,在registerCallback,和unRegisterCallback中,分别将ITestCallBack对象注册和反注册进RemoteCallbackList中。RemoteCallbackList提供了获取注册进去的IInterface对象方法

//其实RemoteCallbackList类似于java中{@link java.util.Observable},用来批量处理接口回调对象,
//其实如果确保只有一个客户端会bind到这个服务,只需要保存一个IMyAidlInterfaceCallback即可。
//但是如果有多个,强烈推荐使用其实RemoteCallbackList

public void callBack() {
 if (mCallBacks == null) {
  return;
 }
 int num = mCallBacks.beginBroadcast();
 for (int i = 0; i < num; i++) {
  try {
   mCallBacks.getBroadcastItem(i).onTagValid("congratulation callback success " + tag);
  } catch (RemoteException e) {
   e.printStackTrace();
  }
 }
 //结束后一定要使用finsh,否则下次执行beginBroadcast会抛出IllegalStateException异常
 mCallBacks.finishBroadcast();
}

在isTagValid中可以调用callBack方法去遍历注册的接口对象,也可以当服务端有变化时主动调用callBack方法去通知客户端,这样就实现了服务端变化主动通知客户端。可根据实际方法修改。

在service的onBind方法中,返回ITestInterface.Stub的对象即可,等待客户端绑定服务端。

下面是服务端Service的代码:

public class TestService extends Service {

 private RemoteCallbackList<ITestCallBack> mCallBacks = new RemoteCallbackList<>();
 private String tag = "hy";

 public TestService() {
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO: Return the communication channel to the service.
  return iTestInterface;
 }

 @Override
 public boolean onUnbind(Intent intent) {
  return super.onUnbind(intent);
 }

 ITestInterface.Stub iTestInterface = new ITestInterface.Stub() {
  @Override
  public boolean isTagValid(String tag) throws RemoteException {
   if (tag.equals(TestService.this.tag)) {
    callBack();
    return true;
   }
   return false;
  }

  @Override
  public void registerCallback(String tag, ITestCallBack callback) throws RemoteException {
   if (null != mCallBacks && null != callback) {
    mCallBacks.register(callback);
   }
  }

  @Override
  public void unRegisterCallback(String tag, ITestCallBack callback) throws RemoteException {
   if (null != mCallBacks && null != callback) {
    mCallBacks.unregister(callback);
   }
  }
 };

 public void callBack() {
  if (mCallBacks == null) {
   return;
  }
  int num = mCallBacks.beginBroadcast();
  for (int i = 0; i < num; i++) {
   try {
    mCallBacks.getBroadcastItem(i).onTagValid("congratulation callback success " + tag);
   } catch (RemoteException e) {
    e.printStackTrace();
   }
  }
  mCallBacks.finishBroadcast();
 }
}

客户端:

        客户端首先要做的是绑定服务端,实现AIDL的通信,在客户端创建绑定按钮,解绑按钮,和主动获取信息的通信按钮。在主动获取信息的通信按钮中实现iTestInterface对象的isTagValid方法可以主动去获取服务端的信息(服务端在isTagValid方法中调用了callBack方法)。

客户端代码:

public class MainActivity extends AppCompatActivity {

 private String tag = "hy";
 private ITestInterface iTestInterface;
 private ServiceConnection connection = new ServiceConnection() {
  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   iTestInterface = ITestInterface.Stub.asInterface(service);
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   iTestInterface = null;
  }
 };

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  bindService();
  ((Button) findViewById(R.id.buttonregister)).setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    try {
     iTestInterface.registerCallback(tag, new ITestCallBack.Stub() {
      @Override
      public void onTagValid(String tag) throws RemoteException {
       Log.e("test", "registerCallback: " + tag);
      }
     });
    } catch (RemoteException e) {
     e.printStackTrace();
    }
   }
  });

  ((Button) findViewById(R.id.buttonunregister)).setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    try {
     iTestInterface.unRegisterCallback(tag, new ITestCallBack.Stub() {
      @Override
      public void onTagValid(String tag) throws RemoteException {

      }
     });
    } catch (RemoteException e) {
     e.printStackTrace();
    }
   }
  });

  ((Button) findViewById(R.id.buttonisvalid)).setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    try {
     iTestInterface.isTagValid(tag);
    } catch (RemoteException e) {
     e.printStackTrace();
    }
   }
  });
 }

 private void bindService() {
  Intent intent = new Intent();
  intent.setAction("com.example.heyang.myapplication.TestService");
  intent.setPackage("com.example.heyang.myapplication");
  boolean success = bindService(intent, connection, Context.BIND_AUTO_CREATE);
  if (success) {
   Log.e("test ", "bindService OK");
  } else {
   Log.e("test ", "bindService Fail");
  }
 }

 @Override
 protected void onDestroy() {
  super.onDestroy();
  unBindeService();
 }

 private void unBindeService() {
  try {
   unbindService(connection);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • Android实现静默安装实例代码

    Android实现静默安装实例代码

    本篇文章主要介绍了Android实现静默安装实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Android主题切换之探究白天和夜间模式

    Android主题切换之探究白天和夜间模式

    所谓的主题切换,就是能够根据不同的设定,呈现不同风格的界面给用户,也就是所谓的换肤。下面跟小编一起来看看怎么实现Android主题切换中的白天和夜间模式。
    2016-07-07
  • Android多媒体之VideoView视频播放器

    Android多媒体之VideoView视频播放器

    这篇文章主要为大家详细介绍了Android多媒体之VideoView视频播放器的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • Android签名知识小结

    Android签名知识小结

    不止一次有用到Android签名相关的知识,每次都几乎从零开始在Google上搜索找,不想在继续这样了,找了个时间好好整理了一下自己用到的一些碎片知识,于是乎放到这里,一是备忘,二是帮助别人
    2016-03-03
  • Android Studio多工程引用同一个library项目配置的解决方法

    Android Studio多工程引用同一个library项目配置的解决方法

    大家在使用android studio的时候,会遇到多个项目引用相同的library这篇文章主要介绍了Android Studio多工程引用同一个library项目配置方法,需要的朋友可以参考下
    2018-03-03
  • 常见android app加固厂商脱壳方法研究

    常见android app加固厂商脱壳方法研究

    这篇文章主要介绍了常见android app加固厂商脱壳方法研究,需要的朋友可以参考下
    2018-01-01
  • Kotlin中协变、逆变和不变示例详解

    Kotlin中协变、逆变和不变示例详解

    这篇文章主要给大家介绍了关于Kotlin中协变、逆变和不变的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-04-04
  • 手机/移动前端开发需要注意的20个要点

    手机/移动前端开发需要注意的20个要点

    本文主要介绍了手机/移动前端开发需要注意的20个要点,具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • android中的AIDL进程间通信示例

    android中的AIDL进程间通信示例

    进程之间不能共享内存,那么怎么在不同的应用程序中进行通讯,这就要依赖AIDL机制,本文详细介绍了android中的AIDL进程间通信示例,有兴趣的可以了解一下。
    2016-11-11
  • Flutter进阶之实现动画效果(五)

    Flutter进阶之实现动画效果(五)

    这篇文章主要为大家详细介绍了Flutter进阶之实现动画效果的第五篇,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08

最新评论