Java wifi断开连接且无法重新连接时,应用程序、服务和mqtt崩溃

Java wifi断开连接且无法重新连接时,应用程序、服务和mqtt崩溃,java,android,mqtt,mosquitto,paho,Java,Android,Mqtt,Mosquitto,Paho,我正在制作一个带有mqtt客户端和后台服务的应用程序,当我收到某个mqtt消息时会发出通知 我使用泛美卫生组织图书馆和服务作为客户,只要我连接到wifi,并且代理处于开启状态,一切都会完美工作 我不想通过互联网访问代理,因此当没有可用的wifi时,客户端会断开连接,问题是当wifi再次连接时,mqtt客户端不会重新连接 我尝试了很多方法,但最近的测试是让处理程序检查是否有互联网,是否通过wifi,如果是,我再次启动mqtt服务器 我在清单中拥有以下权限: android.permissi

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

我使用泛美卫生组织图书馆和服务作为客户,只要我连接到wifi,并且代理处于开启状态,一切都会完美工作

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

我尝试了很多方法,但最近的测试是让处理程序检查是否有互联网,是否通过wifi,如果是,我再次启动mqtt服务器

我在清单中拥有以下权限:

    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);
这是iWifiConnected(如果我没有在应用程序中添加
context context=this;
,context.getSystemService就无法工作,我不知道这是否也是一个问题):

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

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

你说:

问题在于,当wifi再次连接时,mqtt客户端将无法重新连接

  • 您只需在您的
    服务#onCreate()
    方法中使用
    广播接收器
    ,即可收听
    WIFI\u STATE\u CHANGED\u操作
    如下。
  • 您还必须在
    服务#onStartCommand()
    中使用
    return START\u 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();
    }
    
    }
    
  • 您必须在清单文件中声明
    org.eclipse.paho.android.service.MqttService
    您的服务类
  • 
    
    我希望这对你有帮助。

    最美好的祝愿

    谢谢Ghasem Sadeghi先生的帮助实际上我有点困惑你能告诉我如何在活动中访问此服务类或如何使用此服务类订阅香奈儿吗
    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.
    
    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();
    }
    
    }
    
    <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" />