初学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的话添加依赖的方法会有区别:

  1. 首先在项目主目录的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'
  1. 接着在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'
}
  1. 在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" />
  1. 在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.实现效果

android mqtt 权限 安卓作为mqtt服务端_物联网


android mqtt 权限 安卓作为mqtt服务端_物联网_02