android客户端 Mqtt连接+定时发送+订阅消息

1、引入依赖包

//Android mqtt客户端
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'

2、Mqtt service使用类

继承了service类,使用service订阅和发布消息

public class IotMqttService extends Service {
    private static MqttAndroidClient mqttAndroidClient;
    public final String TAG = IotMqttService.class.getSimpleName();
    public String HOST = "tcp://*.*.*.*:*";//服务器地址(协议+地址+端口号)
    public String USERNAME = "admin";//用户名
    public String PASSWORD = "password";//密码

    // 订阅的主题
    public static String TURN_ON_TOPIC = ""; //开的主题
    public static String TURN_OFF_TOPIC = ""; //关的主题
    public static String QUERY_TOPIC = ""; //查询的主题

    // 返回结果的主题
    public static String RESPONSE_TOPIC = "";

    public String CLIENTID = String.valueOf(new Date().getTime());//客户端标识(唯一性)
    private MqttConnectOptions mMqttConnectOptions;
    //MQTT是否连接成功的监听
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {
        @Override
        public void onSuccess(IMqttToken arg0) {
            Toast.makeText(getApplicationContext(),"Mqtt连接成功",Toast.LENGTH_LONG).show();
            // 注册订阅信息
            MqttSubscribes();
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            arg1.printStackTrace();
            Toast.makeText(getApplicationContext(),"Mqtt连接失败!",Toast.LENGTH_LONG).show();
            doClientConnection();//连接失败,重连(可关闭服务器进行模拟)
        }
    };

    //订阅主题的回调
    private MqttCallback mqttCallback = new MqttCallback() {
        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            String result = new String(message.getPayload());
            Log.i(TAG, "Mqtt收到消息: " + result);
            Log.i(TAG, "Mqtt收到消息topic: " + topic);
            //收到消息,这里弹出Toast表示。如果需要更新UI,可以使用广播或者EventBus进行发送
            Toast.makeText(getApplicationContext(),"Mqtt收到消息:"+result,Toast.LENGTH_LONG).show();
            //收到其他客户端的消息后,响应给对方告知消息已到达或者消息有问题等
            response(topic,result);
            //需要在这个地方根据返回的topic来对消息进行区分和处理
            //收到的消息分为执行和查询 1、查询每个开关的状态;2、执行对某个开关的操作。执行完成后需要进行返回
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {

        }

        @Override
        public void connectionLost(Throwable arg0) {
            Log.i(TAG, "连接断开 ");
            Toast.makeText(getApplicationContext(),"Mqtt连接断开!",Toast.LENGTH_LONG).show();
            doClientConnection();//连接断开,重连
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        //初始化mqtt的链接参数

        // 可根据不同的设备设置不同的主题,例如设备1:client001只会接收到自己的主题消息
        TURN_ON_TOPIC = "mqtt/switch/" + WebSettingConfig.getInstance().getClientId() + "/on"; //开的主题
        TURN_OFF_TOPIC = "mqtt/switch/" + WebSettingConfig.getInstance().getClientId() + "/off"; //关的主题
        QUERY_TOPIC = "mqtt/switch/" + WebSettingConfig.getInstance().getClientId() + "/query"; //查询的主题
        RESPONSE_TOPIC = "mqtt/switch/" + WebSettingConfig.getInstance().getClientId() + "/query/response";
        init();

    }

    /**
     * 开启服务
     */
    public static void startService(Context mContext) {
        mContext.startService(new Intent(mContext, IotMqttService.class));
    }

    /**
     * 发布 (向服务器发送消息)
     *@param topic 主题
     * @param message 消息
     */
    public static void publish(String topic, String message) {
        Integer qos = 2;
        Boolean retained = false;
        try {
            Log.v("IotMqttService:topic="+topic, "Mqtt发送消息:"+message);
            //参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
            mqttAndroidClient.publish(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 响应 (收到mqtt消息后,响应给对方告知消息已到达或者消息有问题等)
     *
     * @param result 消息
     */
    public void response(String topic, String result) {
        JSONObject jsonResult = JSONObject.parseObject(result);
        if(jsonResult.getString("equipmentNo").equals(WebSettingConfig.getInstance().getClientId())){
            if(topic.equals(QUERY_TOPIC)){ // 查询
                publish(RESPONSE_TOPIC,"{}");
            }else if(topic.equals(TURN_ON_TOPIC)){ // 开
                publish(RESPONSE_TOPIC,"{}");
            }else if(topic.equals(TURN_OFF_TOPIC)){ // 关
                publish(RESPONSE_TOPIC,"{}");
            }
        }
    }

    /**
     * 初始化
     */
    private void init() {
        String serverURI = HOST; //服务器地址(协议+地址+端口号)
        mqttAndroidClient = new MqttAndroidClient(this, serverURI, CLIENTID);
        mqttAndroidClient.setCallback(mqttCallback); //设置监听订阅消息的回调
        mMqttConnectOptions = new MqttConnectOptions();
        mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存
        mMqttConnectOptions.setConnectionTimeout(10); //设置超时时间,单位:秒
        mMqttConnectOptions.setKeepAliveInterval(10); //设置心跳包发送间隔,单位:秒
        mMqttConnectOptions.setAutomaticReconnect(true); // 设置自动重连
        mMqttConnectOptions.setUserName(USERNAME); //设置用户名
        mMqttConnectOptions.setPassword(PASSWORD.toCharArray()); //设置密码

        doClientConnection();
    }

    /**
     * 注册订阅
     * 订阅就是被动接受(接受另一个设备发送的topic)
     */
    public void MqttSubscribes(){
        try {
            //订阅开的主题、服务质量
            Log.v(TAG,"订阅topic:"+TURN_ON_TOPIC);
            mqttAndroidClient.subscribe(TURN_ON_TOPIC, 2);
            //订阅关的主题、服务质量
            Log.v(TAG,"订阅topic:"+TURN_OFF_TOPIC);
            mqttAndroidClient.subscribe(TURN_OFF_TOPIC, 2);
            //订阅查询的主题、服务质量
            Log.v(TAG,"订阅topic:"+QUERY_TOPIC);
            mqttAndroidClient.subscribe(QUERY_TOPIC, 2);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接MQTT服务器
     */
    private void doClientConnection() {
        if (!mqttAndroidClient.isConnected() && isConnectIsNomarl()) {
            try {
                mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 判断网络是否连接
     */
    private boolean isConnectIsNomarl() {
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            String name = info.getTypeName();
            Log.i(TAG, "当前网络名称:" + name);
            return true;
        } else {
            Log.i(TAG, "没有可用网络");
            /*没有可用网络的时候,延迟3秒再尝试重连*/
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    doClientConnection();
                }
            }, 3000);
            return false;
        }
    }

    @Override
    public void onDestroy() {
        try {
            mqttAndroidClient.disconnect(); //断开连接
        } catch (MqttException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }
}

3、定时任务类

定时任务也是继承的service类

public class TimingService extends Service {
    private String TAG = "TimingService";
    int TIME_INTERVAL = 1000*60*1; // 设置3分钟执行一次
    PendingIntent pendingIntent;
    AlarmManager alarmManager;
    public static final String TEST_ACTION = "timingService";


    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter intentFilter = new IntentFilter(TEST_ACTION);
        registerReceiver(receiver, intentFilter);
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent intent = new Intent();
        intent.setAction(TEST_ACTION);
        pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//6.0低电量模式需要使用该方法触发定时任务
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4以上 需要使用该方法精确执行时间
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), pendingIntent);
        } else {//4.4一下 使用老方法
            alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), TIME_INTERVAL, pendingIntent);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (TEST_ACTION.equals(action)) {
                Log.v(TAG,"定时任务执行");
                sendReadStatusOrder();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TIME_INTERVAL, pendingIntent);
                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + TIME_INTERVAL, pendingIntent);
                }
            }
        }
    };

    /**
     * 发送指令读取
     */
    public void sendReadStatusOrder(){
        try{
            for (int i=3;i<11;i++){
                int timeNumber = 1000*(i-3);
                Message msg = new Message();
                msg.what = 0;
                msg.obj = "指令";
                sendHandler.sendMessageDelayed(msg,timeNumber);
            }
        }catch (Exception e){
            e.printStackTrace();
            Log.e(TAG,Log.getStackTraceString(e));
        }
    }

    Handler sendHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            String result = msg.obj.toString();

        }
    };
}

