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.真实场景可能是后台程序在运行时(满足一定条件 ...
随机推荐
- 吸顶大法 -- UWP中的工具栏吸顶的实现方式之一
如果一个页面中有很长的列表/内容,很多应用都会在用户向下滚动时隐藏页面的头,给用户留出更多的阅读空间,同时提供一个方便的吸顶工具栏,比如淘宝中的店铺页面. 下面是一个比较简单的实现,如果有同学有更好的 ...
- 巧用location.hash保存页面状态
在我们的项目中,有大量ajax查询表单+结果列表的页面,由于查询结果是ajax返回的,当用户点击列表的某一项进入详情页之后,再点击浏览器回退按钮返回ajax查询页面,这时大家都知道查询页面的表单和结果 ...
- ABP框架 - 设置管理
文档目录 本节内容: 简介 关于ISettingStore 定义设置 setting scope(设置范围) 重写设置定义 获取设置值 服务端 客户端 修改设置 关于缓存 简介 每个应用必需存储一些设 ...
- Atitit 硬件 软件 的开源工作 差异对比
Atitit 硬件 软件 的开源工作 差异对比 1.1. 模块化,标准化,以及修改的便捷性1 1.2. 生产和发布成本 1 1.3. 3. 入行门槛搞2 1.4. 在软件业极度发达的今天,任何具 ...
- vue中,class、内联style绑定、computed属性
1.绑定Class ①对象语法 <li :class="{ 'active': activeIdx==0 }" @click="fnClickTab(0)" ...
- OPEN CASCADE编译视频
为了帮助OPEN CASCADE新手顺利编译OPEN CASCADE源码,特录制了一个视频, 有了这个视频,OPEN CASCADE的编译再也不麻烦啦!
- 通过一个实例理解 offsetLeft,offsetTop; offsetWidth , offsetHeight
obj.offsetTop 指 obj 相对于版面或由 offsetParent 属性指定的父坐标的计算上侧位置,整型 obj.offsetLeft 指 obj 相对于版面或由 offsetParen ...
- linq to entity常用操作
一.聚合函数查询 ; using (xxxEntities db = new xxxEntities()) { sum = db.userinfo.AsNoTracking().Where(d =&g ...
- C++程序员如何转Java
C++程序员如何转Java 忙里偷闲,到了这个时间终于得空写一篇早想写的文章.其实本文的标题有些不太准确,C++程序员写Java代码不是说就非得转行写Java,抛弃C++,而只是多了一个选择而已.两 ...
- 【QuickHit项目实例】
关于java面向对象QuickHit项目实例 Game类:用来得到随机出现的字符串(随机打印的字符串,然后玩家进行输入字符串) public class Game { private String s ...