有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

我使用泛美卫生组织图书馆和服务作为客户,只要我连接到wifi,并且经纪人处于开启状态,一切都能完美运行

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

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

我在清单中有以下权限:

    安卓.permission.INTERNET"
    安卓:name="安卓.permission.ACCESS_NETWORK_STATE"
    安卓.permission.WAKE_LOCK"

当我运行模拟器并断开wifi连接时,整个应用程序以及服务崩溃,错误如下

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

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

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

以下是isWifiConnected(如果我没有在应用程序中添加^{,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=安卓.net.conn.CONNECTIVITY_CHANGE flg=0x4200010 (has extras) } in org.eclipse.paho.安卓.service.MqttService$NetworkConnectionIntentReceiver@5224905
        at 安卓.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1401)
        at 安卓.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
        at 安卓.os.Handler.handleCallback(Handler.java:873)
        at 安卓.os.Handler.dispatchMessage(Handler.java:99)
        at 安卓.os.Looper.loop(Looper.java:193)
        at 安卓.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.安卓.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.安卓.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.安卓.service.MqttConnection.reconnect(MqttConnection.java:1049)
        at org.eclipse.paho.安卓.service.MqttService.reconnect(MqttService.java:342)
        at org.eclipse.paho.安卓.service.MqttService$NetworkConnectionIntentReceiver.onReceive(MqttService.java:827)
        at 安卓.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0(LoadedApk.java:1391)
        at 安卓.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2) 
        at 安卓.os.Handler.handleCallback(Handler.java:873) 
        at 安卓.os.Handler.dispatchMessage(Handler.java:99) 
        at 安卓.os.Looper.loop(Looper.java:193) 
        at 安卓.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.安卓.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.安卓.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
I/Process: Sending signal. PID: 7394 SIG: 9
Application terminated.

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

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


共 (1) 个答案

  1. # 1 楼答案

    你说:

    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();
    }
    
    }
    
    1. 您必须在清单文件中声明org.eclipse.paho.android.service.MqttServiceYour Service Class
    <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" />
    

    我希望这对你有帮助
    祝福