gpt4 book ai didi

java - 当 WiFi 断开且无法重新连接时,应用程序、服务和 mqtt 崩溃

转载 作者:太空宇宙 更新时间:2023-11-04 09:26:46 25 4
gpt4 key购买 nike

我正在制作一个带有 mqtt 客户端和后台服务的应用程序,当我收到某些 mqtt 消息时,该服务会发出通知。

我使用 Paho 库和服务作为客户端,只要我连接到 WiFi 并且代理处于打开状态,一切都会正常工作。

我不想通过互联网访问代理,因此当没有可用的 wifi 时,客户端会断开连接,问题是当 wifi 再次连接时,mqtt 客户端将无法重新连接。

我已经尝试了很多事情,但最新的测试是让处理程序检查是否有互联网以及是否通过 wifi,如果是,我再次启动 mqtt 服务器。

我在 list 中拥有以下权限:

    android.permission.INTERNET"
android:name="android.permission.ACCESS_NETWORK_STATE"
android.permission.WAKE_LOCK"

当我运行模拟器并断开 WiFi 时,整个应用程序崩溃,服务也崩溃,并出现以下错误

这是我正在使用的处理程序:

    handler.postDelayed(new Runnable(){
public void run(){
if (isWifiConnected()) {
startMqtt();
}

handler.postDelayed(this, delay);
}
}, delay);

这是 isWifiConnected (如果我没有在应用程序中添加 Context context = this; ,context.getSystemService 就无法工作,我不知道这是否也是一个问题):

    private boolean isWifiConnected() {
boolean isWifi;
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

return isWifi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
}
D/AlarmPingSender: Unregister alarmreceiver to MqttServicephone
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
I/chatty: uid=10085(com.iteda.nome) identical 85 lines
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
I/chatty: uid=10085(com.iteda.nome) identical 4 lines
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
I/chatty: uid=10085(com.iteda.nome) identical 36 lines
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
I/chatty: uid=10085(com.iteda.nome) identical 17 lines
W/Mqtt: Failed to connect to: tcp://192.168.1.39:1883Unable to connect to server (32103) - java.net.ConnectException: failed to connect to /192.168.1.39 (port 1883) from /:: (port 0) after 30000ms: connect failed: ENETUNREACH (Network is unreachable)
I/MqttConnection: Requesting Automatic reconnect using New Java AC
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.iteda.nome, PID: 7394
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.conn.CONNECTIVITY_CHANGE flg=0x4200010 (has extras) } in org.eclipse.paho.android.service.MqttService$NetworkConnectionIntentReceiver@5224905
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1401)
at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void java.util.Timer.cancel()' on a null object reference
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.stopReconnectCycle(MqttAsyncClient.java:1120)
at org.eclipse.paho.client.mqttv3.MqttAsyncClient.reconnect(MqttAsyncClient.java:1057)
at org.eclipse.paho.android.service.MqttConnection.reconnect(MqttConnection.java:1049)
at org.eclipse.paho.android.service.MqttService.reconnect(MqttService.java:342)
at org.eclipse.paho.android.service.MqttService$NetworkConnectionIntentReceiver.onReceive(MqttService.java:827)
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1391)
at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2) 
at android.os.Handler.handleCallback(Handler.java:873) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6669) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
I/Process: Sending signal. PID: 7394 SIG: 9
Application terminated.

我知道你可能想要更多信息,所以不要让我用错误的代码轰炸,告诉我你需要什么来看看我做错了什么:)

错误代码似乎给出了答案,但因为我对 android 和 java 还很陌生。我不知道如何改变方法以使其正确。

最佳答案

你说:

the problem is that when the wifi connects again the mqtt client wont reconnect.

  1. 您只需在 Service#onCreate() 方法中使用 BroadcastReceiver 来监听 WIFI_STATE_CHANGED_ACTION 操作,如下所示。
  2. 此外,您还必须在 Service#onStartCommand() 中使用 return START_STICKY,这样服务类将在应用程序关闭后运行。

服务等级:

public class MQTTService extends Service {

private MqttAndroidClient clientPhone;

@Override
public void onCreate() {
super.onCreate();
registerReceiver();
new Thread(() -> init()).start();
}

@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(() -> {
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:
connectMQTT();
}, 10000);
}
}
};

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
registerReceiver(m_ScreenOffReceiver, intentFilter);
}

private void init() {

clientPhone = new MqttAndroidClient(this, "tcp://IP:PORT", "Your-CLIENT-ID");
//clientPhone = new MqttAndroidClient(this, "ssl://IP:PORT", "Your-CLIENT-ID");

clientPhone.setCallback(new MqttCallback() {
@Override
public void connectionLost(Throwable cause) {
//do something - for example reconnnect again
}

@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
//you can do everything with the received message from broker here
}

@Override
public void deliveryComplete(IMqttDeliveryToken token) {
//do something
}
});
}

private MqttConnectOptions getOptions(){

if(clientPhone.getServerURI().contains("ssl")) {
//set ssl config.for example:
//options.setSocketFactory(clientPhone.getSSLSocketFactory(YOUR_KEYSTORE_FILE, "YOUR_KEYSTORE_PASSWORD"));
//...
}
options.setKeepAliveInterval(...);
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
options.setAutomaticReconnect(true);
options.setCleanSession(...);
//options.setWill(...);
options.setUserName(...));
options.setPassword(...);
return options;
}

private void connectMQTT() {
try {
//getOptions is a method that returns your MqttConnectOptions object
IMqttToken token = clientPhone.connect(getOptions());
token.setActionCallback(new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
//do something
}
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
//do something
}
});
} catch (MqttException e) {
//do something
e.printStackTrace();
}
}


@Override
public void onDestroy() {
if(clientPhone!=null) {
/*unregisterResources is needed,otherwise receive this error:
has leaked ServiceConnection org.eclipse.paho.android.service.MqttAndroidClient*/
try {
clientPhone.unregisterResources();
clientPhone.close();
clientPhone.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
unregisterReceiver(m_ScreenOffReceiver);
m_ScreenOffReceiver = null;
...
super.onDestroy();
}

}
  • 您必须在 list 文件中声明org.eclipse.paho.android.service.MqttService您的服务类:
  • <service
    android:name="org.eclipse.paho.android.service.MqttService"
    android:enabled="true" />
    <service
    android:name="YOUR-MQTT-SERVICE-CLASS"
    android:enabled="true"
    android:exported="false" />

    希望这对您有帮助。
    最美好的祝愿

    关于java - 当 WiFi 断开且无法重新连接时,应用程序、服务和 mqtt 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57598554/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com