Android WebSocket实现即时通讯/推送

From:http://blog.csdn.net/li352558693/article/details/42639683

使用java-websocket实现即时通讯/推送模块;

支持即时发消息和收消息,消息类型有开发者自定义;;

该模块需要websocket.jar的支持;开源项目地址--https://github.com/TooTallNate/Java-WebSocket

该开源项目支持客户端client和服务端server的配置使用,并提供示例test;


 

1,Android 客户端使用需要配置网络权限; 

2,需要写一个自己的client类来继承WebsocketClient;实现websocket的状态回调和新消息的解析动作;

3,需要监控自己的client的链接状态,维持长链接;

4,发送和接收


下面贴出部分相关代码;

网络权限的不用说了吧!

client类:

常用状态回调方法有4个

自己可以在对应的函数里面做响应的处理,比如当链接发生错误时要重新去打开该链接,收到消息时即时的保存聊天记录和发送系统通知来提醒用户查看新消息等等;

[html]  view plain  copy
  1. public class TestClient extends WebSocketClient {  
  2.   
  3.     public TestClient(URI serverURI) {  
  4.         super(serverURI);  
  5.     }  
  6.     /***  
  7.      * 链接关闭  
  8.      */  
  9.     @Override  
  10.     public void onClose(int arg0, String arg1, boolean arg2) {  
  11.   
  12.     }  
  13.     /***  
  14.      * 链接发生错误  
  15.      */  
  16.     @Override  
  17.     public void onError(Exception arg0) {  
  18.   
  19.     }  
  20.     /**  
  21.      * 新消息  
  22.      */  
  23.     @Override  
  24.     public void onMessage(String arg0) {  
  25.   
  26.     }  
  27.     /***  
  28.      * 链接打开  
  29.      */  
  30.     @Override  
  31.     public void onOpen(ServerHandshake arg0) {  
  32.         // TODO Auto-generated method stub  
  33.   
  34.     }  
  35. }  

 
 下面是我聊天部分代码,有离线消息/PC同步/多对多的聊天; 
  
 

