上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html

但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推送数据给客户端

原理:客户端注册回调函数,并把回调的对象当做参数传递给服务端,这种服务端调用函数其实就是回调客户端的函数,废话不多说,直接看代码!

首先是服务端的AIDL文件

IAidlHguConnCallback.aidl文件

package tel.gateway.connservice;

interface IAidlHguConnCallback{

void update( String ssid, String pwd);

}

IAidlHguConnCallback.aidl文件

package tel.gateway.connservice;
import tel.gateway.connservice.IAidlHguConnCallback;
interface IAidlHguConnService{
void setListener(IAidlHguConnCallback listener);

void unregisterListener(IAidlHguConnCallback listener);

void setWifiInfo(String username, String pwd, String security);

void getWifiInfo();

}

注意客户端那边直接把服务端的包直接复制过去就可以的,因为aidl文件要保证两边的包名类名是完全一样的

接下来就是服务端的代码:

public class MyService extends Service{
protected static final String TAG = "MyService";
private String ssid;
private String mPwd;
/**
* 我们知道AIDL方法是在服务端的Binder线程池中执行的,当我们多个客户端访问服务端的时候,容易发生并发现象,
* 这里采用CopyOnWriteArrayList,这个CopyOnWriteArrayList支持并发读/写,而我们这里直接使用
* CopyOnWriteArrayList来进行自动的线程同步
*/
//private CopyOnWriteArrayList<IAidlHguConnCallback> callbacks = new CopyOnWriteArrayList<IAidlHguConnCallback>();

private RemoteCallbackList<IAidlHguConnCallback> callbacks = new RemoteCallbackList<IAidlHguConnCallback>();
private AtomicBoolean atomicBoolean = new AtomicBoolean(false);
private int i =0;//用来判断是否循环发生SSID
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return binder;
}
@Override
public void onCreate() {
super.onCreate();
//在这里开启一个线程,每隔5S向所有用户推送wifi的SSID和PWD
new Thread(new Runnable() {
@Override
public void run() {
while (!atomicBoolean.get()) {
try {
Thread.sleep(5000);
//这里就是向客户端推送的消息,你想发什么消息依照自己的项目来,我这里只是示范!
if(ssid!=null&&mPwd!=null){
OnSendSsidAndPwd(ssid+i, mPwd+i);
i++;
}
} catch (Exception e) {
}

}
}
}).start();
}
private void OnSendSsidAndPwd(String ssid,String pwd) throws RemoteException{

for(int i =0;i<callbacks.beginBroadcast();i++){
IAidlHguConnCallback l = callbacks.getBroadcastItem(i);
if(l !=null){
l.update(ssid, pwd);
}
}
callbacks.finishBroadcast();

}
private Binder binder = new IAidlHguConnService.Stub() {

@Override
public void unregisterListener(IAidlHguConnCallback listener)
throws RemoteException {
callbacks.unregister(listener);
}

@Override
public void setWifiInfo(String username, String pwd, String security)
throws RemoteException {
//TODO
//这里处理客户端用户传递过来的wifi名字和密码
//比如我把传递过来的数值实例化给成员变量,然后在getWifiInfo传递给客户端
ssid = username;
mPwd = pwd;
}
@Override
public void setListener(IAidlHguConnCallback listener)
throws RemoteException {
//这里把所有注册过监听的客户端收集起来,以便接下来可以传递数据给他们
callbacks.register(listener);
}
@Override
public void getWifiInfo() throws RemoteException {
Log.i(TAG, "收到!!!");
OnSendSsidAndPwd(ssid, mPwd);//通知所有注册过监听的用户,告诉他们密码和用户名
}
};

}

客户端的代码:

public class Client extends Service{
private static final String TAG = "Client";
public Handler handler = new Handler(){
public void handleMessage(Message msg) {
String ssid = msg.getData().getString("ssid");
String pwd = msg.getData().getString("pwd");
Log.i("client --- TAG", "msg:;"+ssid+"pwd:"+pwd);
};
};
protected IAidlHguConnService mService;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent mIntent = new Intent();
mIntent.setClassName("com.example.test1", "com.example.test1.MyService");
bindService(mIntent, mBindService, Context.BIND_AUTO_CREATE);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
//当服务被销毁时记得销毁绑定的监听和service
unbindService(mBindService);
try {
mService.unregisterListener(stub);
} catch (RemoteException e) {
e.printStackTrace();
}
}
/**
* 注意此回调方法是在客户端的Binder线程池中执行的,因为威力便于更新UI,我们需要创建一个handler
*/
private IAidlHguConnCallback.Stub stub = new IAidlHguConnCallback.Stub() {
@Override
public void update(String ssid, String pwd) throws RemoteException {
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("ssid", ssid);
bundle.putString("pwd", pwd);
message.setData(bundle);
handler.sendMessage(message);
}
};
private ServiceConnection mBindService = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IAidlHguConnService.Stub.asInterface(service);
try {
mService.setListener(stub);//设置回调函数
mService.setWifiInfo("想偷WIFI?", "123456", "0");
mService.getWifiInfo();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub

}
};
}