4、初始化service

在mainfest中注册


        <!--MqttService-->
        <service android:name="org.eclipse.paho.android.service.MqttService" />
        <!--自定义MqttService-->
        <service android:name="com.lotaai.bookroom.service.IotMqttService"/>
        <!--定时任务service-->
        <service android:name="com.lotaai.bookroom.service.TimingService"/>

5、在activity中启动service以及发送消息


public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent mqttIntent = new Intent(MainActivity.this,IotMqttService.class);
        startService(mqttIntent);
        Intent timeIntent = new Intent(MainActivity.this,TimingService.class);
        startService(timeIntent);
    }

    public void sendMeessage(){
        IotMqttService.publish(IotMqttService.RESPONSE_TOPIC,paramsStr);
    }
}

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要实现Android MQTT客户端连接订阅、发布和接收订阅消息,可以按照以下步骤进行: 1. 添加MQTT库依赖 在Android Studio中,打开 build.gradle 文件,然后在 dependencies 中添加以下依赖项: ``` implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' ``` 2. 创建MQTT客户端Android应用程序中,创建一个MqttAndroidClient对象来表示MQTT客户端。这需要指定MQTT服务器的URI和客户端ID: ``` String serverUri = "tcp://mqtt.eclipse.org:1883"; String clientId = "my_android_client_id"; MqttAndroidClient mqttClient = new MqttAndroidClient(this, serverUri, clientId); ``` 3. 连接MQTT服务器 使用MqttConnectOptions对象设置连接参数,如用户名和密码,然后使用MqttAndroidClient对象连接MQTT服务器: ``` MqttConnectOptions options = new MqttConnectOptions(); options.setUserName("my_username"); options.setPassword("my_password".toCharArray()); mqttClient.connect(options); ``` 4. 订阅MQTT主题 使用MqttAndroidClient对象订阅MQTT主题,可以使用QoS(服务质量)参数指定消息传递的可靠性级别: ``` String topic = "my_topic"; int qos = 1; mqttClient.subscribe(topic, qos); ``` 5. 发布MQTT消息 使用MqttMessage对象创建要发布的消息,然后使用MqttAndroidClient对象将其发布到指定的主题: ``` String topic = "my_topic"; String payload = "Hello, MQTT!"; MqttMessage message = new MqttMessage(payload.getBytes()); mqttClient.publish(topic, message); ``` 6. 处理MQTT消息 要处理接收到的MQTT消息,可以使用MqttCallback接口并将其附加到MqttAndroidClient对象上: ``` mqttClient.setCallback(new MqttCallback() { @Override public void connectionLost(Throwable cause) { // 处理连接丢失事件 } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { // 处理收到消息事件 } @Override public void deliveryComplete(IMqttDeliveryToken token) { // 处理消息发送完成事件 } }); ``` 以上就是基本的Android MQTT客户端连接订阅、发布和接收订阅消息的步骤。需要根据你的实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专业前端小白

写了这么久文章,1分钱都没收到

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值