在这里主要想实现服务端向App端推送消息,所以采用了Socket。

java端:

第一步:创建ServerSocketManager.java类,这个类是针对客户端和App端的连接和断开进行监听,读取并发送数据这几个功能的封装,具体代码如下:

public class ServerSocketManager { //ServerSocketManager.java开始
private static ServerSocketManager manager;
 // 存储客户端ip-SocketChannel
 private static Map<String, SocketChannel> map;
 // 连接监听
 private static SelectorLoop connectionBell;
 // 读取监听
 private static List<SelectorLoop> readBells;
 private ServerSocketChannel ssc;
 // 标识是否已经开启读取客户端数据的线程
 public boolean isReadBellRunning = false;
 // 客户端连接断开监听
 private List<OnClientListener> clientListeners;
 // 接收客户端信息监听
 private List<OnReceivedMessageListener> messageListeners; public void addOnClientListener(OnClientListener clientListener) {
  if (!this.clientListeners.contains(clientListener)) {
   this.clientListeners.add(clientListener);
  }
 } public void removeClientListener(OnClientListener clientListener) {
  this.clientListeners.remove(clientListener);
 } public void addOnReveicedMessageListener(
   OnReceivedMessageListener messageListener) {
  if (!this.messageListeners.contains(messageListener)) {
   this.messageListeners.add(messageListener);
  }
 } public void removeOnReveicedMessageListener(
   OnReceivedMessageListener messageListener) {
  this.messageListeners.remove(messageListener);
 } private ServerSocketManager() {
  map = new HashMap<String, SocketChannel>();
  clientListeners = new LinkedList<OnClientListener>();
  messageListeners = new LinkedList<ServerSocketManager.OnReceivedMessageListener>();
 } public synchronized static ServerSocketManager getInstance() {
  if (manager == null) {
   manager = new ServerSocketManager();
  }
  return manager;
 } public void startServer(String host, int port) throws IOException {
  System.out.println("-------ip-----" + host);
  readBells = new LinkedList<ServerSocketManager.SelectorLoop>();
  connectionBell = new SelectorLoop();
  // 开启一个server channel来监听
  ssc = ServerSocketChannel.open();
  // 开启非阻塞模式
  ssc.configureBlocking(false);
  ServerSocket socket = ssc.socket();
  socket.bind(new InetSocketAddress(host, port));
  // 给闹钟规定好要监听报告的事件,这个闹钟只监听新连接事件.
  ssc.register(connectionBell.getSelector(), SelectionKey.OP_ACCEPT);
  new Thread(connectionBell).start();
 } public class SelectorLoop implements Runnable {
  private Selector selector;
  private ByteBuffer temp = ByteBuffer.allocate(1024);
  private boolean stop;
  private boolean using;  public boolean isUsing() {
   return using;
  }  public SelectorLoop() throws IOException {
   this.selector = Selector.open();
  }  public Selector getSelector() {
   return this.selector;
  }  public void stop() throws IOException {
   this.stop = true;
   if (this.selector.isOpen()) {
    this.selector.close();
    this.selector = null;
   }
  }  @Override
  public void run() {
   using = true;
   while (!stop) {
    System.out.println("-----------");
    try {
     // 阻塞,只有当至少一个注册的事件发生的时候才会继续.
     if (this.selector.select() > 0) {
      Set<SelectionKey> selectKeys = this.selector
        .selectedKeys();
      Iterator<SelectionKey> it = selectKeys.iterator();
      while (it.hasNext()) {
       SelectionKey key = it.next();
       it.remove();
       // 处理事件. 可以用多线程来处理.
       this.dispatch(key);
      }
     }
    } catch (IOException e) {
     e.printStackTrace();
    } catch (InterruptedException e) {
     e.printStackTrace();
    } catch (Exception e) {    }
   }
   stop = true;
  }  public void dispatch(SelectionKey key) throws IOException,
    InterruptedException {
   System.out.println("-----dispatch----------");
   // 测试此键的通道是否已准备好接受新的套接字连接。
   if (key.isAcceptable()) {
    System.out.println("-----isAcceptable----------");
    // 这是一个connection accept事件, 并且这个事件是注册在serversocketchannel上的.
    // 返回创建此键的通道
    ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
    // 接受一个连接.
    SocketChannel sc = ssc.accept();
    // 对新的连接的channel注册read事件. 使用readBell闹钟.
    sc.configureBlocking(false);
    SelectorLoop readBell = new SelectorLoop();
    readBells.add(readBell);
    sc.register(readBell.getSelector(), SelectionKey.OP_READ);
    String host = ((InetSocketAddress) sc.getRemoteAddress())
      .getHostString(); int port=((InetSocketAddress) sc.getRemoteAddress()).getPort();//部署在外网时,需要获取随机的端口
    host=host+":"+port; 
    // 存放连接的socket
    map.put(host, sc);
    if (!clientListeners.isEmpty()) {
     // 触发连接监听
     for (OnClientListener cl : clientListeners) {
      cl.onConnected(host);
     }
    }
    // 如果读取线程还没有启动,那就启动一个读取线程.
    // synchronized (ServerSocketManager.this) {
    // if (!ServerSocketManager.this.isReadBellRunning) {
    // ServerSocketManager.this.isReadBellRunning = true;
    new Thread(readBell).start();
    // }
    // }
   } else if (key.isReadable()) {
    // 这是一个read事件,并且这个事件是注册在socketchannel上的.
    SocketChannel sc = (SocketChannel) key.channel();
    String host = ((InetSocketAddress) sc.getRemoteAddress())
      .getHostString();    int port=((InetSocketAddress) sc.getRemoteAddress()).getPort();//部署在外网时,需要获取随机的端口
    host=host+":"+port;
    // 写数据到buffer
    int count = sc.read(temp);
    System.out.println("-------count-------" + count);
    if (count < 0) {
     map.remove(host);
     stop();
     if (!clientListeners.isEmpty()) {
      for (OnClientListener cl : clientListeners) {
       cl.onDisconnected(host);
      }
     }
     // 客户端已经断开连接.
     key.cancel();
     sc.close();
     return;
    }
    // 切换buffer到读状态,内部指针归位.
    temp.flip();
    String msg = Charset.forName("UTF-8").decode(temp).toString();
    // 清空buffer
    temp.clear();
    if (msg != null && !"".equals(msg)
      && !messageListeners.isEmpty()) {
     for (OnReceivedMessageListener rml : messageListeners) {
      rml.onReceivedMessage(host, msg);
     }
    }
   }
  }
 } public void stop() {
  try {
   // if (readBell != null) {
   // readBell.stop();
   // }
   if (connectionBell != null) {
    connectionBell.stop();
   }
   if (ssc != null && ssc.isOpen()) {
    ssc.close();
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }/**
  * 发送信息
  * 
  * @param host
  * @param msg
  * @throws IOException
  */
 public int sendMessage(String host, byte[] msg) throws IOException {
  System.out.println("host====" + host);
  SocketChannel sc = map.get(host);
  int retnum = 0;
  if (sc == null) {
   // System.out.println("--------发送失败,未找到对应的连接信息---------");
   return 0;
  }
  if (sc.isConnected()) {
   // echo back.
   sc.write(ByteBuffer.wrap(msg));
   retnum = 1;
  } else {
   System.out.println("---SocketChannel未开启--");
   retnum = -1;
  }
  return retnum;
 } /**
  * 发送信息
  * 
  * @param host
  * @param msg
  * @param charset
  * @throws IOException
  */
 public int sendMessage(String host, String msg, String charset)
   throws IOException {
  return sendMessage(host, msg.getBytes(charset));
 } /**
  * 发送信息 charset default utf-8
  * 
  * @param host
  * @param msg
  * @throws IOException
  */
 public int sendMessage(String host, String msg) throws IOException {
  return sendMessage(host, msg.getBytes("UTF-8"));
 } /**
  * 监听客户端连接和断开
  * 
  * @author YJH
  * 
  */
 public interface OnClientListener {
  /**
   * 有客户端连接时调用
   * 
   * @param host
   */
  void onConnected(String host);  /**
   * 有客户端断开连接时调用
   * 
   * @param host
   */
  void onDisconnected(String host);
 } /**
  * 监听客户端发送来的消息
  * 
  * @author YJH
  * 
  */
 public interface OnReceivedMessageListener {
  /**
   * 接收到消息
   * 
   * @param host
   *            客户端ip
   * @param msg
   *            客户端信息
   */
  void onReceivedMessage(String host, String msg);
 }
} //ServerSocketManager.java结束

第二步:把方法封装完后,接下来,我们就可以在其它类里调用这些方法了,创建ServerSocketService.java类,代码如下:

@Service    //ServerSocketService.java开始
public class ServerSocketService {
 @Resource
 private FrameDao frameDao; public void setFrameDao(FrameDao frameDao) {
  this.frameDao = frameDao;
 } private ServerSocketManager manager;
 private OnClientListener clientListener = new OnClientListener() {  @Override
  public void onDisconnected(String host) {
   System.out.println("断开:" + host);   //断开连接时要做的操作写这里
  }  @Override
  public void onConnected(String host) {
   System.out.println("接入:" + host);
   //连接上时要做的操作写这里
  }
 }; private OnReceivedMessageListener messageListener = new OnReceivedMessageListener() {
  @Override   //host是接入的ip,msg是接收到的信息
  public void onReceivedMessage(String host, String msg) {
   System.out.println("----msg--------" + msg);
   RequestData data = JSON.parseObject(msg,
     new TypeReference<RequestData>() {     //自定义的类:RequestData
     });
   Map<String, String> datamap = data.getData();
   String lightid = datamap.get("lightid");
   String projectname = datamap.get("projectname");
   String mac=datamap.get("mac");
   int act = data.getAct();// 操作id,是App端发送过来的值
   System.out.println(act + "----act---");
   switch (act) {
   case 1:
     //如果是操作标志是1的话进行的操作
    break;
   case 2:
     //如果是操作标志是2的话进行的操作
    break;   default:
    break;
   }  }
 }; {
  try {
   manager = ServerSocketManager.getInstance();
   manager.addOnClientListener(clientListener);
   manager.addOnReveicedMessageListener(messageListener);
   String ip = IP.getInstance().getAcceptIp();
   if (ip != null && !"".equals(ip)) {
    manager.startServer(ip, 9090);// ip是服务器的ip
    System.out.println("-------ServerSocketManager------");
   } else {
    System.out.println("-------读取ip配置失败------");
   }
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 } public String sendMessage(String projectid, String light) {
//推送的信息一般是JSON类型,转换可以使用fastjson
 //获的要推送的信息frameInfo
   List<FrameInfo> frameInfo = frameDao.pushFrameInfo(
     Integer.parseInt(projectid), lights[i]);
   try {
    int num = manager.sendMessage(frameInfo.get(0).getIp(),
      JSON.toJSONString(frameInfo));
    if (num == 1) {
     msg = "推送成功";
    } else if (num == 0) {
     msg = "发送失败,未找到对应的连接信息";
    } else {
     msg = "Socket连接未开启";
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
  return msg;
 }}  //ServerSocketService.java结束

第三步:创建RequestData.java类:

public class RequestData {
 private Integer act;//操作
 private Map<String, String> data;
 public Integer getAct() {
  return act;
 }
 public void setAct(Integer act) {
  this.act = act;
 }
 public Map<String, String> getData() {
  return data;
 }
 public void setData(Map<String, String> data) {
  this.data = data;
 }
 public RequestData() {
  super();
  // TODO Auto-generated constructor stub
 }
 public RequestData(Integer act, Map<String, String> data) {
  super();
  this.act = act;
  this.data = data;
 }


}

到此java服务器端完成,接下来android端

第一步:创建ClientManager.java类:

public class ClientManager {

    private static ClientManager manager;
    private SocketChannel socketChannel;
    private SelectorLoop readBell;
    private OnConnectedListener connectedListener;
    private OnReceivedMessageListener messageListener;
    private ByteBuffer temp = ByteBuffer.allocate(1024);

    public void setOnReceivedMessageListener(OnReceivedMessageListener messageListener) {
        this.messageListener = messageListener;
    }

    public void setOnConnectedListener(OnConnectedListener connectedListener) {
        this.connectedListener = connectedListener;
    }

    private ClientManager() {
    }

    public static ClientManager getInstance() {
        if (manager == null) {
            manager = new ClientManager();
        }
        return manager;
    }

    public void sendMessage(String msg, String charset) {
        sendMessage(msg.getBytes(Charset.forName(charset)));
    }

    public void sendMessage(String msg) {
        Log.e("aaa",msg+"--sendMessage---");
        sendMessage(msg.getBytes(Charset.forName("UTF-8")));
    }

    public void sendMessage(final byte[] msg) {
        new Thread() {
            @Override
            public void run() {
                try {
                    if(socketChannel.isConnected()) {
                        socketChannel.write(ByteBuffer.wrap(msg));
                    }else{
                        Log.e("aaaa","-------连接已断开------");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void start(final String host, final int port) {
        new Thread() {
            @Override
            public void run() {
                try {
                    readBell = new SelectorLoop();
                    // 连接远程server
                    socketChannel = SocketChannel.open();
                    boolean isConnected;
                    while (true) {
                        try {
                            isConnected = socketChannel.connect(new InetSocketAddress(host, port));
                            break;
                        } catch (Exception e) {
                            Thread.sleep(1000);
                        }
                    }
                    socketChannel.configureBlocking(false);
                    SelectionKey key = socketChannel.register(readBell.getSelector(), SelectionKey.OP_READ);
                    if (isConnected) {
                        if (connectedListener != null) {
                            connectedListener.onConnected();
                        }
                    } else {
                        key.interestOps(SelectionKey.OP_CONNECT);
                    }
                    new Thread(readBell).start();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    class SelectorLoop implements Runnable {
        private Selector selector;
        private boolean stop;

        public SelectorLoop() throws IOException {
            this.selector = Selector.open();
        }

        public Selector getSelector() {
            return this.selector;
        }

        public void stop() throws IOException {
            this.stop = true;
            if (this.selector.isOpen()) {
                this.selector.close();
            }
        }

        @Override
        public void run() {
            while (!stop) {
                try {
                    if (this.selector.select() > 0) {
                        Log.e("aaaa", "--------有数据读取------");
                        Set<SelectionKey> keys = this.selector.selectedKeys();
                        Iterator<SelectionKey> it = keys.iterator();
                        while (it.hasNext()) {
                            SelectionKey key = it.next();
                            it.remove();
                            dispatchSelectionKey(key);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void dispatchSelectionKey(SelectionKey key) throws IOException {
        if (key.isConnectable()) {
            // socket connected
            SocketChannel sc = (SocketChannel) key.channel();
            // 判断此通道上是否正在进行连接操作。
            // 完成套接字通道的连接过程。
            boolean f = sc.isConnectionPending();
            if (f) {
                boolean d = sc.finishConnect();
                Log.e("aaaa", "=====finishConnect=====" + d);
                if (d && connectedListener != null) {
                    connectedListener.onConnected();
                }
            } else {
                Log.e("aaaa", "连接已断开");
                stop();
            }
        } else if (key.isReadable()) {
            // msg received.
            SocketChannel sc = (SocketChannel) key.channel();
            int count = sc.read(temp);
            if (count < 0) {//连接断开
                stop();
                return;
            }
            // 切换buffer到读状态,内部指针归位.
            temp.flip();
            String msg = Charset.forName("UTF-8").decode(temp).toString();
            if (messageListener != null) {
                messageListener.onReceivedMessage(msg);
            }
            // 清空buffer
            temp.clear();
        }
    }

    public void stop() throws IOException {
        if (connectedListener != null) {
            connectedListener.onDisconnected();
        }
        readBell.stop();
        if (socketChannel != null)
            socketChannel.close();
    }

    public interface OnConnectedListener {

        void onConnected();

        void onDisconnected();
    }

    /**
     * 监听客户端发送来的消息
     *
     * @author zz
     */
    public interface OnReceivedMessageListener {
        /**
         * 接收到消息
         *
         * @param msg 客户端信息
         */
        void onReceivedMessage(String msg);
    }
}

第二步:创建SocketService.java类:

public class SocketService {
    private static ClientManager.OnConnectedListener connectedLis = new ClientManager.OnConnectedListener() {
        @Override
        public void onConnected() {
            Log.e("aaaa", "-----Connected-----");
            JSONObject jo = new JSONObject();
            jo.put("act",1);
            jo.put("data",App.getConfig());
            ClientManager.getInstance().sendMessage(jo.toJSONString());
        }

        @Override
        public void onDisconnected() {
            Log.e("aaaa", "-----Disconnected-----");
        }
    };

    private static ClientManager.OnReceivedMessageListener messageLis = new ClientManager.OnReceivedMessageListener() {
        @Override
        public void onReceivedMessage(String msg) {
            Log.e("aaaa", "---msg----" + msg);
            List<FrameInfo> infos = JSON.parseObject(msg, new TypeReference<List<FrameInfo>>() {
            });
            if (infos == null || infos.isEmpty())
                return;
            try {
                ActiveAndroid.beginTransaction();
                DBUtil.clearImageByType(1);
                for (FrameInfo info : infos) {
                    info.setReserve(1);
                    info.save();
                }
                EventBus.getDefault().post(infos);
                ActiveAndroid.setTransactionSuccessful();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                ActiveAndroid.endTransaction();
            }
        }
    };

    public static void startService(String host, String port) {
        ClientManager manager = ClientManager.getInstance();
        manager.setOnConnectedListener(connectedLis);
        manager.setOnReceivedMessageListener(messageLis);
        manager.start(host, Integer.parseInt(port));
    }

    public static void stop() {
        try {
            ClientManager.getInstance().stop();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
第三步:在MainActivity.java类中调用开始方法



SocketService.startService("192.168.0.123","9090");