仅供参考; copy

  1. /*** 
  2.  * <h2>WebSocket Android 客户端</h2> 
  3.  * <ol> 
  4.  * <li>Socket链接打开回调 {@link WebSocket#onOpen(ServerHandshake)},此处有 
  5.  * {@link SocketConstant#ON_OPEN} 广播发出; 
  6.  * <li>Socket链接出现异常错误时回调 {@link WebSocket#onError(Exception)},此处有 
  7.  * {@link SocketConstant#ON_ERROR}广播发出; 
  8.  * <li>Socket链接关闭回调 {@link WebSocket #onClose(int, String, boolean)},此处有 
  9.  * {@link SocketConstant#ON_CLOSES}广播发出; 
  10.  * <li>Socket链接接收消息回调 {@link WebSocket#onMessage(String)} 
  11.  * ,此处做收消息的逻辑的处理;包括发送消息服务器返回的发送结果,PC端同步接收的新消息,及外来的新消息; 
  12.  * <li>检测是否有消息遗漏 {@link WebSocket#checkMsgWebId(String, String)},参数为联系人和webId; 
  13.  * <li>取得正在桌面运行的activity的名称 {@link WebSocket#getRunningActivityName()} 
  14.  * <li>接收到的消息的处理 {@link WebSocket#messageHandle(MessageEntity, String)} 
  15.  * ,参数为消息实体和消息类型 (buyer/server) 
  16.  * <li>发送新消息的系统通知 {@link WebSocket#sendNotification(String)},参数为联系人; 
  17.  * <li>保存离线消息 {@link WebSocket#saveOffLineMsg(HashMap)},参数为接收到的离线消息集合; 
  18.  * <li>保存从服务端获取的联系人的webId {@link WebSocket#saveContactsWebID(HashMap)} 
  19.  * ,参数为以联系人为key以最大webId为值得map集合; 
  20.  * </ol> 
  21.  *  
  22.  * @author li'mingqi <a> 2014-3-19</a> 
  23.  *  
  24.  */  
  25. public class WebSocket extends WebSocketClient {  
  26.     // 登陆返回的back_type字段  
  27.     public static final String LOGIN_RETURN_TYPE = "login";  
  28.     // 发送信息的back_type字段  
  29.     public static final String SEND_RETURN_TYPE = "send_result";  
  30.     // 接收信息的back_type字段  
  31.     public static final String RECEIVER_RETURN_TYPE = "msg";  
  32.     // 接收客服的信息的back_type字段  
  33.     public static final String GET_SERVER_RETURN_TYPE = "server_info";  
  34.     // 接收服务端返回对应联系人的最大顺序ID  
  35.     public static final String CONTACTS_MAX_WEBID_TYPE = "max_id_return";  
  36.     // 接收用户的离线消息  
  37.     public static final String USER_OFFLINE_MSG_TYPE = "offline";  
  38.     // 上下文对象  
  39.     private Context mContext;  
  40.     // socket返回json解析类对象  
  41.     private WebSocketParser mParser;  
  42.     // 系统通知管理  
  43.     public NotificationManager mNotificationManager;  
  44.     // 系统通知  
  45.     private Notification mNoti;  
  46.     // 意图  
  47.     private PendingIntent mIntent;  
  48.     // 该系统通知的 id  
  49.     public static final int NOTIFICATION_ID = 100;  
  50.   
  51.     @SuppressWarnings("deprecation")  
  52.     public SGWebSocket(Context context, URI serverUri, Draft draft) {  
  53.         super(serverUri, draft);  
  54.         this.mContext = context;  
  55.                 //新消息的解析类  
  56.                 this.mParser = WebSocketParser.getInstance();  
  57.                 //收到新消息发送的通知  
  58.                 this.mNotificationManager = (NotificationManager) this.mContext  
  59.                 .getSystemService(Context.NOTIFICATION_SERVICE);  
  60.         this.mNoti = new Notification(R.drawable.system_info, "您有新消息!",  
  61.                 System.currentTimeMillis());  
  62.     }  
  63.   
  64.     /*** 
  65.      * send broadcast <SGSocketConstant>ON_CLOSES filter if this socket closed 
  66.      * socket 发生关闭时发送的广播,若想提示,可以接受并处理 
  67.      *  
  68.      */  
  69.     @Override  
  70.     public void onClose(int arg0, String arg1, boolean arg2) {  
  71.         // 更改保存的链接状态  
  72.         UserInfoUtil.saveSocket(mContext, false);  
  73.         mNotificationManager.cancelAll();  
  74.         Intent intent = new Intent(SocketConstant.ON_CLOSES);  
  75.         intent.putExtra(SocketConstant.ON_CLOSES, arg1.toString());  
  76.         mContext.sendBroadcast(intent);  
  77.     }  
  78.   
  79.     /*** 
  80.      * send broadcast <SGSocketConstant>ON_ERROR filter if this socket has error 
  81.      * socket 发生错误发送的广播,若想提示,可以接受并处理 
  82.      *  
  83.      */  
  84.     @Override  
  85.     public void onError(Exception arg0) {  
  86.         Intent intent = new Intent(SGSocketConstant.ON_ERROR);  
  87.         intent.putExtra(SGSocketConstant.ON_ERROR, arg0.toString());  
  88.         mContext.sendBroadcast(intent);  
  89.         this.close();  
  90.     }  
  91.   
  92.     // 买家  
  93.     public static final String MSG_BUYER_TYPE = "1";  
  94.     // 客服  
  95.     public static final String MSG_SERVCER_TYPE = "2";  
  96.   
  97.     // 游客  
  98.     // public static final String MSG_RANDOM_TYPE = "3";  
  99.   
  100.     /*** 
  101.      * receiver message from server 1,登陆返回 type 
  102.      * <WebSocket>LOGIN_RETURN_TYPE; 2,发送返回 type 
  103.      * <WebSocket>SEND_RETURN_TYPE; 3,接收信息返回 type 
  104.      * <WebSocket>RECEIVER_RETURN_TYPE; 
  105.      *  
  106.      * @throws InterruptedException 
  107.      */  
  108.     @Override  
  109.     public void onMessage(String content) {  
  110.         // parser  
  111.         try {  
  112.             JSONObject object = new JSONObject(content);  
  113.             Log.i("json""卖家--" + object.toString());  
  114.             String back_type = object.getString("back_type");  
  115.             String activity = getRunningActivityName();  
  116.             if (SEND_RETURN_TYPE.equals(back_type)) {// 发送具体消息时返回发送结果  
  117.                 // json解析  
  118.                 MessageEntity entity = mParser.sendMessageParser(mContext,  
  119.                         content);  
  120.                 if ("true".equals(entity.getSend_state())) {// 发送成功  
  121.                     // 判断是否是PC端发送的消息,若是PC端发送的消息,则在Android端做同步存储处理  
  122.                     // 1,首先判断数据库中是否包含该条信息  
  123.                     boolean has = MessageDB.getInstance(mContext)  
  124.                             .findMessageByMsgId(entity.get_id());  
  125.                     if (has) {  
  126.                         // Android端发送  
  127.                         MessageDB.getInstance(mContext).update(entity.get_id(),  
  128.                                 true, entity.getReceiverTime(),  
  129.                                 entity.getWebId());// 更新发送状态为已发送  
  130.                     } else {  
  131.                         // PC端发送,将该消息同步到Android端数据库  
  132.                         entity.setSend_state(SocketConstant.MSG_SEND_SUCCESS_STATE);  
  133.                         MessageDB.getInstance(mContext).insert(entity,  
  134.                                 SocketConstant.MSG_TYPE_BUYER);// 卖家发送给买家的  
  135.                         // 通知聊天主页面,更新聊天列表  
  136.                         pcSynAndroid(activity);  
  137.                     }  
  138.                     // 检测是否有消息遗漏  
  139.                     checkMsgWebId(entity.getContacts(), entity.getWebId());  
  140.                     Log.i("miss""发送返回或者PC同步--" + entity.getContacts() + "--"  
  141.                             + entity.getWebId());  
  142.                 } else if ("false".equals(entity.getSend_state())) {// 发送失败  
  143.                     MessageDB.getInstance(mContext).update(entity.get_id(),  
  144.                             false, entity.getReceiverTime(), entity.getWebId());  
  145.                     Toast.makeText(mContext, entity.getErrorText(),  
  146.                             Toast.LENGTH_SHORT).show();  
  147.                 }  
  148.                 // 登陆返回 记录session  
  149.             } else if (LOGIN_RETURN_TYPE.equals(back_type)) {  
  150.                 KApplication.session = object.getString("session_id");  
  151.                 String str = object.getString("login_status");  
  152.                 if ("true".equals(str)) {  
  153.                     UserInfoUtil.saveSocket(mContext, true);  
  154.                     // 生成json请求字符串  
  155.                     String maxIdstring = SocketJsonUtil  
  156.                             .getContactsCurrentWebId(UserInfoUtil  
  157.                                     .getUser(mContext)[0], "2", MessageDB  
  158.                                     .getInstance(mContext)  
  159.                                     .findAllContactsAndType());  
  160.                     // 登陆成功,向服务器索取联系人的最大webId  
  161.                     send(maxIdstring);  
  162.                     Log.i("send", maxIdstring);  
  163.                 } else if ("false".equals(str)) {  
  164.                     UserInfoUtil.saveSocket(mContext, false);  
  165.                 }  
  166.   
  167.             } else if (RECEIVER_RETURN_TYPE.equals(back_type)) {// 接收到的具体聊天的信息  
  168.                 // json解析  
  169.                 MessageEntity entity = mParser.receiverMessagePrser(mContext,  
  170.                         content);  
  171.                 // 判断数据库中是否有该条消息,有则不处理,无则处理消息;  
  172.                 if (!MessageDB.getInstance(mContext).findMessageByMsgId(  
  173.                         entity.get_id())) {  
  174.                     // 消息处理  
  175.                     if (MSG_BUYER_TYPE.equals(entity.getSenderType())) {  
  176.                         // 买家  
  177.                         messageHandle(entity, SocketConstant.MSG_TYPE_BUYER);  
  178.                     } else if (MSG_SERVCER_TYPE.equals(entity.getSenderType())) {  
  179.                         // 卖家,客服  
  180.                         messageHandle(entity, SocketConstant.MSG_TYPE_SERVER);  
  181.                     }  
  182.                     Log.i("miss""没有该条消息");  
  183.                     // 检测是否有消息遗漏  
  184.                     checkMsgWebId(entity.getContacts(), entity.getWebId());  
  185.                 }  
  186.             } else if (GET_SERVER_RETURN_TYPE.equals(back_type)) {// 获取闪聊客服返回的数据  
  187.                 // 客服  
  188.                 ServerEntity entity = mParser.serverInfoParser(content);// 客服对象  
  189.                 Intent intent = new Intent(SocketConstant.GET_SERVER_INFO);  
  190.                 intent.putExtra("server_info", entity);  
  191.                 mContext.sendBroadcast(intent);  
  192.             } else if (CONTACTS_MAX_WEBID_TYPE.equals(back_type)) {  
  193.                 // 返回的联系人最大的消息id  
  194.                 HashMap<String, String> map = mParser.contactsMaxWebId(content);  
  195.                 // 将联系人和其最大webId存入临时集合  
  196.                 saveContactsWebID(map);  
  197.                 // 开始请求服务器,释放离线消息给客户端;  
  198.                 send(SocketJsonUtil.getOffLine(  
  199.                         UserInfoUtil.getUser(mContext)[0], "2"));  
  200.                 Log.i("send",  
  201.                         SocketJsonUtil.getOffLine(  
  202.                                 UserInfoUtil.getUser(mContext)[0], "2"));  
  203.             } else if (USER_OFFLINE_MSG_TYPE.equals(back_type)) {  
  204.                 // 用户的离线消息  
  205.                 HashMap<String, ArrayList<MessageEntity>> map = mParser  
  206.                         .offLineMsg(mContext, content);  
  207.                 // 将离线消息入库  
  208.                 saveOffLineMsg(map);  
  209.             }  
  210.         } catch (JSONException e) {  
  211.             this.close();  
  212.         }  
  213.     }  
  214.   
  215.     /*** 
  216.      * send broadcast <SocketConstant>ON_OPEN filter if this socket opened 
  217.      * socket 打开时发送的广播,若想提示,可以接受并处理 
  218.      *  
  219.      */  
  220.     @Override  
  221.     public void onOpen(ServerHandshake arg0) {  
  222.         Intent intent = new Intent(SGSocketConstant.ON_OPEN);  
  223.         mContext.sendBroadcast(intent);  
  224.     }  
  225.   
  226.     /*** 
  227.      * 检测正在运行tasktop的activity 
  228.      * @return current running activity name 
  229.      *  
  230.      */  
  231.     private String getRunningActivityName() {  
  232.         ActivityManager activityManager = (ActivityManager) mContext  
  233.                 .getSystemService(Context.ACTIVITY_SERVICE);  
  234.         String runningActivity = activityManager.getRunningTasks(1).get(0).topActivity  
  235.                 .getClassName();  
  236.         return runningActivity;  
  237.     }  
  238.   
  239.     /*** 
  240.      * send notification for this contacts 
  241.      * 发送通知 
  242.      * @param contacts 
  243.      *  
  244.      */  
  245.     @SuppressWarnings("deprecation")  
  246.     private void sendNotification(String contacts) {  
  247.         Intent intent = new Intent(mContext, MainActivity.class);  
  248.         mIntent = PendingIntent.getActivity(mContext, 100, intent, 0);  
  249.         mNoti.flags = Notification.FLAG_AUTO_CANCEL;  
  250.         mNoti.defaults = Notification.DEFAULT_VIBRATE;  
  251.         mNoti.setLatestEventInfo(mContext, "标题""您有新消息!", mIntent);  
  252.         mNoti.contentView = new RemoteViews(mContext.getApplicationContext()  
  253.                 .getPackageName(), R.layout.notification_item);  
  254.         mNoti.contentView.setTextViewText(R.id.noti_message, "收到来自" + contacts  
  255.                 + "的新消息");  
  256.         mNotificationManager.notify(NOTIFICATION_ID, mNoti);  
  257.     }  
  258.   
  259.     /*** 
  260.      * 具体聊天收到的外来消息处理 
  261.      *  
  262.      * @param entity 
  263.      *            消息实体 
  264.      * @param messageType 
  265.      *            消息类型(买家/客服) 
  266.      */  
  267.     private void messageHandle(MessageEntity entity, String messageType) {  
  268.         String activity = getRunningActivityName();  
  269.         // 处于聊天的页面  
  270.         if ("com.ui.activity.ManageChartActivity".equals(activity)) {  
  271.             // 处于正在聊天对象的页面,将数据写入数据库,并发送广播更新页面数据  
  272.             if (KApplication.crurentContacts.equals(entity.getContacts())) {  
  273.                 /** 
  274.                  * 接收到的消息,消息实体entity的send_state字段状态设置为 
  275.                  * MSG_SEND_SUCCESS_STATE(即201) 
  276.                  **/  
  277.                 entity.setSend_state(SocketConstant.MSG_SEND_SUCCESS_STATE);// 收到的信息,设置信息的状态  
  278.                 entity.setRead(SocketConstant.READ_STATE);  
  279.                 MessageDB.getInstance(mContext).insert(entity, messageType);// 将数据写入数据库,  
  280.                 Intent intent = new Intent(SocketConstant.NEW_MESSAGE);  
  281.                 intent.putExtra("newmsg", entity);  
  282.                 mContext.sendBroadcast(intent);  
  283.                 // 没有处于闪聊对象的页面,将数据写入数据库,发送系统通知  
  284.             } else {  
  285.                 entity.setSend_state(SocketConstant.MSG_SEND_SUCCESS_STATE);// 收到的信息,设置信息的状态  
  286.                 entity.setRead(SocketConstant.DEFAULT_READ_STATE);  
  287.                 MessageDB.getInstance(mContext).insert(entity, messageType);  
  288.                 if (KApplication.sp.getBoolean(RefreshUtils.noteFlag, false)) {  
  289.                     sendNotification(entity.getContacts());  
  290.                 }  
  291.                 Intent intent = new Intent(  
  292.                         SocketConstant.RECEIVER_NEW_MESSAGE);  
  293.                 mContext.sendBroadcast(intent);  
  294.             }  
  295.             // 将数据写入数据库,发送系统通知  
  296.         } else {  
  297.             entity.setSend_state(SocketConstant.MSG_SEND_SUCCESS_STATE);// 收到的信息,设置信息的状态  
  298.             entity.setRead(SocketConstant.DEFAULT_READ_STATE);  
  299.             MessageDB.getInstance(mContext).insert(entity, messageType);  
  300.             Intent intent = new Intent();  
  301.             if ("com.ui.activity.ManageConversationActivity"  
  302.                     .equals(activity)  
  303.                     || "com.ui.activity.MainActivity"  
  304.                             .equals(activity)) {  
  305.                 intent.setAction(SocketConstant.RECEIVER_NEW_MESSAGE);// 聊天页面  
  306.             } else {  
  307.                 intent.setAction(SocketConstant.RECEIVER_NEW_MESSAGE_OTHER);// 其他页面  
  308.             }  
  309.             mContext.sendBroadcast(intent);  
  310.             if (KApplication.sp.getBoolean(RefreshUtils.noteFlag, false)) {  
  311.                 sendNotification(entity.getContacts());  
  312.             }  
  313.         }  
  314.           
  315.     }  
  316.   
  317.     /*** 
  318.      * 电脑与手机同步信息 
  319.      *  
  320.      * @param currentActivity 
  321.      */  
  322.     public void pcSynAndroid(String currentActivity) {  
  323.         if ("com.iflashseller.ui.activity.ManageChartActivity"  
  324.                 .equals(currentActivity)) {  
  325.             // 正好与该联系人对话的页面  
  326.             Intent intent = new Intent(SocketConstant.CHART_ACTIVITY);  
  327.             mContext.sendBroadcast(intent);  
  328.         } else {  
  329.             // 其他页面  
  330.             Intent intent = new Intent(SocketConstant.GROUPS_ACTIVITY);  
  331.             mContext.sendBroadcast(intent);  
  332.         }  
  333.     }  
  334.   
  335.     /*** 
  336.      * 检测是否有消息遗漏 
  337.      *  
  338.      * @param contacts 
  339.      *            联系人 
  340.      * @param webId 
  341.      *            服务端给出的消息Id 
  342.      */  
  343.     public void checkMsgWebId(String contacts, int webId) {  
  344.         // 集合中含有该联系人  
  345.         if (KApplication.webIds.containsKey(contacts)) {  
  346.             Log.i("miss""保存的--" + KApplication.webIds.get(contacts));  
  347.             // 临时集合中保存的webId  
  348.             int c = KApplication.webIds.get(contacts);  
  349.             /*** 
  350.              * 如果新收到的消息的webId大于临时集合中保存的改联系人的webId,且他们之间的差值大于1, 
  351.              * 则请求服务器推送疑似丢失的webId对应的消息 
  352.              */  
  353.             if (webId > c && (webId - 1) != c) {  
  354.                 // id不连续  
  355.                 for (int i = c + 1; i < webId; i++) {  
  356.                     // 向服务器发送请求,获取遗漏的消息  
  357.                     String miss = SocketJsonUtil.getMissMsg(  
  358.                             UserInfoUtil.getUser(mContext)[0], "2", contacts,  
  359.                             "1", i + "");  
  360.                     this.send(miss);  
  361.                     Log.i("miss", miss);  
  362.                 }  
  363.                 /*** 
  364.                  * 如果他们之间的差值正好为1,则修改临时集合的改联系人的webId, 
  365.                  */  
  366.             } else if (webId > c && (webId - 1) == c) {  
  367.                 KApplication.webIds.put(contacts, webId);  
  368.                 Log.i("miss""修改的--" + contacts + "--" + webId);  
  369.             }  
  370.             /**** 
  371.              * 临时集合中没有改联系人的信息,则将该联系人的webId存入临时集合. 
  372.              */  
  373.         } else {  
  374.             KApplication.webIds.put(contacts, webId);  
  375.             Log.i("miss""新增--" + contacts + "--" + webId);  
  376.         }  
  377.     }  
  378.   
  379.     /*** 
  380.      * 将从服务端获取的联系人的webId存入临时集合 
  381.      *  
  382.      * @param map 
  383.      */  
  384.     public void saveContactsWebID(HashMap<String, String> map) {  
  385.         Iterator<Entry<String, String>> iter = map.entrySet().iterator();  
  386.         while (iter.hasNext()) {  
  387.             Entry<String, String> es = iter.next();  
  388.             String contacts = es.getKey();  
  389.             String maxWebID = es.getValue();  
  390.             KApplication.webIds.put(contacts, Integer.parseInt(maxWebID));  
  391.         }  
  392.     }  
  393.   
  394.     /*** 
  395.      * 将离线消息入库 
  396.      *  
  397.      * @param map 
  398.      */  
  399.     public void saveOffLineMsg(HashMap<String, ArrayList<MessageEntity>> map) {  
  400.         Iterator<Entry<String, ArrayList<MessageEntity>>> iter = map.entrySet()  
  401.                 .iterator();  
  402.         while (iter.hasNext()) {  
  403.             ArrayList<MessageEntity> msgs = iter.next().getValue();  
  404.             for (int i = 0; i < msgs.size(); i++) {  
  405.                 threadSleep(100);  
  406.                 MessageDB.getInstance(mContext).insert(msgs.get(i),  
  407.                         SocketConstant.MSG_TYPE_BUYER);  
  408.                 Log.i("write""离线数据入库---" + msgs.get(i).toString());  
  409.             }  
  410.             /*** 
  411.              * 如果服务端一次释放的离线消息大于等于10条,则继续请求释放离线消息. 
  412.              */  
  413.             if (msgs.size() >= 10) {  
  414.                 send(SocketJsonUtil.getOffLine(  
  415.                         UserInfoUtil.getUser(mContext)[0], "2"));  
  416.                 Log.i("send",  
  417.                         SocketJsonUtil.getOffLine(  
  418.                                 UserInfoUtil.getUser(mContext)[0], "2"));  
  419.             }  
  420.         }  
  421.         // 一轮消息入库结束,发送通知,更新UI;  
  422.         mContext.sendBroadcast(new Intent(  
  423.                 SocketConstant.OFFLINE_MSG_RECEIVER_SUCCESS));  
  424.     }  
  425.   
  426.     private void threadSleep(long time) {  
  427.         try {  
  428.             Thread.currentThread();  
  429.             Thread.sleep(time);  
  430.         } catch (InterruptedException e) {  
  431.             e.printStackTrace();  
  432.         }  
  433.     }  
  434. }  
