MqttAndroidClient的使用

尽意
2023-02-04 / 1 评论 / 302 阅读
温馨提示:
本文最后更新于2023年02月04日,已超过1367天没有更新,若内容或图片失效,请留言反馈。
MQTT协议特点

MQTT是一个由IBM主导开发的物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。它的核心设计思想是开源、可靠、轻巧、简单,具有以下主要的几项特性:

  • 非常小的通信开销(最小的消息大小为 2 字节);
  • 支持各种流行编程语言(包括C,Java,Ruby,Python 等等)且易于使用的客户端;
  • 支持发布 / 预定模型,简化应用程序的开发;
  • 提供三种不同消息传递等级,让消息能按需到达目的地,适应在不稳定工作的网络传输需求
  • 应项目要求使用MQTT协议实现客户端与服务端通信。Android端使用MqttAndroidClient实现MQTT通信:MqttAndroidClient
MqttAndroidClient配置

在项目根目录下的build.gradle中添加:

repositories {
    maven {
        url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
    }
}

在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'
    //eventbus 各个组件之间进行通信
    implementation 'org.greenrobot:eventbus:3.1.1'
}


在AndroidManifest.xml中添加:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

在AndroidManifest.xml中添加:

        <service
            android:name=".MQTTService"
            android:enabled="true"
            android:exported="true" />
        <service android:name="org.eclipse.paho.android.service.MqttService" />

MQTTService.java

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;


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.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;

public class MQTTService extends Service {

    private static MqttAndroidClient mqttAndroidClient;//声明
    final String serverUri = "tcp://43.139.79.48:1883";//mqtt地址
    String clientId = "hello";//客户端的ID
    public static String subscriptionTopic = "test";//订阅的主题
    public static String publishTopic = "test";//发布的主题
    public MQTTService() {

    }
    //与mainactivit之间通信的
    class MyBinder extends Binder{
        //activity与service之间进行通信的桥梁

    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.i("MQTTService","mqttService start");
        mqttinit();//mqtt的初始化
        return new MyBinder();//返回Binder的实例
    }
    //mqtt的初始化
    private void mqttinit() {

        mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), serverUri, clientId);
        //设置回调函数
        mqttAndroidClient.setCallback(new MqttCallbackExtended() {
            //连接完成时,自动调用
            @Override
            public void connectComplete(boolean reconnect, String serverURI) {
                Log.i("TempMqtt", "connectComplete: 连接成功");
                //订阅主题
                subscribeToTopic();
            }
            //连接失去的调用
            @Override
            public void connectionLost(Throwable cause) {
                Log.i("TempMqtt", "connectComplete: 断开连接");
            }
            //接收到消息的时候
            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                Log.e("TempMqtt", "connectComplete: 收到消息"+message.toString());
                String str=message.toString();
                //接受的消息,发布到eventbus,post
                EventBus.getDefault().post(new MessageEvent(str));
            }
            //发送消息完成
            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
            }
        });
        //完成 mqtt连接

        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();//定义一个mqttConnectOptions
        mqttConnectOptions.setAutomaticReconnect(true);//自动重连
        mqttConnectOptions.setCleanSession(false);//不清除会话
        try {
            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    //Toast.makeText("MQTTService", "连接成功", Toast.LENGTH_SHORT).show();
                    Log.i("MQTTService", "onSuccess: 连接成功");
                    //进行主题的订阅
                    subscribeToTopic();
                }
                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    // Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();
                    Log.i("MQTTService", "onSuccess: 连接失败");
                }
            });
        } catch (MqttException ex){
            ex.printStackTrace();
        }

    }

    //订阅主题
    public static void subscribeToTopic() {
        try {
            mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
                //订阅成功的时候,就会调用
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    //Toast.makeText(MainActivity.this, "订阅成功", Toast.LENGTH_SHORT).show();
                    Log.i("TempMqtt", "onSuccess: 订阅成功");
                }
                //订阅失败的时候,就会调用
                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    //Toast.makeText(MainActivity.this, "订阅失败", Toast.LENGTH_SHORT).show();
                    Log.i("TempMqtt", "onSuccess: 订阅失败");
                }
            });
        } catch (MqttException ex){
            Log.i("" +
                    "", "onSuccess: Exception whilst subscribing");
            ex.printStackTrace();
        }
    }
    //发布主题
    public static  void publishToTopic(String message){
        try {
            //参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
            mqttAndroidClient.publish(publishTopic, message.getBytes(), 0, false);
            Log.i("TempMqtt", "publishToTopic: 发送消息为"+message);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

}

MessageEvent.java

//然后,我们定义一个事件的封装对象。在程序内部就使用该对象作为通信的信息:
public class MessageEvent {

    public final String message;

    public static MessageEvent getInstance(String message) {
        return new MessageEvent(message);
    }

    MessageEvent(String message) {
        this.message = message;
    }
}

MainActivity.java

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONException;
import org.json.JSONObject;


public class MainActivity extends AppCompatActivity {

    private Intent  mintent;
    private TextView q;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mintent=new Intent(this,MQTTService.class);
        EventBus.getDefault().register(this);//注册EventBus
        bindService(mintent,connection, Context.BIND_AUTO_CREATE);//绑定方式启动服务

        q= (TextView) findViewById(R.id.aa);
        q.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //点击文字发布消息
                MQTTService.publishToTopic("hahaah");
            }
        });

    }

    //当接收到MQTT服务器发送过来的数据的时候,就会调用此函数
    // This method will be called when a MessageEvent is posted (in the UI thread for Toast)
    //表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
    @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
    public  void onReceiveMsg(@NonNull MessageEvent event){
        String str=event.message;
        //在这里,可以进行UI界面的更新
        UiShow(str);
    }
    private void UiShow(String str ){
        try {
            JSONObject jsonMessage=new JSONObject(str);
            String  temp= jsonMessage.getString("msg");
            //Toast.makeText(this, temp, Toast.LENGTH_SHORT).show();
            q.setText(temp);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    //新建了一个 ServiceConnection 实例
    private ServiceConnection connection=new ServiceConnection() {
        //当service与activity连接的时候,调用此方法
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

        }
        //当service与activity失去连接的时候,调用此方法
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);//注销、
        unbindService(connection);//解除绑定
        stopService(mintent);//停止mqtt的服务
        super.onDestroy();
    }
}

在activity_main.xml中,给TextView赋值id

android:id="@+id/aa"
最终效果

ldq28smg.png

ldq2etow.png

1

评论 (1)

取消
  1. 头像
    尽意 作者
    Android · Google Chrome
    {!{data:image/webp;base64,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}!}<
    回复