App, service and mqtt crashes when wifi disconnects and wont reconnect

我与影子孤独终老i 提交于 2019-12-02 05:48:22

You said:

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

  1. You can simply use a BroadcastReceiver in your Service#onCreate() method that is listening to WIFI_STATE_CHANGED_ACTION action as below.
  2. Also you have to use return START_STICKY in your Service#onStartCommand(), So that the service class will be running after application is closed.

Service class:

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. You have to declare org.eclipse.paho.android.service.MqttService and Your Service Class in your Manifest file:
<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" />

I hope this helps you.
Best wishes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!