MQTT实现消息推送

来源:互联网 发布:明代男子服饰知乎 编辑:程序博客网 时间:2024/04/29 12:07

MQTT实现消息接收(接收消息需实现MqttSimpleCallback接口并实现它的publishArrived方法)必须注册接收消息方法

[java] view plain copy
  1. mqttClient.registerSimpleHandler(simpleCallbackHandler);// 注册接收消息方法  

和订阅接主题

[java] view plain copy
  1. mqttClient.subscribe(TOPICS, QOS_VALUES);// 订阅接主题  

 

 

服务端:

[java] view plain copy
  1. package com.gmcc.kuchuan.business;  
  2.   
  3. import org.apache.commons.logging.Log;  
  4. import org.apache.commons.logging.LogFactory;  
  5.   
  6. import com.ibm.mqtt.MqttClient;  
  7. import com.ibm.mqtt.MqttException;  
  8. import com.ibm.mqtt.MqttSimpleCallback;  
  9.   
  10. /** 
  11.  * MQTT消息发送与接收 
  12.  * @author Join 
  13.  * 
  14.  */  
  15. public class MqttBroker {  
  16.     private final static Log logger = LogFactory.getLog(MqttBroker.class);// 日志对象  
  17.     // 连接参数  
  18.     private final static String CONNECTION_STRING = "tcp://localhost:9901";  
  19.     private final static boolean CLEAN_START = true;  
  20.     private final static short KEEP_ALIVE = 30;// 低耗网络,但是又需要及时获取数据,心跳30s  
  21.     private final static String CLIENT_ID = "master";// 客户端标识  
  22.     private final static int[] QOS_VALUES = { 0020 };// 对应主题的消息级别  
  23.     private final static String[] TOPICS = { "Test/TestTopics/Topic1",  
  24.             "Test/TestTopics/Topic2""Test/TestTopics/Topic3",  
  25.             "client/keepalive" };  
  26.     private static MqttBroker instance = new MqttBroker();  
  27.   
  28.     private MqttClient mqttClient;  
  29.   
  30.     /** 
  31.      * 返回实例对象 
  32.      *  
  33.      * @return 
  34.      */  
  35.     public static MqttBroker getInstance() {  
  36.         return instance;  
  37.     }  
  38.   
  39.     /** 
  40.      * 重新连接服务 
  41.      */  
  42.     private void connect() throws MqttException {  
  43.         logger.info("connect to mqtt broker.");  
  44.         mqttClient = new MqttClient(CONNECTION_STRING);  
  45.         logger.info("***********register Simple Handler***********");  
  46.         SimpleCallbackHandler simpleCallbackHandler = new SimpleCallbackHandler();  
  47.         mqttClient.registerSimpleHandler(simpleCallbackHandler);// 注册接收消息方法  
  48.         mqttClient.connect(CLIENT_ID, CLEAN_START, KEEP_ALIVE);  
  49.         logger.info("***********subscribe receiver topics***********");  
  50.         mqttClient.subscribe(TOPICS, QOS_VALUES);// 订阅接主题  
  51.   
  52.         logger.info("***********CLIENT_ID:" + CLIENT_ID);  
  53.         /** 
  54.          * 完成订阅后,可以增加心跳,保持网络通畅,也可以发布自己的消息 
  55.          */  
  56.         mqttClient.publish("keepalive""keepalive".getBytes(), QOS_VALUES[0],  
  57.                 true);// 增加心跳,保持网络通畅  
  58.     }  
  59.   
  60.     /** 
  61.      * 发送消息 
  62.      *  
  63.      * @param clientId 
  64.      * @param messageId 
  65.      */  
  66.     public void sendMessage(String clientId, String message) {  
  67.         try {  
  68.             if (mqttClient == null || !mqttClient.isConnected()) {  
  69.                 connect();  
  70.             }  
  71.   
  72.             logger.info("send message to " + clientId + ", message is "  
  73.                     + message);  
  74.             // 发布自己的消息  
  75.             mqttClient.publish("GMCC/client/" + clientId, message.getBytes(),  
  76.                     0false);  
  77.         } catch (MqttException e) {  
  78.             logger.error(e.getCause());  
  79.             e.printStackTrace();  
  80.         }  
  81.     }  
  82.   
  83.     /** 
  84.      * 简单回调函数,处理server接收到的主题消息 
  85.      *  
  86.      * @author Join 
  87.      *  
  88.      */  
  89.     class SimpleCallbackHandler implements MqttSimpleCallback {  
  90.   
  91.         /** 
  92.          * 当客户机和broker意外断开时触发 可以再此处理重新订阅 
  93.          */  
  94.         @Override  
  95.         public void connectionLost() throws Exception {  
  96.             // TODO Auto-generated method stub  
  97.             System.out.println("客户机和broker已经断开");  
  98.         }  
  99.   
  100.         /** 
  101.          * 客户端订阅消息后,该方法负责回调接收处理消息 
  102.          */  
  103.         @Override  
  104.         public void publishArrived(String topicName, byte[] payload, int Qos,  
  105.                 boolean retained) throws Exception {  
  106.             // TODO Auto-generated method stub  
  107.             System.out.println("订阅主题: " + topicName);  
  108.             System.out.println("消息数据: " + new String(payload));  
  109.             System.out.println("消息级别(0,1,2): " + Qos);  
  110.             System.out.println("是否是实时发送的消息(false=实时,true=服务器上保留的最后消息): "  
  111.                     + retained);  
  112.         }  
  113.   
  114.     }  
  115.   
  116.     public static void main(String[] args) {  
  117.         new MqttBroker().sendMessage("client""message");  
  118.     }  
  119. }  


 

 

Android客户端:

核心代码:MQTTConnection内部类

