4
votes

I am trying to publish a message to my MQTT broker(which is my Raspberry Pi) for the topic rpi/gpio. The aim of sending that message is to turn on/off an LED connected to my Raspberry Pi(like in this tutorial but that tutorial is for Swift not Android). So when I turn on the switch widget on my Android app, the message "on" will be published to the Raspberry Pi broker to turn it on(via a python script also connected to MQTT on the Raspberry Pi). Without all the MQTT codes, the fragment below works well by displaying the switch. However, with the following codes, it crashes.

public class ControlsFragment extends Fragment {

    private ControlsFragment.OnFragmentInteractionListener listener;

    public static ControlsFragment newInstance() {
        return new ControlsFragment();
    }

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

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view=inflater.inflate(R.layout.fragment_controls, container, false);

        Switch switch1= (Switch)view.findViewById(R.id.tempSwitch);
        switch1.setChecked(true);
        switch1.setTextOn("On");
        switch1.setTextOff("Off");

        String clientId = MqttClient.generateClientId();
        MqttAndroidClient client =
                new MqttAndroidClient(this.getActivity(), "tcp://192.168.100.8:1883",
                        clientId);

        try {
            IMqttToken token = client.connect();
            token.setActionCallback(new IMqttActionListener() {
                @Override
                public void onSuccess(IMqttToken asyncActionToken) {
                    // We are connected
                    Log.d(TAG, "onSuccess");
                }

                @Override
                public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
                    // Something went wrong e.g. connection timeout or firewall problems
                    Log.d(TAG, "onFailure");

                }
            });
        } catch (MqttException e) {
            e.printStackTrace();
        }

        String topic = "rpi/gpio";
        String payload;


        if(switch1.isChecked()){
            payload="on";
        }

        else{
            payload="off";
        }
        byte[] encodedPayload = new byte[0];
        try {
            encodedPayload = payload.getBytes("UTF-8");
            MqttMessage message = new MqttMessage(encodedPayload);
            client.publish(topic, message);
        } catch (UnsupportedEncodingException | MqttException e) {
            e.printStackTrace();
        }


        return view;
    }

    @Override
    public void onAttach(android.content.Context context) {
        super.onAttach(context);
        if (context instanceof ControlsFragment.OnFragmentInteractionListener) {
            listener = (ControlsFragment.OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        listener = null;
    }

    public interface OnFragmentInteractionListener {
    }


}

Logcat error:

03-07 00:40:37.537 32415-32415/com.example.teerna.smartagriculturev5 E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                       java.lang.NullPointerException
                                                                                           at org.eclipse.paho.android.service.MqttAndroidClient.publish(MqttAndroidClient.java:815)
                                                                                           at org.eclipse.paho.android.service.MqttAndroidClient.publish(MqttAndroidClient.java:673)
                                                                                           at com.example.teerna.smartagriculturev5.ControlsFragment.onCreateView(ControlsFragment.java:90)
                                                                                           at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
                                                                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419)
                                                                                           at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
                                                                                           at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
                                                                                           at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
                                                                                           at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
                                                                                           at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
                                                                                           at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
                                                                                           at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
                                                                                           at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:700)
                                                                                           at android.os.Handler.handleCallback(Handler.java:725)
                                                                                           at android.os.Handler.dispatchMessage(Handler.java:92)
                                                                                           at android.os.Looper.loop(Looper.java:137)
                                                                                           at android.app.ActivityThread.main(ActivityThread.java:5283)
                                                                                           at java.lang.reflect.Method.invokeNative(Native Method)
                                                                                           at java.lang.reflect.Method.invoke(Method.java:511)
                                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
                                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
                                                                                           at dalvik.system.NativeStart.main(Native Method)

com.example.teerna.smartagriculturev5.ControlsFragment.onCreateView(ControlsFragment.java:90) points to the following line:

client.publish(topic, message);

which is found in the try block.

Used the following reference:

https://www.hivemq.com/blog/mqtt-client-library-enyclopedia-paho-android-service

http://androidkt.com/android-mqtt/

1

1 Answers

5
votes

If you follow the error in the paho source code, you'll find that the NPE is caused by the mqttService of the client being null. You need to wait for the connection to the service to be established before publishing messages, the right place would be onSuccess of the callback, which you are basically ignoring

token.setActionCallback(new IMqttActionListener() {
    @Override
    public void onSuccess(IMqttToken asyncActionToken) {
        // after this is called you can publish messages
    }

    @Override
    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
        // Something went wrong e.g. connection timeout or firewall problems
        Log.d(TAG, "onFailure");

    }
});