MQTT之Android实现

MQTT之Android实现

在使用之前,配置android端的mqtt需要下面这些参数:

Topic:订阅的事件。在图一中,也就是“主题”——ForTest。
URI:MQTT服务器的地址。也是图一中的服“服务器地址”。
username & password:账户与密码,在图二中。
ClientId:客户端的ID,可以自定义,必须保证唯一性,否则连接服务器的时候会导致服务器断开,不要问我是怎么知道的。比如图一中有一个“客户机标识”,那么ClientId是不能和它一致的。
好了,了解上面这些参数后,然后就是配置android中的mqtt相关库了。

第一步,添加依赖

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

repositories {
maven {
url “https://repo.eclipse.org/content/repositories/paho-releases/”
}
}

然后在app目录下的build.gradle中添加:

dependencies {
compile ‘org.eclipse.paho:org.eclipse.paho.android.service:1.1.1’
compile ‘org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1’
}

第二步,声明权限
在AndroidManifest.xml中添加:





第三步,开启服务:

<service android:name="org.eclipse.paho.android.service.MqttService" />

第四步,具体实现:

我们可以把MQTTD的配置放入Service中去,所以需要创建一个Service,Android studio中可以快捷创建Service,具体操作是【File→New→Service→Service】。

这样会自动在AndroidManifest.xml声明该服务,如果你是通过创建Java类的方式创建服务的,千万别忘了在AndroidManifest.xml中进行声明。

下面是Service的代码:
public class MQTTService extends Service {

public static final String TAG = MQTTService.class.getSimpleName();

private static MqttAndroidClient client;
private MqttConnectOptions conOpt;

private String host = "tcp://192.168.0.11:61613";
private String userName = "admin";
private String passWord = "password";
private static String myTopic = "ForTest";      //要订阅的主题
private String clientId = "androidId";//客户端标识
private IGetMessageCallBack IGetMessageCallBack;


@Override
public void onCreate() {
    super.onCreate();
    Log.e(getClass().getName(), "onCreate");
    init();
}

public static void publish(String msg){
    String topic = myTopic;
    Integer qos = 0;
    Boolean retained = false;
    try {
        if (client != null){
            client.publish(topic, msg.getBytes(), qos.intValue(), retained.booleanValue());
        }
    } catch (MqttException e) {
        e.printStackTrace();
    }
}

private void init() {
    // 服务器地址(协议+地址+端口号)
    String uri = host;
    client = new MqttAndroidClient(this, uri, clientId);
    // 设置MQTT监听并且接受消息
    client.setCallback(mqttCallback);

    conOpt = new MqttConnectOptions();
    // 清除缓存
    conOpt.setCleanSession(true);
    // 设置超时时间,单位:秒
    conOpt.setConnectionTimeout(10);
    // 心跳包发送间隔,单位:秒
    conOpt.setKeepAliveInterval(20);
    // 用户名
    conOpt.setUserName(userName);
    // 密码
    conOpt.setPassword(passWord.toCharArray());     //将字符串转换为字符串数组

    // last will message
    boolean doConnect = true;
    String message = "{\"terminal_uid\":\"" + clientId + "\"}";
    Log.e(getClass().getName(), "message是:" + message);
    String topic = myTopic;
    Integer qos = 0;
    Boolean retained = false;
    if ((!message.equals("")) || (!topic.equals(""))) {
        // 最后的遗嘱
        // MQTT本身就是为信号不稳定的网络设计的,所以难免一些客户端会无故的和Broker断开连接。
        //当客户端连接到Broker时,可以指定LWT,Broker会定期检测客户端是否有异常。
        //当客户端异常掉线时,Broker就往连接时指定的topic里推送当时指定的LWT消息。

        try {
            conOpt.setWill(topic, message.getBytes(), qos.intValue(), retained.booleanValue());
        } catch (Exception e) {
            Log.i(TAG, "Exception Occured", e);
            doConnect = false;
            iMqttActionListener.onFailure(null, e);
        }
    }

    if (doConnect) {
        doClientConnection();
    }

}


@Override
public void onDestroy() {
    stopSelf();
    try {
        client.disconnect();
    } catch (MqttException e) {
        e.printStackTrace();
    }
    super.onDestroy();
}

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

}

