java - 即使应用程序关闭,也试图保持 MQTT 客户端连接
问题描述
我目前在我的 android 应用程序中使用 MQTT 协议,当我的应用程序打开或在后台运行时我能够接收消息但是当我完全关闭我的应用程序时连接丢失并且我不再能够接收消息. 我需要能够仍然接收消息,因为我希望消息触发我的应用程序中的活动以启动。以下是我用来实现 MQTT 的文件。MQTTHelper 类:编辑。我已经尝试实施一项服务,但它似乎仍然没有工作。有人知道我做错了什么吗?
package com.example.carcrashdetection.helpers;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions;
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 MqttHelper extends Service {
public MqttAndroidClient mqttAndroidClient;
BroadcastReceiver m_ScreenOffReceiver;
final String serverUri = "tcp://hairdresser.cloudmqtt.com:15767";
final String clientId = "CarCrashDetection";
final String subscriptionTopic = "Topic/+";
final String username = "username";
final String password = "password";
@Override
public void onCreate() {
super.onCreate();
registerReceiver();
new Thread(new Runnable() {
@Override
public void run() {
MqttHelper.this.connect();
}
}).start();
}
public MqttHelper(Context context){
mqttAndroidClient = new MqttAndroidClient(context, serverUri, clientId);
mqttAndroidClient.setCallback(new MqttCallback() {
public void connectComplete(boolean b, String s) {
}
@Override
public void connectionLost(Throwable throwable) {
}
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
Log.w("Mqtt", mqttMessage.toString());
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
});
connect();
}
public void setCallback(MqttCallback callback) {
mqttAndroidClient.setCallback(callback);
}
private void connect(){
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(false);
mqttConnectOptions.setUserName(username);
mqttConnectOptions.setPassword(password.toCharArray());
try {
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setBufferSize(100);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);
subscribeToTopic();
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.w("Mqtt", "Failed to connect to: " + serverUri + exception.toString());
}
});
} catch (MqttException ex){
ex.printStackTrace();
}
}
private void subscribeToTopic() {
try {
mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.w("Mqtt","Subscribed!");
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.w("Mqtt", "Subscribed fail!");
}
});
} catch (MqttException ex) {
System.err.println("Exception whilst subscribing");
ex.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//do something
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void registerReceiver(){
m_ScreenOffReceiver = new BroadcastReceiver(){
@Override
public void onReceive(final Context context, Intent intent){
//Log.d(TAG,"onReceive of Wifi_State_Change called");
if(intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION))
{
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
if(wifiState != WifiManager.WIFI_STATE_ENABLED)
return;
final WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
Toast.makeText(context, "active wifi:" + ssid, Toast.LENGTH_SHORT).show();
//You can connect to the your mqtt broker again:
connect();
}
}, 10000);
}
}
};
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
registerReceiver(m_ScreenOffReceiver, intentFilter);
}
@Override
public void onDestroy() {
if(mqttAndroidClient!=null) {
/*unregisterResources is needed,otherwise receive this error:
has leaked ServiceConnection org.eclipse.paho.android.service.MqttAndroidClient*/
try {
mqttAndroidClient.unregisterResources();
mqttAndroidClient.close();
mqttAndroidClient.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
unregisterReceiver(m_ScreenOffReceiver);
m_ScreenOffReceiver = null;
super.onDestroy();
}
}
主要活动
private void startMqtt(){
mqttHelper = new MqttHelper(getApplicationContext());
mqttHelper.setCallback(new MqttCallbackExtended(){
@Override
public void connectComplete(boolean b, String s) {
Toast.makeText(MainActivity.this, "connected ", Toast.LENGTH_SHORT).show();
}
public void connectionLost(Throwable throwable){
Toast.makeText(MainActivity.this,"Disconnected", Toast.LENGTH_SHORT).show();
}
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception{
Log.e("message ", String.valueOf(mqttMessage));
Toast.makeText(MainActivity.this, "Crash Occurred", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MainActivity.this, alert.class);
startActivity(intent);
}
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken){
}
});
}
我已经搜索了一段时间,但似乎找不到任何有效的方法。我认为这将是一个简单的修复,但它并不适合我。任何帮助将非常感激。
解决方案
您的选择将是实现一个服务器,该服务器将发送您的设备推送通知,然后您的应用程序可以在再次打开后获取该消息。
或者,您可以实现后台服务:https ://developer.android.com/guide/components/services
推荐阅读
- c++ - CWPack - cw_pack_context_init 中的“数据”是什么?
- excel - 如何将 Excel 与 IBM Watson 连接起来
- java - 无需手动编辑构建路径的 JavaFX 11 设置
- symfony - 如何在 FOR 循环中更改元素的值
- javascript - 过滤器值的增加和减少在 Camanjs 中无法正常工作
- php - 如何检查在 php 中完成的 bash shell
- dart - 如何根据第一个流中的事件启动第二个流?
- symfony4 - Symfony4 内核找不到自动加载的类
- python-3.x - 如何避免在activex autocad api上的SendCommand期间保存提示
- c - Cppcheck 在每次扫描时返回不同的结果