android不需要Socket的跨进程推送消息AIDL!
上篇介绍了跨进程实时通讯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!的更多相关文章
- Android为TV端助力 不需要Socket的跨进程推送消息AIDL!
上篇介绍了跨进程实时通讯http://www.cnblogs.com/xiaoxiaing/p/5818161.html 但是他有个缺点就是服务端无法推送消息给客户端,今天这篇文章主要说的就是服务器推 ...
- Android 心跳包心跳连接 如何实现android和服务器长连接呢?推送消息的原理
前言:现在的大多数移动端应用都有实时得到消息的能力,简单来说,有发送消息的主动权和接受消息的被动权.例如:微信,QQ,天气预报等等,相信好处和用户体验相信大家都知道吧. 提出问题:这种功能必须涉及cl ...
- Android:开机自启动并接收推送消息
接收推送消息部分我们通过ZeroMQ实现,可以参考http://www.cnblogs.com/ilovewindy/p/3984283.html. 首先是开机自启动的功能实现,代码如下:1. ...
- Android APP切换到后台接收不到推送消息
1. Android端进程被杀死后,目前自带的保护后台接收消息活跃机制.暂时没有什么好的机制保持任何情况下都活跃 android原生系统用home键杀进程可以起来,如果是强行停止就只能用户自己手动 ...
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 我的本意是第二篇写Mob的shareSD ...
- Spring MVC 实现web Socket向前端实时推送数据
最近项目中用到了webSocket服务,由后台实时向所有的前端推送消息,前端暂时是不可以发消息给后端的,数据的来源是由具体的设备数据收集器收集起来,然后通过socket推送给后端,后端收到数据后,再将 ...
- Android应用实现Push推送消息原理
本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我 们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅 ...
- Android push推送消息到达成功率优化
Android push推送消息到达成功率优化 问题:server向client发送消息.未考虑client是否在线,这种消息到达率是非常低的. 第一次优化:使用server离线缓存数据,推断假设cl ...
- Java Springboot webSocket简单实现,调接口推送消息到客户端socket
Java Springboot webSocket简单实现,调接口推送消息到客户端socket 后台一般作为webSocket服务器,前台作为client.真实场景可能是后台程序在运行时(满足一定条件 ...
随机推荐
- 学习笔记:Maven构造版本号的方法解决浏览器缓存问题
需要解决的问题 在做WEB系统开发时,为了提高性能会利用浏览器的缓存功能,其实即使不显式的申明缓存,现代的浏览器都会对静态文件(js.css.图片之类)缓存.但也正因为这个问题导致一个问题,就是资源的 ...
- ASP.NET 5 Beta 8 发布
ASP.NET 5 的路线图(详见 ASP.NET 5 Schedule and Roadmap : https://github.com/aspnet/home/wiki/roadmap ):Bet ...
- 关于领域驱动设计(DDD)中聚合设计的一些思考
关于DDD的理论知识总结,可参考这篇文章. DDD社区官网上一篇关于聚合设计的几个原则的简单讨论: 文章地址:http://dddcommunity.org/library/vernon_2011/, ...
- Linux C++ 开发简介
主要介绍将Windows程序迁移到Linux系统相关知识 简介 Windows程序迁移到Linux系统可能需要修改很多代码, 既需要了解Linux平台的开发知识, 也需要了解Windows平台代码如何 ...
- ABP源码分析十九:Auditing
审计跟踪(也叫审计日志)是与安全相关的按照时间顺序的记录,它们提供了活动序列的文档证据,这些活动序列可以在任何时间影响一个特定的操作. AuditInfo:定义如下图中需要被Audit的信息. Aud ...
- Cookie和Session的总结
1.开篇 在之前学习这一段的时候我一直有点没弄清楚,其实对Session这块的理解还可以,但是Cookie感觉始终还是欠缺点火候.之后的很长一段时间都基本上很少用Cookie了,渐渐的也淡忘了这一块的 ...
- LATEX数学公式基本语法
TEX 是Donald E. Knuth 编写的一个以排版文章及数学公式为目标的计算机程序.TEX的版本号不断趋近于π,现在为3.141592.由Pascal 语言写成,特点: 免费.输出质量高.擅长 ...
- 利用select实现IO多路复用TCP服务端
一.相关函数 1. int select(int maxfdp, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeva ...
- ElasticSearch 5学习(4)——简单搜索笔记
空搜索: GET /_search hits: total 总数 hits 前10条数据 hits 数组中的每个结果都包含_index._type和文档的_id字段,被加入到_source字段中这意味 ...
- Log4net入门(ASP.NET MVC 5篇)
在前4篇Log4net入门文章中,我们讲述了log4net的一些简单用法,在这一篇中我们主要讲述如何在ASP.NET MVC 5项目中将日志信息写入SQL Server数据库中. 一.创建最简单的AS ...