初学Android Studio,在实现MQTT客户端的过程中遇到了很多坑,而在查阅博文的时候发现各个博文能提供的解决方法很零碎,我也是结合了诸多博文才最终解决了问题,于是打算做一个小总结
我用的版本是Android Studio Bumblebee | 2021.1.1 Patch 1,所以接下来记录的方法比较适用于解决新版本遇到的问题
本文实现MQTT客户端的方法比较初级,后续在能保证基本功能实现的情况下可以使用继承Service类的方法实现MQTT服务
0. 配置MQTT服务器
如果还没有mqtt服务器的同学,可以去一些知名的物联网云平台弄,也可以跟我一样参考以下文章搭建自己的mqtt服务器(基于mosquitto)
1. Android中使用MQTT
Android中使用MQTT需要使用到Paho Android Service库,Paho Android Service是一个用Java编写的MQTT客户端库。
GitHub地址:https://github.com/eclipse/paho.mqtt.android
1.1 集成
在我找的一些博文中会在module的build.gradle文件中添加依赖,但新版本Android Studio的话添加依赖的方法会有区别:
- 首先在项目主目录的settings.gradle添加
repositories {
maven {
url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
}
}
settings.gradle:
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
maven {
url "https://repo.eclipse.org/content/repositories/paho-releases/"
}
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url "https://repo.eclipse.org/content/repositories/paho-releases/"
}
}
}
rootProject.name = "mqtt_example"
include ':app'
- 接着在app目录下的build.gradle添加
dependencies {
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
}
- 在AndroidManifest.xml添加限权
<!-- Permissions the Application Requires -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
- 在AndroidManifest.xml注册Service
<!-- Mqtt Service -->
<service android:name="org.eclipse.paho.android.service.MqttService">
</service>
注意,androidx在依赖第三方库时,第三方库自身使用v4库,会引起程序崩溃,而androidx项目接入mqtt时,引入了依赖库
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.2'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
这是由于第三方库引入的v4库没有转化为androidx导致。
此时在程序根目录的gradle.propertites文件启用一下代码,可以正常运行程序
android.enableJetifier=true
1.2 MQTT客户端实现
实现方法比较简单,直接在MainActivity上建立MqttClient,按一下按钮发送信息
package com.example.mqtt_example;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
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 final String TAG = "AiotMqtt";
final private String PUB_TOPIC = "pubtopic"; //发送主题
final private String SUB_TOPIC = "substopic"; //订阅主题
/* 阿里云Mqtt服务器域名 */
final String host = "tcp://xxx.xxx.xxx.xxx:xxxxx"; //服务器地址(协议+地址+端口号)
private String clientId = "AndroidTest"; //客户端ID
private String userName = "xxxxxx"; //用户名
private String passWord = "xxxxx"; //密码
MqttAndroidClient mqttAndroidClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* 创建MqttConnectOptions对象并配置username和password */
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setUserName(userName);
mqttConnectOptions.setPassword(passWord.toCharArray());
/* 创建MqttAndroidClient对象, 并设置回调接口 */
mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), host, clientId);
mqttAndroidClient.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
Log.i(TAG, "connection lost");
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG, "topic: " + topic + ", msg: " + new String(message.getPayload()));
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i(TAG, "msg delivered");
}
});
/* Mqtt建连 */
try {
mqttAndroidClient.connect(mqttConnectOptions,null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "connect succeed");
subscribeTopic(SUB_TOPIC);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "connect failed");
}
});
} catch (MqttException e) {
e.printStackTrace();
}
/* 通过按键发布消息 */
Button pubButton = findViewById(R.id.publish);
pubButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
publishMessage("hello IoT");
}
});
}
/**
* 订阅特定的主题
* @param topic mqtt主题
*/
public void subscribeTopic(String topic) {
try {
mqttAndroidClient.subscribe(topic, 0, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "subscribed succeed");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "subscribed failed");
}
});
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 向默认的主题/user/update发布消息
* @param payload 消息载荷
*/
public void publishMessage(String payload) {
try {
if (mqttAndroidClient.isConnected() == false) {
mqttAndroidClient.connect();
}
MqttMessage message = new MqttMessage();
message.setPayload(payload.getBytes());
message.setQos(0);
mqttAndroidClient.publish(PUB_TOPIC, message,null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "publish succeed!");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i(TAG, "publish failed!");
}
});
} catch (MqttException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
}
2.实现效果