Using Alibaba Cloud Message Queuing
Console address: http://ons.console.aliyun.com/#/home/topic
(1) Generate Producer ID
Click "Apply for Publishing"
sample code:
package com.alibaba.ons.demo; import java.util.Properties; import com.aliyun.openservices.ons.api.Message; import com.aliyun.openservices.ons.api.ONSFactory; import com.aliyun.openservices.ons.api.Producer; import com.aliyun.openservices.ons.api.PropertyKeyConst; import com.aliyun.openservices.ons.api.SendResult; public class ProducerClient { public static void main(String[] args) { Properties properties = new Properties(); properties.put(PropertyKeyConst.ProducerId, "PID_whuang"); properties.put(PropertyKeyConst.AccessKey, "Please enter AccessKey"); properties.put(PropertyKeyConst.SecretKey, "Please enter SecretKey"); Producer producer = ONSFactory.createProducer(properties); //Before sending a message, the start method must be called to start the Producer, which only needs to be called once. producer.start(); Message msg = new Message( //Message Topic "com_hbjltv", //Message Tag, //It can be understood as a label in Gmail, which reclassifies the message, which is convenient for the Consumer to specify filter conditions to filter on the ONS server "TagA", //Message Body //Any binary form of data, ONS does not do any intervention, the serialization and deserialization methods need to be negotiated between the Producer and the Consumer "Hello ONS".getBytes() ); // Set the business key attribute representing the message, please make it globally unique as much as possible. // In case you cannot receive the message normally, you can query the message through the ONS Console and reissue it. // Note: If you don't set it, it will not affect the normal sending and receiving of messages msg.setKey("ORDERID_100"); //Send a message, as long as no exception is thrown, it is successful SendResult sendResult = producer.send(msg); System.out.println(sendResult); // Before the application exits, destroy the Producer object // Note: if it is not destroyed, there is no problem producer.shutdown(); } }
(2) Generate Consumer ID
Click "Request Subscription"
Sample Code:
public class ConsumerTest { public static void main(String[] args) { Properties properties = new Properties(); properties.put(PropertyKeyConst.ConsumerId, "CID_tv_mobile"); properties.put(PropertyKeyConst.AccessKey, "Please enter AccessKey"); properties.put(PropertyKeyConst.SecretKey, "Please enter SecretKey"); Consumer consumer = ONSFactory.createConsumer(properties); consumer.subscribe("com_hbjltv", "*", new MessageListener() { public Action consume(Message message, ConsumeContext context) { System.out.println("Receive: " + message); return Action.CommitMessage; } }); consumer.start(); System.out.println("Consumer Started"); } }
(3) Restriction of clientId
Alibaba Cloud Message Queue has strict restrictions on the name of clientId:
(a) It must start with the applied Consumer ID , followed by @@@ , followed by a sign used to distinguish the client,
E.g:
CID_tv_mobile@@@86458fd is legal
CID_tv_mobile @@ 86458fd is illegal because there are only two @
(b) The total length cannot exceed 23 characters
E.g
CID_tv_mobile@@@86458_A is legal
CID_tv_mobile@@@86458_Ab is illegal because it exceeds 23 characters
(4) Add subscription logic on the mobile phone (client)
package com.service; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.internal.MemoryPersistence; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.IBinder; import com.common.util.SystemHWUtil; import com.dict.Constants3; import com.jianli.R; import com.push.PushCallback; import com.string.widget.util.ValueWidget; import com.util.MacSignature; import com.util.ShopUtil; /** * @author Dominik Obermaier */ public class MQTTService extends Service { // public static final String BROKER_URL = // "tcp://broker.mqttdashboard.com:1883"; // public static String BROKER_URL = "tcp://172.16.15.50:1883"; public static String BROKER_URL_FORMAT = "tcp://%s:%s"; // public static final String BROKER_URL = "tcp://test.mosquitto.org:1883"; /* * In a real application, you should get an Unique Client ID of the device * and use this, see * http://android-developers.blogspot.de/2011/03/identifying * -app-installations.html */ public static String clientId = null; /** * 不能含有英文句点,可以包含下划线 */ public static final String TOPIC = "com_hbjltv"; private MqttClient mqttClient; // private String ip="182.92.80.122"; /*** * 是否连接上activeMQ */ private boolean online = false; boolean isAliyun=false; public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); } private MqttClient createMqttClient(String serverURL, String clientId) throws MqttException{ return new MqttClient(serverURL, clientId, new MemoryPersistence()); } /*** * * @param serverURL * @param clientId * : 最大长度:23 * @param isAllowOffline * @param username * @param password * @throws MqttException */ private void connectAndSubscribe(String serverURL, String clientId, /* String topicFilter, */boolean isAllowOffline, String username, String password) throws MqttException { if(isAliyun){ if(!ShopUtil.validateClientId(getApplicationContext(), clientId)){ return; } } mqttClient = createMqttClient(serverURL, clientId); MqttConnectOptions options = new MqttConnectOptions(); options.setCleanSession(!isAllowOffline);// mqtt receive offline message if (ValueWidget.isNullOrEmpty(username)) { username = null; } String sign=null; if(isAliyun){ try { sign = MacSignature.macSignature(Constants3.CONSUMER_ID_TV, password); password=sign; } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } if (ValueWidget.isNullOrEmpty(password)) { password = null; } else { options.setPassword(password.toCharArray()); } options.setUserName(username); options.setConnectionTimeout(10); options.setKeepAliveInterval(10); if(null==mqttClient){//点击HOME键,过很长时间,再点击应用时,mqttClient为null mqttClient = createMqttClient(serverURL, clientId); } mqttClient.setCallback(new PushCallback(this)); boolean isSuccess=false; mqttClient.connect(options); isSuccess=true; // Subscribe to all subtopics of homeautomation // mqttClient.subscribe(topicFilter); if(null==mqttClient){//点击HOME键,过很长时间,再点击应用时,mqttClient为null mqttClient = createMqttClient(serverURL, clientId); } if(isAliyun){ final String p2ptopic = TOPIC+"/p2p/"; //同时订阅两个topic,一个是基于标准mqtt协议的发布订阅模式,一个是扩展的点对点推送模式 final String[] topicFilters=new String[]{TOPIC,p2ptopic}; mqttClient.subscribe(topicFilters); }else{ mqttClient.subscribe(new String[] { TOPIC, clientId }); } } @Override public void onStart(Intent intent, int startId) { final boolean isRestart=intent.getBooleanExtra("isRestart", false); ShopUtil.logger2("restart MQTT service:"+isRestart); // super.onStart(intent, startId); // if (intent == null) {//重启服务时intent 确实为空 // Log.d(Constants.LOG_TAG, "intent is null"); // return; // } Context context = getApplicationContext(); clientId = ShopUtil.getIMEI(context); // Bundle bundle=intent.getExtras(); // String ip=bundle.getString(Constants.ACTIVEMQ_IP); // final String ip = context.getString(R.string.pushserver_ip); SharedPreferences preferences = getApplicationContext() .getSharedPreferences(Constants3.SHAREDPREFERENCES_NAME, Context.MODE_PRIVATE); final String ip ="mqtt.ons.aliyun.com";// preferences.getString("pushserver_ip", context.getString(R.string.pushserver_ip)); final String port = preferences.getString("pushserver_port", "1883"); isAliyun=SystemHWUtil.parse2Boolean(preferences.getString("is_aliyun_mq_ONS", "false")); // String topic=bundle.getString(Constants.ACTIVEMQ_TOPIC); System.out.println("push ip:"+ip); new Thread(new Runnable() { /**** * 尝试连接的次数,为什么要尝试连接几次那? * (1)无wifi时启动,则肯定连接失败,所以尝试连接三次,只要在这个期间启动wifi就可以连接上activeMQ;<br /> * (2)之前连接上,然后断开wifi,然后又启动wifi,<br /> * 这时容易报 "Broker unavailable"异常,暂时不清楚原因,所以也需要继续尝试连接;<br /> * */ private int tryTime = 5; @Override public void run() { System.out.println(tryTime+","+mqttClient+","+isOnline() ); while (tryTime > 0 && (!isOnline() || mqttClient == null || (!mqttClient .isConnected())||isRestart)) { try { ShopUtil.logger2("start push service"); ShopUtil.logger2("push server:"+ip); String prefix=Constants3.CONSUMER_ID_TV+"@@@"; int remainingLength=23-prefix.length(); String suffix=null; if(clientId.length()>remainingLength){ suffix=clientId.substring(0,remainingLength); }else{ suffix=clientId; } String clientId2=prefix+suffix; connectAndSubscribe(String.format( MQTTService.BROKER_URL_FORMAT, ip, port), clientId2, /* topic, */true, ""/*自己申请的access key*/, ""/*secret*/); ShopUtil.logger2("clientId:" + clientId2); ShopUtil.logger2("succeed to connect to activeMQ"); setOnline(true); } catch (MqttException e) { setOnline(false); mqttClient=null; e.printStackTrace(); ShopUtil.logger2("抛异常:"+e.getMessage()); ShopUtil.logger2("ip:" + ip + " ,port:" + port); try { Thread.sleep(10000); } catch (InterruptedException e1) { e1.printStackTrace(); } } tryTime--; } } }).start(); // new Thread(new Runnable() { // @Override // public void run() { // System.out.println("start:"+System.currentTimeMillis()); // try { // Thread.sleep(10000); // } catch (InterruptedException e) { // e.printStackTrace(); // } // while(true){ // try { // Thread.sleep(10000); // if(mqttClient!=null&& !mqttClient.isConnected()){ // System.out.println("disConnected:"+System.currentTimeMillis()); // } // } catch (InterruptedException e) { // e.printStackTrace(); // } // } // } // }).start(); } @Override public void onDestroy() { setOnline(false); try { ShopUtil.logger2("MQTTService destory"); mqttClient.disconnect(0); } catch (MqttException e) { // Toast.makeText(getApplicationContext(), // "Something went wrong!" + e.getMessage(), Toast.LENGTH_LONG) // .show(); e.printStackTrace(); } mqttClient = null; stopForeground(true); Intent intent = new Intent("com.dbjtech.waiqin.destroy"); sendBroadcast(intent); } public boolean isOnline() { return online; } public void setOnline(boolean online) { this.online = online; } @Override public int onStartCommand(Intent intent, int flags, int startId) { flags = START_STICKY; return super.onStartCommand(intent, flags, startId); } }
源代码见githb:
https://github.com/whuanghkl/mqtt_client_swing.git
阿里云消息队列MQ 开发者手册见附件