-->

保持MQTT主题订阅活动的onResume(Keep MQTT Topics Subscribed

2019-09-28 08:03发布

我有一个MQTT服务类,MyMqttService.class,乳宁当我登录在我的应用程序:

    Intent intent = new Intent(getApplicationContext(), MyMqttService.class);
    startService(intent);

然后,我有各种各样的活动,并在其中的一个,我有开关按钮,选择我要订阅的频道。 在我的onPause /的onResume,我检查哪些按钮上的开关状态,让他们去到相同的状态,当我回来的那个活动。 问题是,如果有,当我恢复活动,我得到一个错误,我aplication崩溃的至少一个按钮,因为我的应用程序试图以认购,和着。

我的服务类:

public class MyMqttService extends Service implements MqttCallback, IMqttActionListener {

    private final IBinder binder = new MyBinder();

    private MqttAndroidClient mqttClient;
    private MqttConnectOptions mqttConnectOptions;
    private static final MemoryPersistence persistence = new MemoryPersistence();
    private ArrayList<MqttAndroidClient> lostConnectionClients;

    private String clientId = "";
    private boolean isReady = false;
    private boolean doConnectTask = true;
    private boolean isConnectInvoked = false;

    private Handler handler = new Handler();
    private final int RECONNECT_INTERVAL = 10000; // 10 seconds
    private final int DISCONNECT_INTERVAL = 20000; // 20 seconds
    private final int CONNECTION_TIMEOUT = 60;
    private final int KEEP_ALIVE_INTERVAL = 200;

    private String broker_url = "xxx.xxx.xxx.xxx";

    public class MyBinder extends Binder {

        public MyMqttService getService() {

            return MyMqttService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        initMqttClient();
    }

    private void initMqttClient() {
        if(mqttClient != null) {
            mqttClient = null;
        }
        lostConnectionClients = new ArrayList<>();

        mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setCleanSession(true);
        mqttConnectOptions.setConnectionTimeout(CONNECTION_TIMEOUT);
        mqttConnectOptions.setKeepAliveInterval(KEEP_ALIVE_INTERVAL);

        setNewMqttClient();

        handler.post(connect);
        handler.postDelayed(disconnect, DISCONNECT_INTERVAL);
    }

    private void setNewMqttClient() {
        mqttClient = new MqttAndroidClient(MyMqttService.this, broker_url, clientId, persistence);
        mqttClient.setCallback(this);
    }

    public Runnable connect = new Runnable() {
        public void run() {
            connectClient();
            handler.postDelayed(connect, RECONNECT_INTERVAL);
        }
    };

    public Runnable disconnect = new Runnable() {
        public void run() {
            disconnectClients();
            handler.postDelayed(disconnect, DISCONNECT_INTERVAL);
        }
    };

    private void connectClient() {
        if(doConnectTask) {
            doConnectTask = false;
            try {
                isConnectInvoked = true;
                mqttClient.connect(mqttConnectOptions, null, this);
            } catch (MqttException ex) {
                doConnectTask = true;
                System.out.println("MQTT exception 1: " + ex.toString());
            }
        }
    }

    private void disconnectClients() {
        if (lostConnectionClients.size() > 0) {
            // Disconnect lost connection clients
            for (MqttAndroidClient client : lostConnectionClients) {
                if (client.isConnected()) {
                    try {
                        client.disconnect();
                    } catch (MqttException e) {
                        System.out.println("MQTT exception 2: " + e.toString() );
                    }
                }
            }

            // Close already disconnected clients
            for (int i = lostConnectionClients.size() - 1; i >= 0; i--) {
                try {
                    if (!lostConnectionClients.get(i).isConnected()) {
                        MqttAndroidClient client = lostConnectionClients.get(i);
                        client.close();
                        lostConnectionClients.remove(i);
                    }
                } catch (IndexOutOfBoundsException e) {
                    System.out.println("MQTT exception 3: " + e.toString());
                }
            }
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onSuccess(IMqttToken asyncActionToken) {
        isReady = true;

        // subscribe here
        subscribe("");
    }

    @Override
    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
        setNewMqttClient();
        isReady = false;
        doConnectTask = true;
        isConnectInvoked = false;
    }

    public void subscribe(String topic) {
        try {
            mqttClient.subscribe(topic, 0);
            isReady = true;
        } catch (MqttSecurityException mqttSexEx) {
            isReady = false;
        } catch (MqttException mqttEx) {
            isReady = false;
        }
    }

    private void unsubscribe(String topic) {
        try {
            mqttClient.unsubscribe(topic);
        } catch (MqttSecurityException mqttSecEx) {
            System.out.println("MQTT exception 4: " + mqttSecEx.toString());
        } catch (MqttException mqttEx) {
            System.out.println("MQTT exception 5: " + mqttEx.toString());
        }
    }

    private void publish(String topic, String jsonPayload) {
        if(!isReady) {
            return;
        }

        try {
            MqttMessage msg = new MqttMessage();
            msg.setQos(0);
            msg.setPayload(jsonPayload.getBytes("UTF-8"));
            mqttClient.publish(topic, msg);
        } catch (Exception ex) {
            System.out.println("MQTT exception 6: " + ex.toString());
        }
    }



    @Override
    public void connectionLost(Throwable cause) {
        System.out.println("MQTT exception 7: " + cause.getMessage());
    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        String payload = new String(message.getPayload());
        // do something
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("MQTT exception 8: deliveryComplete()");
    }
}

我与SWICH按钮,在这里我订阅的活动:

public class DefinicoesActivity extends AppCompatActivity {

    private Switch switchSaude;
    private Switch switchAlimentacao;
    private Switch switchDesporto;

    private static Bundle bundle = new Bundle();

    private String topico;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_definicoes);

        final MqttAndroidClient mqttAndroidClient = new MqttAndroidClient(this.getApplicationContext(), "tcp://5.196.27.244:1883", "users");

        mqttAndroidClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {

            }

            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                String payload = new String(message.getPayload());
                String titulo = payload.substring(0, payload.indexOf("\n"));
                System.out.println("mensagem receitas:" + titulo + " " + topic);
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {

            }
        });

        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setCleanSession(true);

        try {
            mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    System.out.println("Connection Success!");
                    try {
                        System.out.println("Subscribing to /test");
                        mqttAndroidClient.subscribe("/test", 0);
                        System.out.println("Subscribed to /test");
                    } catch (MqttException ex) {
                        System.out.println("MQTT Definicoes excpetion: " + ex);
                    }
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    System.out.println("MQTT Definicoes excpetion 2:" + exception.toString());
                }
            });
        } catch (MqttException ex) {
            System.out.println("MQTT Definicoes excpetion 3:" + ex.toString());
        }


        switchSaude = findViewById(R.id.switchSaude);
        switchAlimentacao = findViewById(R.id.switchAlimentacao);
        switchDesporto = findViewById(R.id.switchDesporto);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);

        setTitle("Definiçoes");

        switchAlimentacao.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton View, boolean isChecked) {

                if(!isChecked){
                    Snackbar.make(View, "Cancelou a subscrição de dicas sobre Receitas", Snackbar.LENGTH_LONG).setAction("Action", null).show();
                }
                else
                {
                    topico = "Receitas";
                    try {
                        mqttAndroidClient.subscribe(topico, 1);
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                    Snackbar.make(View, "Sobscreveu dicas sobre Receitas", Snackbar.LENGTH_LONG).setAction("Action", null).show();
                }
            }
        });

        switchDesporto.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton View, boolean isChecked) {

                if(!isChecked){
                    Snackbar.make(View, "Cancelou a subscrição de dicas sobre Desporto", Snackbar.LENGTH_LONG).show();
                }
                else
                {
                    topico = "Desporto";
                    try {
                        mqttAndroidClient.subscribe(topico, 1);
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                    Snackbar.make(View, "Sobscreveu dicas sobre Desporto", Snackbar.LENGTH_LONG).show();
                }
            }
        });

        switchSaude.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton View, boolean isChecked) {

                if(!isChecked){
                    Snackbar.make(View, "Cancelou a subscrição de dicas sobre Saúde", Snackbar.LENGTH_LONG).show();
                }
                else
                {
                    topico = "Saúde";
                    try {
                        mqttAndroidClient.subscribe(topico, 1);
                    } catch (MqttException e) {
                        e.printStackTrace();
                    }
                    Snackbar.make(View, "Sobscreveu dicas sobre Saúde", Snackbar.LENGTH_LONG).show();
                }
            }
        });
    }


    @Override
    protected void onPause() {
        super.onPause();

        bundle.putBoolean("switchAlimentacaoState", switchAlimentacao.isChecked());
        bundle.putBoolean("switchDesportoState", switchDesporto.isChecked());
        bundle.putBoolean("switchSaudeState", switchSaude.isChecked());

    }

    @Override
    protected void onResume() {
        super.onResume();

        final MqttAndroidClient mqttAndroidClient = new MqttAndroidClient(this.getApplicationContext(), "tcp://5.196.27.244:1883", "users");

        if(bundle.getBoolean("switchAlimentacaoState")){
            switchAlimentacao.setChecked(bundle.getBoolean("switchAlimentacaoState"));
            topico = "Receitas";
            try {
                mqttAndroidClient.subscribe(topico, 1);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        if(bundle.getBoolean("switchDesportoState")){
            switchDesporto.setChecked(bundle.getBoolean("switchDesportoState"));
            topico = "Desporto";
            try {
                mqttAndroidClient.subscribe(topico, 1);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        if(bundle.getBoolean("switchSaudeState")){
            switchDesporto.setChecked(bundle.getBoolean("switchSaudeState"));
            topico = "Saúde";
            try {
                mqttAndroidClient.subscribe(topico, 1);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }
}

我的错误:

十二月12日至27日:06:30.264 20361-20361 / com.support.android.iplfit E / AndroidRuntime:致命异常:主要过程:com.support.android.iplfit,PID:20361了java.lang.RuntimeException:无法恢复活动{com.support.android.iplfit / com.support.android.iplfit.Activities.DefinicoesActivity}:显示java.lang.NullPointerException:尝试调用虚拟方法“无效org.eclipse.paho.android.service.MqttService.subscribe(java的.lang.String,java.lang.String中,INT,java.lang.String中,java.lang.String中)”上在android.app在android.app.ActivityThread.performResumeActivity(ActivityThread.java:3400空对象引用) .ActivityThread.handleResumeActivity(ActivityThread.java:3440)在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2713)在android.app.ActivityThread.-wrap12(ActivityThread.java)在android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1460)在android.os.Handler.dispatchMessage(Handler.java:102)在android.os.Looper.loop(Looper.java:154)在android.app.Activ ityThread.main(ActivityThread.java:6077)在java.lang.reflect.Method.invoke(本机方法)在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:866)在com.android。 internal.os.ZygoteInit.main(ZygoteInit.java:756)产生的原因:显示java.lang.NullPointerException:尝试调用虚拟方法“无效org.eclipse.paho.android.service.MqttService.subscribe(java.lang.String中, java.lang.String中,INT,java.lang.String中,java.lang.String中)”上在组织在org.eclipse.paho.android.service.MqttAndroidClient.subscribe(MqttAndroidClient.java:906空对象引用)。 eclipse.paho.android.service.MqttAndroidClient.subscribe(MqttAndroidClient.java:841)在com.support.android.iplfit.Activities.DefinicoesActivity $ 3.onCheckedChanged(DefinicoesActivity.java:122)在android.widget.CompoundButton.setChecked(CompoundButton的.java:156)在android.widget.Switch.setChecked(Switch.java:1074)在com.support.android.iplfit.Activities.DefinicoesActivity.onResume(DefinicoesActivity.java:213)在安德烈 oid.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)在android.app.Activity.performResume(Activity.java:6766)在android.app.ActivityThread.performResumeActivity(ActivityThread.java:3377)在android.app.ActivityThread .handleResumeActivity(ActivityThread.java:3440)在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2713)维持在android.app.ActivityThread $ H.handleMessage android.app.ActivityThread.-wrap12(ActivityThread.java)(ActivityThread的.java:1460)在android.os.Handler.dispatchMessage(Handler.java:102)在android.os.Looper.loop(Looper.java:154)在android.app.ActivityThread.main(ActivityThread.java:6077)在java.lang.reflect.Method.invoke(本机方法)在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:866)在com.android.internal.os.ZygoteInit.main(ZygoteInit。 Java的:756)

文章来源: Keep MQTT Topics Subscribed onResume Activity