// MQTT是否连接成功
private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

    @Override
    public void onSuccess(IMqttToken arg0) {
        Log.i(TAG, "连接成功 ");
        try {
            // 订阅myTopic话题
            client.subscribe(myTopic,1);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFailure(IMqttToken arg0, Throwable arg1) {
        arg1.printStackTrace();
        // 连接失败,重连
    }
};

// MQTT监听并且接受消息
private MqttCallback mqttCallback = new MqttCallback() {

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {

        String str1 = new String(message.getPayload());
        if (IGetMessageCallBack != null){
            IGetMessageCallBack.setMessage(str1);
        }
        String str2 = topic + ";qos:" + message.getQos() + ";retained:" + message.isRetained();
        Log.i(TAG, "messageArrived:" + str1);
        Log.i(TAG, str2);
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken arg0) {

    }

    @Override
    public void connectionLost(Throwable arg0) {
        // 失去连接,重连
    }
};

/** 判断网络是否连接 */
private boolean isConnectIsNormal() {
    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, "MQTT当前网络名称:" + name);
        return true;
    } else {
        Log.i(TAG, "MQTT 没有可用网络");
        return false;
    }
}


@Override
public IBinder onBind(Intent intent) {
    Log.e(getClass().getName(), "onBind");
    return new CustomBinder();
}

public void setIGetMessageCallBack(IGetMessageCallBack IGetMessageCallBack){
    this.IGetMessageCallBack = IGetMessageCallBack;
}

public class CustomBinder extends Binder {
    public MQTTService getService(){
        return MQTTService.this;
    }
}

public  void toCreateNotification(String message){
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, new Intent(this,MQTTService.class), PendingIntent.FLAG_UPDATE_CURRENT);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this);//3、创建一个通知,属性太多,使用构造器模式

    Notification notification = builder
            .setTicker("测试标题")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle("")
            .setContentText(message)
            .setContentInfo("")
            .setContentIntent(pendingIntent)//点击后才触发的意图,“挂起的”意图
            .setAutoCancel(true)        //设置点击之后notification消失
            .build();
    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    startForeground(0, notification);
    notificationManager.notify(0, notification);

}

}

之前看过的博客中都是通过startService去启动服务的,这里改成了通过BindService去启动服务,所以没有onStartCommond方法。

同时,当获取从服务器推送过来的消息时,是使用回调去更新UI,这样做是为了方便代码的迁移。

上面的代码中还需要注意一个MqttAndroidClient.publish()方法,相当于服务器发布一个消息。

下面是回调接口:

public interface IGetMessageCallBack {
public void setMessage(String message);
}

为了实现通过这个回调去传递从服务端获取到的消息,我们需要实现一个ServiceConnection类,并且通过onBind来从Service和Activity之间传递数据:

public class MyServiceConnection implements ServiceConnection {

private MQTTService mqttService;
private IGetMessageCallBack IGetMessageCallBack;

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    mqttService = ((MQTTService.CustomBinder)iBinder).getService();
    mqttService.setIGetMessageCallBack(IGetMessageCallBack);
}

@Override
public void onServiceDisconnected(ComponentName componentName) {

}

public MQTTService getMqttService(){
    return mqttService;
}

public void setIGetMessageCallBack(IGetMessageCallBack IGetMessageCallBack){
    this.IGetMessageCallBack = IGetMessageCallBack;
}

}

最后就是测试环节的代码了:

public class MainActivity extends AppCompatActivity implements IGetMessageCallBack {

private TextView textView;
private Button button;
private MyServiceConnection serviceConnection;
private MQTTService mqttService;

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

    textView = (TextView) findViewById(R.id.text);
    button = (Button) findViewById(R.id.button);

    serviceConnection = new MyServiceConnection();
    serviceConnection.setIGetMessageCallBack(MainActivity.this);

    Intent intent = new Intent(this, MQTTService.class);

    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);


    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            MQTTService.publish("测试一下子");
        }
    });
}

@Override
public void setMessage(String message) {
    textView.setText(message);
    mqttService = serviceConnection.getMqttService();
    mqttService.toCreateNotification(message);
}

@Override
protected void onDestroy() {
    unbindService(serviceConnection);
    super.onDestroy();
}

}
————————————————

提醒:自己的MQTTService 也要记得在AndroidManifest.xml中声明。

原文链接:https://blog.csdn.net/asjqkkkk/article/details/80714234

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值