上篇介绍了跨进程实时通讯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为TV端助力 不需要Socket的跨进程推送消息AIDL!的更多相关文章

  1. android不需要Socket的跨进程推送消息AIDL!

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

  2. Android为TV端助力 史上最简单易懂的跨进程通讯(Messenger)!

    不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件! 只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递m ...

  3. 用JPUSH极光推送实现服务端向安装了APP应用的手机推送消息(C#服务端接口)

    这次公司要我们做一个功能,就是当用户成功注册以后,他登录以后要收到消息,当然这个消息是安装了我们的手机APP应用的手机咯. 极光推送的网站的网址是:https://www.jpush.cn/ 极光推送 ...

  4. Android为TV端助力 UDP协议

    废话不多说.直接上代码! 一. 接收端 1.创建UDP连接 public void init() { try { //开关的作用 isRunning = true; DatagramSocket mU ...

  5. Android IPC机制(五)用Socket实现跨进程聊天程序

    1.Socket简介 Socket也称作“套接字“,是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信.它分为流式套接字和数据包套接 ...

  6. Android为TV端助力 转载:RecyclerView分页加载

    package com.android.ryane.pulltoloaddata_recyclerview; import android.os.Handler;import android.os.L ...

  7. Android为TV端助力(转载)

    作者地址http://www.jianshu.com/u/63915ef020e2 针对Android Tv的自定义RecyclerView 作者 wenju_song 关注 2016.12.09 1 ...

  8. Android为TV端助力之Webview与JS双向交互

    package com.hhzt.iptv.adservice; import android.app.Activity;import android.graphics.Bitmap;import a ...

  9. Android为TV端助力之WebView开发踩坑一

    在Android清单配置文件里面 自定义application时,在4.4系统上面不能加上一个属性,见下图 否则界面将不会显示任何数据,在更高或者更低的系统上面没有测试!

随机推荐

  1. 推荐:7 月份值得一看的 Java 技术干货!

    月底了,又到了我们总结这一个月 Java 技术干货的时候了,又到了我们给粉丝免费送书的日子了. 7 月份干货总结 Oracle 发布了一个全栈虚拟机 GraalVM 一文带你深入拆解 Java 虚拟机 ...

  2. Python字符串的格式化,看这一篇就够了

    相信很多人在格式化字符串的时候都用"%s" % v的语法,PEP 3101 提出一种更先进的格式化方法 str.format() 并成为 Python 3 的标准用来替换旧的 %s ...

  3. RestyCircuitBreaker --- openresty断路器

    简介 由于某些场景下服务提供方和调用方都无法做到可用性,当系统远程调用时,可能会因为某些接口变慢导致调用方大量HTTP连接被阻塞而引发雪崩. 解决思路如下: 服务提供方实现接口快速失败,当处理时间达到 ...

  4. MySQL 分支的选择:Percona 还是 MariaDB

    原文:https://www.biaodianfu.com/mysql-percona-or-mariadb.html 在MySQL被Oracle收购以后,越来越多的人对于MySQL的前景表示了担忧, ...

  5. [Java Plasterer] Java Components 3:Java Enum

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. Written In The Font Whe ...

  6. leetcode — edit-distance

    /** * Source : https://oj.leetcode.com/problems/edit-distance/ * * * Given two words word1 and word2 ...

  7. Elasticsearch 集群和索引健康状态及常见错误说明

    之前在IDC机房线上环境部署了一套ELK日志集中分析系统, 这里简单总结下ELK中Elasticsearch健康状态相关问题, Elasticsearch的索引状态和集群状态传达着不同的意思. 一.  ...

  8. Go处理json数据

    json数据格式 参见json数据格式说明. 如果没操作过json数据,建议先看下上面的文章,有助于理解本文后面的内容. Go json包 Marshal():Go数据对象 -> json数据 ...

  9. LeetCode链表解题模板

    一.通用方法以及题目分类 0.遍历链表 方法代码如下,head可以为空: ListNode* p = head; while(p!=NULL) p = p->next; 可以在这个代码上进行修改 ...

  10. [转]windows BLE编程 net winform 连接蓝牙4.0

    本文转自:https://www.cnblogs.com/webtojs/p/9675956.html winform 程序调用Windows.Devices.Bluetoot API 实现windo ...