还有一点需要注意,当客户端连接服务端的时候你要保证服务端的service是开启了,然后记得在清单文件里面注册service

<service
android:name="com.example.test1.MyService"
android:enabled="true"
android:exported="true" >
</service>

如果还发现什么错误可以自行看LOGCAT,比如权限没加什么的!

android不需要Socket的跨进程推送消息AIDL!的更多相关文章

  1. Android为TV端助力 不需要Socket的跨进程推送消息AIDL!

    上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html 但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推 ...

  2. Android 心跳包心跳连接 如何实现android和服务器长连接呢?推送消息的原理

    前言:现在的大多数移动端应用都有实时得到消息的能力,简单来说,有发送消息的主动权和接受消息的被动权.例如:微信,QQ,天气预报等等,相信好处和用户体验相信大家都知道吧. 提出问题:这种功能必须涉及cl ...

  3. Android:开机自启动并接收推送消息

    接收推送消息部分我们通过ZeroMQ实现,可以参考http://www.cnblogs.com/ilovewindy/p/3984283.html. 首先是开机自启动的功能实现,代码如下:1.     ...

  4. Android APP切换到后台接收不到推送消息

    1.   Android端进程被杀死后,目前自带的保护后台接收消息活跃机制.暂时没有什么好的机制保持任何情况下都活跃 android原生系统用home键杀进程可以起来,如果是强行停止就只能用户自己手动 ...

  5. Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能

    Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...

  6. Spring MVC 实现web Socket向前端实时推送数据

    最近项目中用到了webSocket服务,由后台实时向所有的前端推送消息,前端暂时是不可以发消息给后端的,数据的来源是由具体的设备数据收集器收集起来,然后通过socket推送给后端,后端收到数据后,再将 ...

  7. Android应用实现Push推送消息原理

            本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我 们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅 ...

  8. Android push推送消息到达成功率优化

    Android push推送消息到达成功率优化 问题:server向client发送消息.未考虑client是否在线,这种消息到达率是非常低的. 第一次优化:使用server离线缓存数据,推断假设cl ...

  9. Java Springboot webSocket简单实现,调接口推送消息到客户端socket

    Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...

随机推荐

  1. ABP源码分析十二:本地化

    本文逐个分析ABP中涉及到locaization的接口和类,以及相互之间的关系.本地化主要涉及两个方面:一个是语言(Language)的管理,这部分相对简单.另一个是语言对应得本地化资源(Locali ...

  2. ABP源码分析十五:ABP中的实用扩展方法

    类名 扩展的类型 方法名 参数 作用 XmlNodeExtensions XmlNode GetAttributeValueOrNull attributeName Gets an   attribu ...

  3. Java基础之IO流

    很长时间都没有更新了,最近在补充JavaSE的一些细节部分 关于IO流的一些总结 首先要介绍的是File类,File类用于对文件和目录的一些操作 1.创建文件CreateNewFile() 2.对文件 ...

  4. 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)

    在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...

  5. TSQL 分组集(Grouping Sets)

    分组集(Grouping Sets)是多个分组的并集,用于在一个查询中,按照不同的分组列对集合进行聚合运算,等价于对单个分组使用“union all”,计算多个结果集的并集.使用分组集的聚合查询,返回 ...

  6. 【Win 10应用开发】自定义浮动层——Flyout

    最近几天总是下雨,真是“何处秋窗无雨声”,也“不知风雨几时休”. 好,进入正题. 弹出层有三种. 第一种是ContentDialog,即内容对话框,它其实类似于模态对话框,弹出后会覆盖整个窗口区域,并 ...

  7. JS事件调试 - 查找HTML元素绑定的事件以及绑定代码所在位置

    日常的网页开发调试工作中,经常需要知道指定的某个网页元素绑定了哪些事件以及绑定代码的位置,下面介绍三种用来跟踪页面中的事件的方法. 1.使用firefox调试 我们可以使用firefox的debug工 ...

  8. 更改默认alert框体

    更改框体主要用到的是更改系统的内置控件winpop下面是winpop具体代码 (function(window, jQuery, undefined) { 2 3 var HTMLS = { 4 ov ...

  9. 《JavaScript 源码分析》之 maxlength.js

    /* @author: Terry @params: feedback - the selector for the element that gives the user feedback. Not ...

  10. 前端学HTTP之网络基础

    × 目录 [1]网络 [2]OSI [3]TCP/IP 前面的话 HTTP协议对于前端工程师是非常重要的.我们在浏览网站时,访问的每一个WEB页面都需要使用HTTP协议实现.如果不了解HTTP协议,就 ...