欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-18 17:06:52
前言         同一个进程内实现接口回掉很简单,这里不做叙述,本文主要讲的是跨进程的接口回掉实...

前言

        同一个进程内实现接口回掉很简单,这里不做叙述,本文主要讲的是跨进程的接口回掉实现方式。有一种跨进程通信的方式就是使用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();
  }
 }
}

总结

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