[java] view plain copy
  1. <pre class="java" name="code">import java.io.ByteArrayInputStream;  
  2. import java.io.File;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.RandomAccessFile;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.URL;  
  8. import java.util.ArrayList;  
  9. import java.util.Timer;  
  10. import java.util.TimerTask;  
  11.   
  12. import android.app.AlarmManager;  
  13. import android.app.Notification;  
  14. import android.app.NotificationManager;  
  15. import android.app.PendingIntent;  
  16. import android.app.Service;  
  17. import android.content.BroadcastReceiver;  
  18. import android.content.Context;  
  19. import android.content.Intent;  
  20. import android.content.IntentFilter;  
  21. import android.content.SharedPreferences;  
  22. import android.database.Cursor;  
  23. import android.net.ConnectivityManager;  
  24. import android.net.NetworkInfo;  
  25. import android.os.Binder;  
  26. import android.os.Bundle;  
  27. import android.os.IBinder;  
  28. import android.provider.ContactsContract;  
  29. import android.util.Log;  
  30. //此部分项目导包已被删除</pre><pre class="java" name="code">import com.ibm.mqtt.IMqttClient;  
  31. import com.ibm.mqtt.MqttClient;  
  32. import com.ibm.mqtt.MqttException;  
  33. import com.ibm.mqtt.MqttPersistence;  
  34. import com.ibm.mqtt.MqttPersistenceException;  
  35. import com.ibm.mqtt.MqttSimpleCallback;  
  36.   
  37. /*  
  38.  * PushService that does all of the work. 
  39.  * Most of the logic is borrowed from KeepAliveService. 
  40.  * http://code.google.com/p/android-random/source/browse/trunk/TestKeepAlive/src/org/devtcg/demo/keepalive/KeepAliveService.java?r=219 
  41.  */  
  42. public class PushService extends Service {  
  43.     private MyBinder mBinder = new MyBinder();  
  44.     // this is the log tag  
  45.     public static final String TAG = "PushService";  
  46.   
  47.     // the IP address, where your MQTT broker is running.  
  48.     private static final String MQTT_HOST = "120.197.230.53"// "209.124.50.174";//  
  49.     // the port at which the broker is running.  
  50.     private static int MQTT_BROKER_PORT_NUM = 9901;  
  51.     // Let's not use the MQTT persistence.  
  52.     private static MqttPersistence MQTT_PERSISTENCE = null;  
  53.     // We don't need to remember any state between the connections, so we use a  
  54.     // clean start.  
  55.     private static boolean MQTT_CLEAN_START = true;  
  56.     // Let's set the internal keep alive for MQTT to 15 mins. I haven't tested  
  57.     // this value much. It could probably be increased.  
  58.     private static short MQTT_KEEP_ALIVE = 60 * 15;  
  59.     // Set quality of services to 0 (at most once delivery), since we don't want  
  60.     // push notifications  
  61.     // arrive more than once. However, this means that some messages might get  
  62.     // lost (delivery is not guaranteed)  
  63.     private static int[] MQTT_QUALITIES_OF_SERVICE = { 0 };  
  64.     private static int MQTT_QUALITY_OF_SERVICE = 0;  
  65.     // The broker should not retain any messages.  
  66.     private static boolean MQTT_RETAINED_PUBLISH = false;  
  67.   
  68.     // MQTT client ID, which is given the broker. In this example, I also use  
  69.     // this for the topic header.  
  70.     // You can use this to run push notifications for multiple apps with one  
  71.     // MQTT broker.  
  72.     public static String MQTT_CLIENT_ID = "client";  
  73.   
  74.     // These are the actions for the service (name are descriptive enough)  
  75.     public static final String ACTION_START = MQTT_CLIENT_ID + ".START";  
  76.     private static final String ACTION_STOP = MQTT_CLIENT_ID + ".STOP";  
  77.     private static final String ACTION_KEEPALIVE = MQTT_CLIENT_ID  
  78.             + ".KEEP_ALIVE";  
  79.     private static final String ACTION_RECONNECT = MQTT_CLIENT_ID  
  80.             + ".RECONNECT";  
  81.   
  82.     // Connection log for the push service. Good for debugging.  
  83.     private ConnectionLog mLog;  
  84.   
  85.     // Connectivity manager to determining, when the phone loses connection  
  86.     private ConnectivityManager mConnMan;  
  87.     // Notification manager to displaying arrived push notifications  
  88.     private NotificationManager mNotifMan;  
  89.   
  90.     // Whether or not the service has been started.  
  91.     private boolean mStarted;  
  92.   
  93.     // This the application level keep-alive interval, that is used by the  
  94.     // AlarmManager  
  95.     // to keep the connection active, even when the device goes to sleep.  
  96.     private static final long KEEP_ALIVE_INTERVAL = 1000 * 60 * 28;  
  97.   
  98.     // Retry intervals, when the connection is lost.  
  99.     private static final long INITIAL_RETRY_INTERVAL = 1000 * 10;  
  100.     private static final long MAXIMUM_RETRY_INTERVAL = 1000 * 60 * 30;  
  101.   
  102.     // Preferences instance  
  103.     private SharedPreferences mPrefs;  
  104.     // We store in the preferences, whether or not the service has been started  
  105.     public static final String PREF_STARTED = "isStarted";  
  106.     // We also store the deviceID (target)  
  107.     public static final String PREF_DEVICE_ID = "deviceID";  
  108.     // We store the last retry interval  
  109.     public static final String PREF_RETRY = "retryInterval";  
  110.   
  111.     // Notification title  
  112.     public static String NOTIF_TITLE = "client";  
  113.     // Notification id  
  114.     private static final int NOTIF_CONNECTED = 0;  
  115.   
  116.     // This is the instance of an MQTT connection.  
  117.     private MQTTConnection mConnection;  
  118.     private long mStartTime;  
  119.     boolean mShowFlag = true;// 是否显示通知  
  120.     public static Context ctx;  
  121.     private boolean mRunFlag = true;// 是否向服务器发送心跳  
  122.     Timer mTimer = new Timer();  
  123.   
  124.     // Static method to start the service  
  125.     public static void actionStart(Context ctx) {  
  126.         Intent i = new Intent(ctx, PushService.class);  
  127.         i.setAction(ACTION_START);  
  128.         ctx.startService(i);  
  129.         PushService.ctx = ctx;  
  130.     }  
  131.   
  132.     // Static method to stop the service  
  133.     public static void actionStop(Context ctx) {  
  134.         Intent i = new Intent(ctx, PushService.class);  
  135.         i.setAction(ACTION_STOP);  
  136.         ctx.startService(i);  
  137.     }  
  138.   
  139.     // Static method to send a keep alive message  
  140.     public static void actionPing(Context ctx) {  
  141.         Intent i = new Intent(ctx, PushService.class);  
  142.         i.setAction(ACTION_KEEPALIVE);  
  143.         ctx.startService(i);  
  144.     }  
  145.   
  146.     @Override  
  147.     public void onCreate() {  
  148.         super.onCreate();  
  149.   
  150.         log("Creating service");  
  151.         mStartTime = System.currentTimeMillis();  
  152.   
  153.         try {  
  154.             mLog = new ConnectionLog();  
  155.             Log.i(TAG, "Opened log at " + mLog.getPath());  
  156.         } catch (IOException e) {  
  157.             Log.e(TAG, "Failed to open log", e);  
  158.         }  
  159.   
  160.         // Get instances of preferences, connectivity manager and notification  
  161.         // manager  
  162.         mPrefs = getSharedPreferences(TAG, MODE_PRIVATE);  
  163.         mConnMan = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);  
  164.         mNotifMan = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  
  165.   
  166.         /* 
  167.          * If our process was reaped by the system for any reason we need to 
  168.          * restore our state with merely a call to onCreate. We record the last 
  169.          * "started" value and restore it here if necessary. 
  170.          */  
  171.         handleCrashedService();  
  172.     }  
  173.   
  174.     // This method does any necessary clean-up need in case the server has been  
  175.     // destroyed by the system  
  176.     // and then restarted  
  177.     private void handleCrashedService() {  
  178.         if (wasStarted() == true) {  
  179.             log("Handling crashed service...");  
  180.             // stop the keep alives  
  181.             stopKeepAlives();  
  182.   
  183.             // Do a clean start  
  184.             start();  
  185.         }  
  186.     }  
  187.   
  188.     @Override  
  189.     public void onDestroy() {  
  190.         log("Service destroyed (started=" + mStarted + ")");  
  191.   
  192.         // Stop the services, if it has been started  
  193.         if (mStarted == true) {  
  194.             stop();  
  195.         }  
  196.   
  197.         try {  
  198.             if (mLog != null)  
  199.                 mLog.close();  
  200.         } catch (IOException e) {  
  201.         }  
  202.     }  
  203.   
  204.     @Override  
  205.     public void onStart(Intent intent, int startId) {  
  206.         super.onStart(intent, startId);  
  207.         log("Service started with intent=" + intent);  
  208.         if (intent == null) {  
  209.             return;  
  210.         }  
  211.         // Do an appropriate action based on the intent.  
  212.         if (intent.getAction().equals(ACTION_STOP) == true) {  
  213.             stop();  
  214.             stopSelf();  
  215.         } else if (intent.getAction().equals(ACTION_START) == true) {  
  216.             start();  
  217.   
  218.         } else if (intent.getAction().equals(ACTION_KEEPALIVE) == true) {  
  219.             keepAlive();  
  220.         } else if (intent.getAction().equals(ACTION_RECONNECT) == true) {  
  221.             if (isNetworkAvailable()) {  
  222.                 reconnectIfNecessary();  
  223.             }  
  224.         }  
  225.     }  
  226.   
  227.     public class MyBinder extends Binder {  
  228.         public PushService getService() {  
  229.             return PushService.this;  
  230.         }  
  231.     }  
  232.   
  233.     @Override  
  234.     public IBinder onBind(Intent intent) {  
  235.         return mBinder;  
  236.     }  
  237.   
  238.     // log helper function  
  239.     private void log(String message) {  
  240.         log(message, null);  
  241.     }  
  242.   
  243.     private void log(String message, Throwable e) {  
  244.         if (e != null) {  
  245.             Log.e(TAG, message, e);  
  246.   
  247.         } else {  
  248.             Log.i(TAG, message);  
  249.         }  
  250.   
  251.         if (mLog != null) {  
  252.             try {  
  253.                 mLog.println(message);  
  254.             } catch (IOException ex) {  
  255.             }  
  256.         }  
  257.     }  
  258.   
  259.     // Reads whether or not the service has been started from the preferences  
  260.     private boolean wasStarted() {  
  261.         return mPrefs.getBoolean(PREF_STARTED, false);  
  262.     }  
  263.   
  264.     // Sets whether or not the services has been started in the preferences.  
  265.     private void setStarted(boolean started) {  
  266.         mPrefs.edit().putBoolean(PREF_STARTED, started).commit();  
  267.         mStarted = started;  
  268.     }  
  269.   
  270.     private synchronized void start() {  
  271.         log("Starting service...");  
  272.   
  273.         // Do nothing, if the service is already running.  
  274.         if (mStarted == true) {  
  275.             Log.w(TAG, "Attempt to start connection that is already active");  
  276.             return;  
  277.         }  
  278.   
  279.         // Establish an MQTT connection  
  280.   
  281.         connect();  
  282.   
  283.         // 向服务器定时发送心跳,一分钟一次  
  284.         mRunFlag = true;  
  285.         mTimer.schedule(new TimerTask() {  
  286.             @Override  
  287.             public void run() {  
  288.                 if (!mRunFlag) {  
  289.                     // this.cancel();  
  290.                     // PushService.this.stopSelf();  
  291.                     return;  
  292.                 }  
  293.                 System.out.println("run");  
  294.                 try {  
  295.                     if (isNetworkAvailable()) {  
  296.                         SharedPreferences pref = getSharedPreferences(  
  297.                                 "client"0);  
  298.                         String MOBILE_NUM = pref.getString("MOBILE_NUM""");  
  299.                         HttpUtil.post(Constants.KEEPALIVE + "&mobile="  
  300.                                 + MOBILE_NUM + "&online_flag=1");  
  301.                     }  
  302.                 } catch (Exception e) {  
  303.                     e.printStackTrace();  
  304.                     // TODO: handle exception  
  305.                 }  
  306.             }  
  307.         }, 060 * 1000);  
  308.         // Register a connectivity listener  
  309.         registerReceiver(mConnectivityChanged, new IntentFilter(  
  310.                 ConnectivityManager.CONNECTIVITY_ACTION));  
  311.     }  
  312.   
  313.     private synchronized void stop() {  
  314.         // Do nothing, if the service is not running.  
  315.         if (mStarted == false) {  
  316.             Log.w(TAG, "Attempt to stop connection not active.");  
  317.             return;  
  318.         }  
  319.   
  320.         // Save stopped state in the preferences  
  321.         setStarted(false);  
  322.   
  323.         // Remove the connectivity receiver  
  324.         unregisterReceiver(mConnectivityChanged);  
  325.         // Any existing reconnect timers should be removed, since we explicitly  
  326.         // stopping the service.  
  327.         cancelReconnect();  
  328.   
  329.         // Destroy the MQTT connection if there is one  
  330.         if (mConnection != null) {  
  331.             mConnection.disconnect();  
  332.             mConnection = null;  
  333.         }  
  334.     }  
  335.   
  336.     //  
  337.     private synchronized void connect() {  
  338.         log("Connecting...");  
  339.         // Thread t = new Thread() {  
  340.         // @Override  
  341.         // public void run() {  
  342.         // fetch the device ID from the preferences.  
  343.         String deviceID = "GMCC/client/"  
  344.                 + mPrefs.getString(PREF_DEVICE_ID, null);  
  345.           
  346.         // Create a new connection only if the device id is not NULL  
  347.         try {  
  348.             mConnection = new MQTTConnection(MQTT_HOST, deviceID);  
  349.         } catch (MqttException e) {  
  350.             // Schedule a reconnect, if we failed to connect  
  351.             log("MqttException: "  
  352.                     + (e.getMessage() != null ? e.getMessage() : "NULL"));  
  353.             if (isNetworkAvailable()) {  
  354.                 scheduleReconnect(mStartTime);  
  355.             }  
  356.         }  
  357.         setStarted(true);  
  358.         // }  
  359.         // };  
  360.         // t.start();  
  361.         // 向服务器定时发送心跳,一分钟一次  
  362.         mRunFlag = true;  
  363.     }  
  364.   
  365.     private synchronized void keepAlive() {  
  366.         try {  
  367.             // Send a keep alive, if there is a connection.  
  368.             if (mStarted == true && mConnection != null) {  
  369.                 mConnection.sendKeepAlive();  
  370.             }  
  371.         } catch (MqttException e) {  
  372.             log("MqttException: "  
  373.                     + (e.getMessage() != null ? e.getMessage() : "NULL"), e);  
  374.   
  375.             mConnection.disconnect();  
  376.             mConnection = null;  
  377.             cancelReconnect();  
  378.         }  
  379.     }  
  380.   
  381.     // Schedule application level keep-alives using the AlarmManager  
  382.     private void startKeepAlives() {  
  383.         Intent i = new Intent();  
  384.         i.setClass(this, PushService.class);  
  385.         i.setAction(ACTION_KEEPALIVE);  
  386.         PendingIntent pi = PendingIntent.getService(this0, i, 0);  
  387.         AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);  
  388.         alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,  
  389.                 System.currentTimeMillis() + KEEP_ALIVE_INTERVAL,  
  390.                 KEEP_ALIVE_INTERVAL, pi);  
  391.     }  
  392.   
  393.     // Remove all scheduled keep alives  
  394.     private void stopKeepAlives() {  
  395.         Intent i = new Intent();  
  396.         i.setClass(this, PushService.class);  
  397.         i.setAction(ACTION_KEEPALIVE);  
  398.         PendingIntent pi = PendingIntent.getService(this0, i, 0);  
  399.         AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);  
  400.         alarmMgr.cancel(pi);  
  401.     }  
  402.   
  403.     // We schedule a reconnect based on the starttime of the service  
  404.     public void scheduleReconnect(long startTime) {  
  405.         // the last keep-alive interval  
  406.         long interval = mPrefs.getLong(PREF_RETRY, INITIAL_RETRY_INTERVAL);  
  407.   
  408.         // Calculate the elapsed time since the start  
  409.         long now = System.currentTimeMillis();  
  410.         long elapsed = now - startTime;  
  411.   
  412.         // Set an appropriate interval based on the elapsed time since start  
  413.         if (elapsed < interval) {  
  414.             interval = Math.min(interval * 4, MAXIMUM_RETRY_INTERVAL);  
  415.         } else {  
  416.             interval = INITIAL_RETRY_INTERVAL;  
  417.         }  
  418.   
  419.         log("Rescheduling connection in " + interval + "ms.");  
  420.   
  421.         // Save the new internval  
  422.         mPrefs.edit().putLong(PREF_RETRY, interval).commit();  
  423.   
  424.         // Schedule a reconnect using the alarm manager.  
  425.         Intent i = new Intent();  
  426.         i.setClass(this, PushService.class);  
  427.         i.setAction(ACTION_RECONNECT);  
  428.         PendingIntent pi = PendingIntent.getService(this0, i, 0);  
  429.         AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);  
  430.         alarmMgr.set(AlarmManager.RTC_WAKEUP, now + interval, pi);  
  431.     }  
  432.   
  433.     // Remove the scheduled reconnect  
  434.     public void cancelReconnect() {  
  435.         Intent i = new Intent();  
  436.         i.setClass(PushService.this, PushService.class);  
  437.         i.setAction(ACTION_RECONNECT);  
  438.         PendingIntent pi = PendingIntent.getService(PushService.this0, i, 0);  
  439.         AlarmManager alarmMgr = (AlarmManager) getSystemService(ALARM_SERVICE);  
  440.         alarmMgr.cancel(pi);  
  441.     }  
  442.   
  443.     private synchronized void reconnectIfNecessary() {  
  444.         log("mStarted" + mStarted);  
  445.         log("mConnection" + mConnection);  
  446.         if (mStarted == true && mConnection == null) {  
  447.             log("Reconnecting...");  
  448.             connect();  
  449.         }  
  450.     }  
  451.   
  452.     // This receiver listeners for network changes and updates the MQTT  
  453.     // connection  
  454.     // accordingly  
  455.     private BroadcastReceiver mConnectivityChanged = new BroadcastReceiver() {  
  456.         @Override  
  457.         public void onReceive(Context context, final Intent intent) {  
  458.             // Get network info  
  459.             // Thread mReconnect = new Thread(){  
  460.             // public void run() {  
  461.             NetworkInfo info = (NetworkInfo) intent  
  462.                     .getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);  
  463.             // Is there connectivity?  
  464.             boolean hasConnectivity = (info != null && info.isConnected()) ? true  
  465.                     : false;  
  466.   
  467.             log("Connectivity changed: connected=" + hasConnectivity);  
  468.   
  469.             if (hasConnectivity) {  
  470.                 reconnectIfNecessary();  
  471.             } else if (mConnection != null) {  
  472.                 // Thread cancelConn = new Thread(){  
  473.                 // public void run() {  
  474.                 // // if there no connectivity, make sure MQTT connection is  
  475.                 // destroyed  
  476.                 log("cancelReconnect");  
  477.                 mConnection.disconnect();  
  478.                 mConnection = null;  
  479.                 log("cancelReconnect" + mConnection);  
  480.                 cancelReconnect();  
  481.                 // }  
  482.                 // };  
  483.                 // cancelConn.start();  
  484.             }  
  485.             // };  
  486.             //  
  487.             // };  
  488.             // mReconnect.start();  
  489.         }  
  490.     };  
  491.   
  492.     // Display the topbar notification  
  493.     private void showNotification(String text, Request request) {  
  494.   
  495.         Notification n = new Notification();  
  496.         n.flags |= Notification.FLAG_SHOW_LIGHTS;  
  497.         n.flags |= Notification.FLAG_AUTO_CANCEL;  
  498.         n.defaults = Notification.DEFAULT_ALL;  
  499.         n.icon = R.drawable.ico;  
  500.         n.when = System.currentTimeMillis();  
  501.         Intent intent = new Intent();  
  502.         Bundle bundle = new Bundle();  
  503.         bundle.putSerializable("request", request);  
  504.         bundle.putString("currentTab""1");  
  505.         intent.putExtras(bundle);  
  506.         intent.setClass(this, MainActivity.class);  
  507.         intent.setAction(Intent.ACTION_MAIN);  
  508.         intent.addCategory(Intent.CATEGORY_LAUNCHER);  
  509.         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK  
  510.                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);  
  511.         // Simply open the parent activity  
  512.         PendingIntent pi = PendingIntent.getActivity(this0, intent, 0);  
  513.   
  514.         // Change the name of the notification here  
  515.         n.setLatestEventInfo(this, NOTIF_TITLE, text, pi);  
  516.         mNotifMan.notify(NOTIF_CONNECTED, n);  
  517.     }  
  518.   
  519.     // Check if we are online  
  520.     private boolean isNetworkAvailable() {  
  521.         NetworkInfo info = mConnMan.getActiveNetworkInfo();  
  522.         if (info == null) {  
  523.             return false;  
  524.         }  
  525.         return info.isConnected();  
  526.     }  
  527.   
  528. <span style="BACKGROUND-COLOR: #ccffff">    // This inner class is a wrapper on top of MQTT client.  
  529.     private class MQTTConnection implements MqttSimpleCallback {  
  530.         IMqttClient mqttClient = null;  
  531.   
  532.         // Creates a new connection given the broker address and initial topic  
  533.         public MQTTConnection(String brokerHostName, String initTopic)  
  534.                 throws MqttException {  
  535.             // Create connection spec  
  536.             String mqttConnSpec = "tcp://" + brokerHostName + "@"  
  537.                     + MQTT_BROKER_PORT_NUM;  
  538.             // Create the client and connect  
  539.             mqttClient = MqttClient.createMqttClient(mqttConnSpec,  
  540.                     MQTT_PERSISTENCE);  
  541.             String clientID = MQTT_CLIENT_ID + "/"  
  542.                     + mPrefs.getString(PREF_DEVICE_ID, "");  
  543.             Log.d(TAG, "mqttConnSpec:" + mqttConnSpec + "  clientID:"  
  544.                     + clientID);  
  545.             mqttClient.connect(clientID, MQTT_CLEAN_START, MQTT_KEEP_ALIVE);  
  546.   
  547.             // register this client app has being able to receive messages  
  548.             mqttClient.registerSimpleHandler(this);  
  549.   
  550.             // Subscribe to an initial topic, which is combination of client ID  
  551.             // and device ID.  
  552.             // initTopic = MQTT_CLIENT_ID + "/" + initTopic;  
  553.             subscribeToTopic(initTopic);  
  554.   
  555.             log("Connection established to " + brokerHostName + " on topic "  
  556.                     + initTopic);  
  557.   
  558.             // Save start time  
  559.             mStartTime = System.currentTimeMillis();  
  560.             // Star the keep-alives  
  561.             startKeepAlives();  
  562.         }  
  563.   
  564.         // Disconnect  
  565.         public void disconnect() {  
  566.             // try {  
  567.             stopKeepAlives();  
  568.             log("stopKeepAlives");  
  569.             Thread t = new Thread() {  
  570.                 public void run() {  
  571.                     try {  
  572.                         mqttClient.disconnect();  
  573.                         log("mqttClient.disconnect();");  
  574.                     } catch (MqttPersistenceException e) {  
  575.                         log("MqttException"  
  576.                                 + (e.getMessage() != null ? e.getMessage()  
  577.                                         : " NULL"), e);  
  578.                     }  
  579.                 };  
  580.             };  
  581.             t.start();  
  582.             // } catch (MqttPersistenceException e) {  
  583.             // log("MqttException"  
  584.             // + (e.getMessage() != null ? e.getMessage() : " NULL"),  
  585.             // e);  
  586.             // }  
  587.         }  
  588.   
  589.         /* 
  590.          * Send a request to the message broker to be sent messages published 
  591.          * with the specified topic name. Wildcards are allowed. 
  592.          */  
  593.         private void subscribeToTopic(String topicName) throws MqttException {  
  594.   
  595.             if ((mqttClient == null) || (mqttClient.isConnected() == false)) {  
  596.                 // quick sanity check - don't try and subscribe if we don't have  
  597.                 // a connection  
  598.                 log("Connection error" + "No connection");  
  599.             } else {  
  600.                 String[] topics = { topicName };  
  601.                 mqttClient.subscribe(topics, MQTT_QUALITIES_OF_SERVICE);  
  602.             }  
  603.         }  
  604.   
  605.         /* 
  606.          * Sends a message to the message broker, requesting that it be 
  607.          * published to the specified topic. 
  608.          */  
  609.         private void publishToTopic(String topicName, String message)  
  610.                 throws MqttException {  
  611.             if ((mqttClient == null) || (mqttClient.isConnected() == false)) {  
  612.                 // quick sanity check - don't try and publish if we don't have  
  613.                 // a connection  
  614.                 log("No connection to public to");  
  615.             } else {  
  616.                 mqttClient.publish(topicName, message.getBytes(),  
  617.                         MQTT_QUALITY_OF_SERVICE, MQTT_RETAINED_PUBLISH);  
  618.             }  
  619.         }  
  620.   
  621.         /* 
  622.          * Called if the application loses it's connection to the message 
  623.          * broker. 
  624.          */  
  625.         public void connectionLost() throws Exception {  
  626.             log("Loss of connection" + "connection downed");  
  627.             stopKeepAlives();  
  628.             // 取消定时发送心跳  
  629.             mRunFlag = false;  
  630.             // 向服务器发送请求,更改在线状态  
  631.             // SharedPreferences pref = getSharedPreferences("client",0);  
  632.             // String MOBILE_NUM=pref.getString("MOBILE_NUM", "");  
  633.             // HttpUtil.post(Constants.KEEPALIVE + "&mobile="  
  634.             // + MOBILE_NUM+"&online_flag=0");  
  635.             // null itself  
  636.             mConnection = null;  
  637.             if (isNetworkAvailable() == true) {  
  638.                 reconnectIfNecessary();  
  639.             }  
  640.         }  
  641.   
  642.         /* 
  643.          * Called when we receive a message from the message broker. 
  644.          */  
  645.         public void publishArrived(String topicName, byte[] payload, int qos,  
  646.                 boolean retained) throws MqttException {  
  647.             // Show a notification  
  648.             // synchronized (lock) {  
  649.             String s = new String(payload);  
  650.             Request request = null;  
  651.             try {// 解析服务端推送过来的消息  
  652.                 request = XmlPaserTool.getMessage(new ByteArrayInputStream(s  
  653.                         .getBytes()));  
  654.                 // request=Constants.request;  
  655.             } catch (Exception e) {  
  656.                 e.printStackTrace();  
  657.             }  
  658.             final Request mRequest = request;  
  659.             DownloadInfo down = new DownloadInfo(mRequest);  
  660.             down.setDownLoad(down);  
  661.             downloadInfos.add(down);  
  662.             sendUpdateBroast();  
  663.             down.start();  
  664.             showNotification("您有一条新的消息!", mRequest);  
  665.             Log.d(PushService.TAG, s);  
  666.             Log.d(PushService.TAG, mRequest.getMessageId());  
  667.             // 再向服务端推送消息  
  668.             new AdvancedCallbackHandler().sendMessage(MQTT_CLIENT_ID  
  669.                     + "/keepalive""***********send message**********");  
  670.         }  
  671.   
  672.         public void sendKeepAlive() throws MqttException {  
  673.             log("Sending keep alive");  
  674.             // publish to a keep-alive topic  
  675.             publishToTopic(MQTT_CLIENT_ID + "/keepalive",  
  676.                     mPrefs.getString(PREF_DEVICE_ID, ""));  
  677.         }  
  678.     }  
  679.   
  680.     class AdvancedCallbackHandler {  
  681.         IMqttClient mqttClient = null;  
  682.         public final int[] QOS_VALUES = { 0020 };// 对应主题的消息级别  
  683.   
  684.         /** 
  685.          * 重新连接服务 
  686.          */  
  687.         private void connect() throws MqttException {  
  688.             String mqttConnSpec = "tcp://" + MQTT_HOST + "@"  
  689.                     + MQTT_BROKER_PORT_NUM;  
  690.             // Create the client and connect  
  691.             mqttClient = MqttClient.createMqttClient(mqttConnSpec,  
  692.                     MQTT_PERSISTENCE);  
  693.             String clientID = MQTT_CLIENT_ID + "/"  
  694.                     + mPrefs.getString(PREF_DEVICE_ID, "");  
  695.             mqttClient.connect(clientID, MQTT_CLEAN_START, MQTT_KEEP_ALIVE);  
  696.             Log.d(TAG, "连接服务器,推送消息");  
  697.             Log.d(TAG, "**mqttConnSpec:" + mqttConnSpec + "  clientID:"  
  698.                     + clientID);  
  699.             Log.d(TAG, MQTT_CLIENT_ID + "/keepalive");  
  700.             // 增加心跳,保持网络通畅  
  701.             mqttClient.publish(MQTT_CLIENT_ID + "/keepalive",  
  702.                     "keepalive".getBytes(), QOS_VALUES[0], true);  
  703.         }  
  704.   
  705.         /** 
  706.          * 发送消息 
  707.          *  
  708.          * @param clientId 
  709.          * @param messageId 
  710.          */  
  711.         public void sendMessage(String clientId, String message) {  
  712.             try {  
  713.                 if (mqttClient == null || !mqttClient.isConnected()) {  
  714.                     connect();  
  715.                 }  
  716.   
  717.                 Log.d(TAG, "send message to " + clientId + ", message is "  
  718.                         + message);  
  719.                 // 发布自己的消息  
  720.                 // mqttClient.publish(MQTT_CLIENT_ID + "/keepalive",  
  721.                 // message.getBytes(), 0, false);  
  722.                 mqttClient.publish(MQTT_CLIENT_ID + "/keepalive",  
  723.                         message.getBytes(), 0false);  
  724.             } catch (MqttException e) {  
  725.                 Log.d(TAG, e.getCause() + "");  
  726.                 e.printStackTrace();  
  727.             }  
  728.         }  
  729.     }  
  730. </span>  
  731.     public String getPeople(String phone_number) {  
  732.         String name = "";  
  733.         String[] projection = { ContactsContract.PhoneLookup.DISPLAY_NAME,  
  734.                 ContactsContract.CommonDataKinds.Phone.NUMBER };  
  735.         Log.d(TAG, "getPeople ---------");  
  736.         // 将自己添加到 msPeers 中  
  737.         Cursor cursor = this.getContentResolver().query(  
  738.                 ContactsContract.CommonDataKinds.Phone.CONTENT_URI,  
  739.                 projection, // Which columns to return.  
  740.                 ContactsContract.CommonDataKinds.Phone.NUMBER + " = '"  
  741.                         + phone_number + "'"// WHERE clause.  
  742.                 null// WHERE clause value substitution  
  743.                 null); // Sort order.  
  744.   
  745.         if (cursor == null) {  
  746.             Log.d(TAG, "getPeople null");  
  747.             return "";  
  748.         }  
  749.         Log.d(TAG, "getPeople cursor.getCount() = " + cursor.getCount());  
  750.         if (cursor.getCount() > 0) {  
  751.             cursor.moveToPosition(0);  
  752.   
  753.             // 取得联系人名字  
  754.             int nameFieldColumnIndex = cursor  
  755.                     .getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME);  
  756.             name = cursor.getString(nameFieldColumnIndex);  
  757.             Log.i("Contacts""" + name + " .... " + nameFieldColumnIndex); // 这里提示  
  758.                                                                             // force  
  759.                                                                             // close  
  760.             System.out.println("联系人姓名:" + name);  
  761.             return name;  
  762.         }  
  763.         return phone_number;  
  764.     }  
  765.   
  766.     public void sendUpdateBroast() {  
  767.         Intent intent = new Intent();  
  768.         intent.setAction("update");  
  769.         sendBroadcast(intent);  
  770.     }  
  771.   
  772.     public void sendUpdateFinishBroast() {  
  773.         Intent intent = new Intent();  
  774.         intent.setAction("updateFinishList");  
  775.         sendBroadcast(intent);  
  776.     }  
  777.   
  778.     public class DownloadInfo extends Thread {  
  779.         boolean runflag = true;  
  780.         Request mRequest;  
  781.         public float progress;  
  782.         public MessageBean bean = null;  
  783.         DownloadInfo download = null;  
  784.         MessageDetailDao dao = new MessageDetailDao(  
  785.                 PushService.this.getApplicationContext());  
  786.   
  787.         public synchronized void stopthread() {  
  788.             runflag = false;  
  789.         }  
  790.   
  791.         public synchronized boolean getrunflag() {  
  792.             return runflag;  
  793.         }  
  794.   
  795.         DownloadInfo(Request mRequest) {  
  796.             this.mRequest = mRequest;  
  797.   
  798.         }  
  799.   
  800.         public void setDownLoad(DownloadInfo download) {  
  801.             this.download = download;  
  802.         }  
  803.   
  804.         @Override  
  805.         public void run() {  
  806.             try {  
  807.   
  808.                 File dir = new File(Constants.DOWNLOAD_PATH);  
  809.                 if (!dir.exists()) {  
  810.                     dir.mkdirs();  
  811.                 }  
  812.                 String filePath = Constants.DOWNLOAD_PATH  
  813.                         + mRequest.getMessageId() + "." + mRequest.getExt();  
  814.                 bean = new MessageBean();  
  815.                 bean.setPath(filePath);  
  816.                 bean.setStatus(0);  
  817.                 bean.setDate(mRequest.getTimestamp());  
  818.                 bean.setLayoutID(R.layout.list_say_he_item);  
  819.                 bean.setPhotoID(R.drawable.receive_ico);  
  820.                 bean.setMessage_key(mRequest.getMessageId());  
  821.                 bean.setPhone_number(mRequest.getReceiver());  
  822.                 bean.setAction(1);  
  823.                 String name = getPeople(mRequest.getSender());  
  824.                 bean.setName(name);  
  825.                 bean.setFileType(Integer.parseInt(mRequest.getCommand()));  
  826.                 if (mRequest.getCommand().equals(Request.TYPE_MUSIC)) {  
  827.                     bean.setMsgIco(R.drawable.music_temp);  
  828.                     bean.setText(name + "给你发送了音乐");  
  829.                     mRequest.setBody(Base64.encodeToString(bean.getText()  
  830.                             .getBytes(), Base64.DEFAULT));  
  831.                 } else if (mRequest.getCommand().equals(Request.TYPE_CARD)) {  
  832.                     bean.setMsgIco(R.drawable.card_temp);  
  833.                     bean.setText(new String(Base64.decode(mRequest.getBody(),  
  834.                             Base64.DEFAULT)));  
  835.                     mRequest.setBody(Base64.encodeToString(bean.getText()  
  836.                             .getBytes(), Base64.DEFAULT));  
  837.                 } else if (mRequest.getCommand().equals(Request.TYPE_LBS)) {  
  838.                     bean.setMsgIco(R.drawable.address_temp);  
  839.                     bean.setText(new String(Base64.decode(mRequest.getBody(),  
  840.                             Base64.DEFAULT)));  
  841.                     mRequest.setBody(Base64.encodeToString(bean.getText()  
  842.                             .getBytes(), Base64.DEFAULT));  
  843.                 } else if (mRequest.getCommand().equals(Request.TYPE_PHOTO)) {  
  844.                     bean.setText(name + "向你发送了照片");  
  845.                     bean.setMsgIco(-1);  
  846.                 } else if (mRequest.getCommand().equals(Request.TYPE_PIC)) {  
  847.                     bean.setText(name + "向你发送了图片");  
  848.                     bean.setMsgIco(-1);  
  849.                 } else if (mRequest.getCommand().equals(Request.TYPE_SMS)) {  
  850.                     bean.setFileType(0);  
  851.                 }  
  852.   
  853.                 if (!mRequest.getCommand().equals(Request.TYPE_CARD)  
  854.                         && !mRequest.getCommand().equals(Request.TYPE_SMS)) {  
  855.                     String path = Constants.FILE_DOWNLOAD_URL  
  856.                             + mRequest.getMessageId();  
  857.                     URL url = new URL(path);  
  858.                     HttpURLConnection hurlconn = (HttpURLConnection) url  
  859.                             .openConnection();// 基于HTTP协议的连接对象  
  860.                     hurlconn.setConnectTimeout(5000);// 请求超时时间 5s  
  861.                     hurlconn.setRequestMethod("GET");// 请求方式  
  862.                     hurlconn.connect();  
  863.                     long fileSize = hurlconn.getContentLength();  
  864.                     InputStream instream = hurlconn.getInputStream();  
  865.                     byte[] buffer = new byte[1024];  
  866.                     int len = 0;  
  867.                     int number = 0;  
  868.                     RandomAccessFile rasf = new RandomAccessFile(filePath,  
  869.                             "rwd");  
  870.                     while ((len = instream.read(buffer)) != -1) {// 开始下载文件  
  871.                         if (getrunflag() && progress < 100) {  
  872.                             rasf.seek(number);  
  873.                             number += len;  
  874.                             rasf.write(buffer, 0, len);  
  875.                             progress = (((float) number) / fileSize) * 100;  
  876.                             // 发送广播,修改进度条进度  
  877.                             sendUpdateBroast();  
  878.                         } else {  
  879.                             this.interrupt();  
  880.                             if (number != fileSize) {// 取消下载,将已经缓存的未下载完成的文件删除  
  881.                                 File file = new File(filePath);  
  882.                                 if (file.exists())  
  883.                                     file.delete();  
  884.                             }  
  885.                             PushService.downloadInfos.remove(download);  
  886.                             sendUpdateBroast();  
  887.                             return;  
  888.                         }  
  889.                     }  
  890.                     instream.close();  
  891.                     PushService.downloadInfos.remove(download);  
  892.                     sendUpdateBroast();  
  893.                 } else {// 收到消息,将信息保存到数据库  
  894.   
  895.                     PushService.downloadInfos.remove(download);  
  896.                     sendUpdateBroast();  
  897.                 }  
  898.                 // 将文件信息保存到数据库  
  899.                 dao.create(bean);  
  900.                 sendUpdateFinishBroast();  
  901.   
  902.             } catch (Exception e) {  
  903.                 PushService.downloadInfos.remove(download);  
  904.                 sendUpdateBroast();  
  905.                 e.printStackTrace();  
  906.             }  
  907.         }  
  908.     }  
  909.   
  910.     public static ArrayList<DownloadInfo> downloadInfos = new ArrayList<DownloadInfo>();  
  911.   
  912.     public ArrayList<DownloadInfo> getDownloadInfos() {  
  913.         return PushService.downloadInfos;  
  914.     }  
  915.   
  916.     public void setDownloadInfos(ArrayList<DownloadInfo> downloadInfos) {  
  917.         PushService.downloadInfos = downloadInfos;  
  918.     }  
  919. }</pre>  
  920. <p><br>  
  921.  ps:</p>  
  922. <p>接收者必须订阅发送者的TOPICS才能收到消息</p>  
  923. <p> </p>  
  924. <pre></pre>  
  925. <pre></pre>  
  926. <pre></pre>  
  927. <pre></pre>  
  928.      
1 0
原创粉丝点击