Android安卓实现mqtt客户端
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>
View Code
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