至于数据库的一部分代码就不贴出了,无非是增删改查。


下面贴出部分监控链接状态的代码,以保证能即时的收到消息;

[java]  view plain  copy
  1. public class LApplication extends Application {  
  2.   
  3.     public static String TAG = LApplication.class.getSimpleName();  
  4.     /** 接收消息广播 **/  
  5.     private LPullReceiver mPullReceiver;  
  6.     /** 是否是正在登录 **/  
  7.     public static boolean isLoging = false;  
  8.     /** socket管理类 **/  
  9.     private LPushManager mWebSocket;  
  10.       
  11.     @Override  
  12.     public void onCreate() {  
  13.         super.onCreate();  
  14.         /*** 
  15.          * 注册接收消息的广播 
  16.          */  
  17.         mPullReceiver = new LPullReceiver();  
  18.         // 广播过滤  
  19.         IntentFilter filter = new IntentFilter();  
  20.         // 时钟信息发生变化  
  21.         filter.addAction(Intent.ACTION_TIME_TICK);  
  22.         // 开机广播  
  23.         filter.addAction(Intent.ACTION_BOOT_COMPLETED);  
  24.         // 网络状态发生变化  
  25.         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);  
  26.         // 屏幕打开  
  27.         filter.addAction(Intent.ACTION_SCREEN_ON);  
  28.         // 注册广播  
  29.         registerReceiver(mPullReceiver, filter);  
  30.         // 实例化socket管理类  
  31.         mWebSocket = new LPushManager(getApplicationContext());  
  32.         // 应用重启一次,默认socket为关闭状态  
  33.         LPushUser.saveSocket(getApplicationContext(), false);  
  34.         // 默认链接没有被拒绝  
  35.         LPushUser.saveConnect(getApplicationContext(), false);  
  36.         // 1,获取当前时间  
  37.         long currentTime = System.currentTimeMillis();  
  38.         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  39.         Date date = new Date(currentTime);  
  40.         String time = sdf.format(date);  
  41.         // 修改标记的时间,保证5分钟内链接一次  
  42.         LPushUser.saveOpenTime(getApplicationContext(), time);  
  43.     }  
  44.   
  45.     /** 
  46.      * 广播接口类 
  47.      * <ol> 
  48.      * <li>接收时钟发生变化的广播 
  49.      * <li>接收网络发生变化的广播 
  50.      * <li>接收开机发送广播 
  51.      * <li>接收用户登录后发送的广播 
  52.      * </ol> 
  53.      *  
  54.      * @author li'mingqi 
  55.      *  
  56.      */  
  57.     class LPullReceiver extends BroadcastReceiver {  
  58.         @SuppressLint("SimpleDateFormat")  
  59.         @Override  
  60.         public void onReceive(Context context, Intent intent) {  
  61.             String action = intent.getAction();  
  62.             if (Intent.ACTION_TIME_TICK.equals(action)  
  63.                     || ConnectivityManager.CONNECTIVITY_ACTION.equals(action)  
  64.                     || Intent.ACTION_BOOT_COMPLETED.equals(action)  
  65.                     || Intent.ACTION_SCREEN_ON.equals(action)) {  
  66.   
  67.                 if (LPushUser.GETLOG(getApplicationContext()))  
  68.                     Log.i("lpush",  
  69.                             "socket的链接状态----"  
  70.                                     + LPushUser  
  71.                                             .getSocket(getApplicationContext())  
  72.                                     + "是否正在链接--" + isLoging + "----" + action);  
  73.                 // 当时钟或者网络发生变化或者socket关闭或者发生异常时或者开机 时,判断socket连接是否出现异常  
  74.                 if (!LPushUser.getSocket(getApplicationContext()) && !isLoging  
  75.                         && LPushUser.getSocketEnable(getApplicationContext())  
  76.                         && !"".equals(IP) && !"".equals(PORT)  
  77.                         && !LPushUser.getConnectState(getApplicationContext())) {  
  78.                     // 掉线,执行登录动作  
  79.                       
  80.                       
  81.                     if (LNetworkUtil.netIsEnable(getApplicationContext())) {  
  82.                         mWebSocket.secondMethod(IP, PORT);  
  83.                         // 开始登录了,标记打开时间  
  84.                         // 1,获取当前时间  
  85.                         long currentTime = System.currentTimeMillis();  
  86.                         SimpleDateFormat sdf = new SimpleDateFormat(  
  87.                                 "yyyy-MM-dd HH:mm:ss");  
  88.                         Date date = new Date(currentTime);  
  89.                         String time = sdf.format(date);  
  90.                         // 修改标记的时间,保证5分钟嗅探链接一次  
  91.                         LPushUser.saveOpenTime(getApplicationContext(), time);  
  92.                     }  
  93.                 } else {  
  94.                     // APP端已经处于链接正常状态 -----5分钟嗅探链接一次  
  95.                     // 1,获取当前时间  
  96.                     long currentTime = System.currentTimeMillis();  
  97.                     SimpleDateFormat sdf = new SimpleDateFormat(  
  98.                             "yyyy-MM-dd HH:mm:ss");  
  99.                     Date date = new Date(currentTime);  
  100.                     String time = sdf.format(date);  
  101.                     // 2,比对链接打开时间  
  102.                     long minTime = LStringManager.dateDifference(  
  103.                             LPushUser.getOpenTime(getApplicationContext()),  
  104.                             time);  
  105.                     if (LPushUser.GETLOG(getApplicationContext())) {  
  106.                         Log.i("lpush",  
  107.                                 "链接时长----现在时间:"  
  108.                                         + time  
  109.                                         + ";保存时间:"  
  110.                                         + LPushUser  
  111.                                                 .getOpenTime(getApplicationContext())  
  112.                                         + ";时差" + minTime + "分钟");  
  113.                     }  
  114.                     if (minTime >= 5) {  
  115.                         // 大于等于5分钟,则重新链接  
  116.                           
  117.                         // 5分钟之后重新链接  
  118.                         // 修改被拒绝状态  
  119.                         if (LPushUser.getConnectState(getApplicationContext())) {  
  120.                             LPushUser.saveConnect(getApplicationContext(),  
  121.                                     false);  
  122.                         }  
  123.                         if (LNetworkUtil.netIsEnable(getApplicationContext())  
  124.                                 && LPushUser  
  125.                                         .getSocketEnable(getApplicationContext())) {  
  126.                             mWebSocket.secondMethod(IP, PORT);  
  127.                             // 修改标记的时间,保证5分钟嗅探链接一次  
  128.                             LPushUser.saveOpenTime(getApplicationContext(),  
  129.                                     time);  
  130.                         }  
  131.                     }  
  132.                 }  
  133.             }  
  134.         }  
  135.     }  
  136.   
  137.     /*** 
  138.      * 设置推送功能的使用与否,默认使用推送功能,若是关闭推送功能请设置false; 
  139.      *  
  140.      * @param enable 
  141.      *            是否使用 
  142.      *  
  143.      *            li'mingqi  
  144.      */  
  145.     protected void setLPushEnable(boolean enable) {  
  146.         LPushUser.saveSocketEnable(getApplicationContext(), enable);  
  147.     }  
  148.   
  149.     /*** 
  150.      *  
  151.      *  
  152.      * @param ip 
  153.      *            ip信息 
  154.      * @param port 
  155.      *            端口信息 
  156.      *  
  157.      *            li'mingqi  
  158.      */  
  159.     protected void setSocketIPInfo(String ip, String port) {  
  160.         this.IP = ip;  
  161.         this.PORT = port;  
  162.     }  
  163.    
  164.   
  165.     /** 
  166.      * 设置用户的Uid 
  167.      *  
  168.      * @param uid 
  169.      *            li'mingqi  
  170.      */  
  171.     public void setUserInfo(int uid, String code) {  
  172.         /*** 
  173.          * 数据验证 
  174.          */  
  175.         // if (0 == uid || null == code || "".equals(code)) {  
  176.         // Log.e(TAG, "您输入的用户ID或者CODE值为空");  
  177.         // new NullPointerException("您输入的用户ID或者CODE值为空").printStackTrace();  
  178.         // return;  
  179.         // }  
  180.   
  181.         // 保存用户ID  
  182.         LPushUser.saveUserID(getApplicationContext(), uid);  
  183.         // 保存用户CODE  
  184.         LPushUser.saveUserCode(getApplicationContext(), code);  
  185.         // 重启链接  
  186.         mWebSocket.close();  
  187.     }  
  188.   
  189.     /*** 
  190.      * 设置是否查看日志 
  191.      *  
  192.      * @param flag 
  193.      *            是否查看日志 
  194.      * @version 1.2 li'mingqi 
  195.      */  
  196.     public void openLogInfo(boolean flag) {  
  197.         LPushUser.SAVELOG(getApplicationContext(), flag);  
  198.     }  
  199.   
  200.     /*** 
  201.      * socket链接重置,服务器一直处于拒绝链接状态,客户端链接一次遭拒后标记了遭拒的状态,重置之后可进行再次开启链接; 
  202.      *  
  203.      * @version 1.3 li'mingqi  
  204.      */  
  205.     private void reset() {  
  206.         LPushUser.saveConnect(getApplicationContext(), false);  
  207.     }  
  208. }  
UI界面显示部分就不贴出了,后面贴出Application类的目的就是监控各种手机系统的广播来嗅探自己的websocket链接的状态;用来维持它以保证能即时的收到消息;




  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值