zoukankan      html  css  js  c++  java
  • Android为TV端助力 不需要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,比如权限没加什么的!

     

  • 相关阅读:
    Java并发 --对象的共享
    建立一个二叉查找树
    Tomcat 服务优化
    Mina框架(实战详解)
    ES 查询实战
    IEDA安装配置
    Redis操作以及连接异常
    CyclicBarrier[进程同步辅助类]实现进程间同步
    Linux下端口占用解决方法
    物化视图插入记录,手动刷新问题
  • 原文地址:https://www.cnblogs.com/xiaoxiaing/p/5818857.html
Copyright © 2011-2022 走看看