Android安卓实现mqtt客户端
本文连接:https://www.cnblogs.com/muphy/p/14702211.html
先看效果
只设配平板
使用docker安装emqtt搭建mqtt服务
docker run --name emq -p 18083:18083 -p 1883:1883 -p 8084:8084 -p 8883:8883 -p 8083:8083 -d registry.cn-hangzhou.aliyuncs.com/synbop/emqttd:2.3.6
使用浏览器连接mqtt服务
http://192.168.2.100:18083/#/websocket
也可以使用MQTTX客户端连接mqtt服务器
配置连接信息
操作界面
使用当前app连接,显示的都是默认值
代码
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="me.muphy.android.mqtt.demo"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Androidmqttdemo"> <service android:name="org.eclipse.paho.android.service.MqttService" /> <!--MqttService--> <!--MyMqttService--> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="188dp" android:layout_height="0dp" android:layout_marginTop="49dp" android:layout_marginBottom="54dp" android:contentDescription="@string/icon" app:layout_constraintBottom_toTopOf="@+id/editTextTextPersonName" app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@mipmap/touxiang" /> <EditText android:id="@+id/editTextTextPersonName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="33dp" android:autofillHints="" android:ems="10" android:hint="@string/username_hint" android:inputType="textPersonName" app:layout_constraintBottom_toTopOf="@+id/editTextTextPassword" app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/imageView" /> <EditText android:id="@+id/editTextTextPassword" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="33dp" android:autofillHints="" android:ems="10" android:hint="@string/password_hint" android:inputType="textPassword" app:layout_constraintBottom_toTopOf="@+id/button" app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editTextTextPersonName" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="61dp" android:layout_marginBottom="28dp" android:text="@string/button_login" app:layout_constraintBottom_toTopOf="@+id/textView2" app:layout_constraintStart_toStartOf="@+id/editTextTextPassword" app:layout_constraintTop_toBottomOf="@+id/editTextTextPassword" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="12dp" android:layout_marginBottom="27dp" android:text="@string/app_version" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/button" app:layout_constraintTop_toBottomOf="@+id/button" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.32" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.61" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.71" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline7" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.9" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.38" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.12" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.43" /> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline9" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.32" /> <EditText android:id="@+id/pubTopic" android:layout_width="0dp" android:layout_height="wrap_content" android:ems="10" android:hint="topic" android:inputType="textPersonName" app:layout_constraintBottom_toTopOf="@+id/guideline4" app:layout_constraintEnd_toStartOf="@+id/guideline2" app:layout_constraintStart_toStartOf="@+id/guideline3" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发布" android:textSize="24sp" app:layout_constraintBottom_toTopOf="@+id/guideline4" app:layout_constraintEnd_toStartOf="@+id/guideline3" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/pubBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确认" app:layout_constraintBottom_toTopOf="@+id/guideline4" app:layout_constraintEnd_toStartOf="@+id/guideline5" app:layout_constraintStart_toStartOf="@+id/guideline2" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="订阅" android:textSize="24sp" app:layout_constraintBottom_toTopOf="@+id/guideline6" app:layout_constraintEnd_toStartOf="@+id/guideline3" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="@+id/guideline9" /> <EditText android:id="@+id/subTopic" android:layout_width="0dp" android:layout_height="wrap_content" android:ems="10" android:hint="topic" android:inputType="textPersonName" app:layout_constraintBottom_toTopOf="@+id/guideline6" app:layout_constraintEnd_toStartOf="@+id/guideline2" app:layout_constraintStart_toStartOf="@+id/guideline3" app:layout_constraintTop_toTopOf="@+id/guideline9" /> <Button android:id="@+id/subBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="确认" app:layout_constraintBottom_toTopOf="@+id/guideline6" app:layout_constraintEnd_toStartOf="@+id/guideline5" app:layout_constraintStart_toStartOf="@+id/guideline2" app:layout_constraintTop_toTopOf="@+id/guideline9" /> <EditText android:id="@+id/subText" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:editable="false" android:ems="10" android:gravity="start|top" android:inputType="textMultiLine" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="@+id/guideline6" app:layout_constraintVertical_bias="0.493" /> <EditText android:id="@+id/pubText" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:ems="10" android:gravity="start|top" android:inputType="textMultiLine" app:layout_constraintBottom_toTopOf="@+id/guideline9" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="@+id/guideline4" /> </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
package me.muphy.android.mqtt.demo; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import org.eclipse.paho.android.service.MqttAndroidClient; import org.eclipse.paho.client.mqttv3.IMqttActionListener; import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.IMqttToken; import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; public class MainActivity extends AppCompatActivity { private static String TAG = MainActivity.class.getSimpleName(); private static MqttAndroidClient mqttAndroidClient; private Button pubBtn; private Button subBtn; private Button connBtn; private EditText pubText; private EditText subText; private EditText pubContent; private EditText pubTopic; private EditText subTopic; private EditText subTopics; private TextView pubMsg; private TextView subMsg; private TextView status; private EditText passwordEt; private EditText usernameEt; private EditText clientIdEt; private EditText hostEt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pubBtn = findViewById(R.id.pubBtn); subBtn = findViewById(R.id.subBtn); connBtn = findViewById(R.id.connBtn); pubText = findViewById(R.id.pubText); pubContent = findViewById(R.id.pubContent); subText = findViewById(R.id.subText); pubTopic = findViewById(R.id.pubTopic); subTopic = findViewById(R.id.subTopic); subTopics = findViewById(R.id.subTopics); pubMsg = findViewById(R.id.pubMsg); subMsg = findViewById(R.id.subMsg); status = findViewById(R.id.status); passwordEt = findViewById(R.id.password); usernameEt = findViewById(R.id.username); clientIdEt = findViewById(R.id.clientId); hostEt = findViewById(R.id.host); connBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { connect(); } }); pubBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String topic = pubTopic.getText().toString(); if (topic.isEmpty()) { topic = "test"; } String message = pubContent.getText().toString(); if (message.isEmpty()) { message = "hello world!"; } publishMessage(topic, message); } }); subBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String topic = subTopic.getText().toString(); if (topic.isEmpty()) { topic = "test"; } subscribeTopic(topic); } }); } /** * String host = "tcp://"; * String clientId = "android_mqtt_client"; * String userName = "admin"; * String passWord = ""; */ public void connect() { String host = hostEt.getText().toString(); String clientId = clientIdEt.getText().toString(); String userName = usernameEt.getText().toString(); String passWord = passwordEt.getText().toString(); /* 获取MQTT连接信息clientId、username、password。 对接阿里云会用到 */ /*//对接阿里云服务 才会用到 final String PRODUCTKEY = "a11xsrW****"; final String DEVICENAME = "paho_android"; final String DEVICESECRET = "tLMT9QWD36U2SArglGqcHCDK9rK9****"; AiotMqttOption aiotMqttOption = new AiotMqttOption().getMqttOption(PRODUCTKEY, DEVICENAME, DEVICESECRET); if (aiotMqttOption == null) { Log.e(TAG, "device info error"); } else { clientId = aiotMqttOption.getClientId(); userName = aiotMqttOption.getUsername(); passWord = aiotMqttOption.getPassword(); }*/ if (clientId.isEmpty()) { clientId = "android_mqtt_client"; } if (host.isEmpty()) { host = "tcp://127.0.0.1:1883"; } /* 创建MqttConnectOptions对象,并配置username和password。 */ MqttConnectOptions mqttConnectOptions = new MqttConnectOptions(); if (!userName.isEmpty()) { mqttConnectOptions.setUserName(userName); } if (!passWord.isEmpty()) { mqttConnectOptions.setPassword(passWord.toCharArray()); } if (mqttAndroidClient != null) { try { mqttAndroidClient.disconnect(); //断开连接 } catch (MqttException e) { e.printStackTrace(); } mqttAndroidClient = null; } /* 创建MqttAndroidClient对象,并设置回调接口。 */ mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId); String finalHost = host; mqttAndroidClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { Log.i(TAG, "连接掉线>host:" + finalHost + "," + cause.getMessage()); status.setText("未连接>host:" + finalHost + "," + cause.getMessage()); } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload())); subText.append("topic: " + topic + ", msg: " + new String(message.getPayload()) + "\n\n"); } @Override public void deliveryComplete(IMqttDeliveryToken token) { Log.i(TAG, "已发送"); } }); /* 建立MQTT连接。 */ try { mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.i(TAG, "连接成功:" + finalHost); status.setText("已连接:" + finalHost); // subscribeTopic("test"); // subscribeTopic("/device_online_status"); // subscribeTopic("/read-property"); // subscribeTopic("/report-property"); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.i(TAG, "连接失败>host:" + finalHost + "," + exception.getMessage()); status.setText("未连接>host:" + finalHost + "," + exception.getMessage()); exception.printStackTrace(); } }); } catch (MqttException e) { Log.i(TAG, "连接失败:" + e.getMessage()); status.setText("未连接:" + e.getMessage()); e.printStackTrace(); } } public void publishMessage(String topic, String payload) { try { if (mqttAndroidClient.isConnected() == false) { mqttAndroidClient.connect(); } MqttMessage message = new MqttMessage(); message.setPayload(payload.getBytes()); message.setQos(0); mqttAndroidClient.publish(topic, message, null, new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.i(TAG, "发布成功>topic:" + topic + ",payload:" + payload); pubText.append("发布成功>topic:" + topic + ",payload:" + payload + "\n\n"); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.i(TAG, "发布失败>topic:" + topic + ",payload:" + payload); pubMsg.setText(exception.getMessage()); pubText.append("发布失败>topic:" + topic + ",payload:" + payload + "\n\n"); exception.printStackTrace(); } }); } catch (MqttException e) { Log.i(TAG, "发布失败>topic:" + topic + ",payload:" + payload); pubMsg.setText(e.getMessage()); pubText.append("发布失败>topic:" + topic + ",payload:" + payload + "\n\n"); e.printStackTrace(); } } public void subscribeTopic(String topic) { try { mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { Log.i(TAG, "订阅成功>topic:" + topic); subTopics.append(topic + "\n"); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { Log.i(TAG, "订阅失败>topic:" + topic); pubMsg.setText(exception.getMessage()); exception.printStackTrace(); } }); } catch (MqttException e) { Log.i(TAG, "订阅失败>topic:" + topic); subMsg.setText(e.getMessage()); e.printStackTrace(); } } @Override public void onDestroy() { if (mqttAndroidClient != null) { try { mqttAndroidClient.disconnect(); //断开连接 } catch (MqttException e) { e.printStackTrace(); } } super.onDestroy(); } }
参考:https://www.alibabacloud.com/help/zh/doc-detail/146630.htm
本文连接:https://www.cnblogs.com/muphy/p/14702211.html