Questions regarding Communications api and transmit

I have a couple of questions regarding the Communications api, using ConnectIQ SDK 2.3.4 and ConnectIQ Mobile Android SDK 1.4.
Since I don't have a hardware device, everything goes in the simulator.

1. Using the Comm example both on the watch and on the phone when sending a message from Phone -> Watch I always get 2 statuses right after each other. The first one is SUCCESS the second one is FAILURE_UNKNOWN in the OnMessageStatus callback. (The simulator is running Vivoactive 3 with target sdk 2.3.x)
Does this happen on a real device too, or is this just a simulator bug?

2. When the OnMessageStatus is called with status=SUCCESS on phone or the onComplete() is called in ConnectionListener on the watch can I be absolutely 100% sure that the message is really delivered on the other side?
Or do I have to send back some kind of ACK message to make it sure?

3. How do you handle retransmissions on error?
On the watch in the onError() function of ConnectionListener if I call the transmit function again, the callbacks (onComplete, onError) are never called again.
Am I doing something wrong here, or is this also a bug in the simulator?
  • Former Member
    Former Member over 7 years ago

    • I have seen the extra FAILURE_UNKNOWN status on a device a few times, so I think you can assume it might behave similar to the simulator.
    • I believe that the OnMessageStatus and onComplete callbacks should only be called with success if the other device has received the original message and then responded with the correct status. A successful response following an incomplete transmission would be a bug, and one I have not seen. If you see otherwise, please make a post in the bug report forum.
    • Would you be willing to post how you are setting up and using the ConnectionListener? I usually construct a new listener each time I send a message.

  • For the retransmits I inserted this mockup code into the CommCheckListener's onError:
    if (retransmit < 3)
    {
    retransmit = retransmit + 1;
    $.DEBUGGER.println(Lang.format("retransmit: $1$", [retransmit]));
    Comm.transmit(Communications.MESSAGE_TYPE_GET_LANGUAGE, null, new CommCheckListener());
    return;
    }


    Even if I change the new CommCheckListener() to another one, still nothing is called after this transmit call.
  • I run into the same problem wrt item 1 : The first one is SUCCESS the second one is FAILURE_UNKNOWN

    Strange that not many people have the same problem. The reversed code extracted from connectiq.jar has a file named  ConnectIQAdbStrategy.java  and the procedure that causes the 2nd callback:

    @Override
        protected void sendMessageProtocol(final IQDevice device, final IQApp application, final byte[] data, final IQSendMessageListener listener) {
            if (AdbConnection.getInstance().sendMessage(data) && listener != null) {
                listener.onMessageStatus(device, application, IQMessageStatus.SUCCESS);
            }
            if (listener != null) {
                listener.onMessageStatus(device, application, IQMessageStatus.FAILURE_UNKNOWN);
            }
        }
      
    I don't know if the reversing is causing this but the 2nd if statement looks like the cause.

  • Next to that I get an    android.os.NetworkOnMainThreadException   on  
    DeviceActivity.java:201  ( the call to mConnectIQ.sendMessage ) of the Comm example:


    2021-01-07 15:06:55.501 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err: android.os.NetworkOnMainThreadException
    2021-01-07 15:06:55.506 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at java.net.SocketOutputStream.write(SocketOutputStream.java:145)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at com.garmin.android.connectiq.adb.AdbConnection.sendMessage(AdbConnection.java:196)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at com.garmin.android.connectiq.ConnectIQAdbStrategy.sendMessageProtocol(ConnectIQAdbStrategy.java:127)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at com.garmin.android.connectiq.ConnectIQ.sendMessage(ConnectIQ.java:941)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at com.garmin.android.connectiq.ConnectIQ.sendMessage(ConnectIQ.java:921)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at com.garmin.android.apps.connectiq.sample.comm.DeviceActivity.onListItemClick(DeviceActivity.java:201)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at android.app.ListActivity$2.onItemClick(ListActivity.java:319)
    2021-01-07 15:06:55.507 15403-15403/com.garmin.android.apps.connectiq.sample.comm W/System.err:     at android.widget.AdapterView.performItemClick(AdapterView.java:339)
    

    Android says: The exception that is thrown when an application attempts to perform a networking operation on its main thread.

    Maybe that is due to changed Android design rules. The old (commented out) and modified code:

        @Override
        public void onListItemClick(ListView l, View v, int position, long id) {
            final Object message = MessageFactory.getMessage(this, position);
    
    //        try {
    //            mConnectIQ.sendMessage(mDevice, mMyApp, message, new IQSendMessageListener() {
    //                @Override
    //                public void onMessageStatus(IQDevice device, IQApp app, IQMessageStatus status) {
    //                    Toast.makeText(DeviceActivity.this, status.name(), Toast.LENGTH_SHORT).show();
    //                }
    //            });
    //        } catch (InvalidStateException e) {
    //            Toast.makeText(this, "ConnectIQ is not in a valid state", Toast.LENGTH_SHORT).show();
    //        } catch (ServiceUnavailableException e) {
    //            Toast.makeText(this, "ConnectIQ service is unavailable.   Is Garmin Connect Mobile installed and running?", Toast.LENGTH_LONG).show();
    //        } catch (Exception e){
    //            e.printStackTrace();
    //        }
    
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.prepare();
                    try {
                        mConnectIQ.sendMessage(mDevice, mMyApp, message, new IQSendMessageListener() {
                            @Override
                            public void onMessageStatus(IQDevice device, IQApp app, IQMessageStatus status) {
                                Toast.makeText(getBaseContext(), status.toString(), Toast.LENGTH_SHORT).show();
                            }
                        });
                    } catch (InvalidStateException e) {
                        Toast.makeText(getBaseContext(), "ConnectIQ is not in a valid state", Toast.LENGTH_SHORT).show();
                    } catch (ServiceUnavailableException e) {
                        Toast.makeText(getBaseContext(), "ConnectIQ service is unavailable.   Is Garmin Connect Mobile installed and running?", Toast.LENGTH_LONG).show();
                    } catch (Exception e){
                        e.printStackTrace();
                    }
                    Looper.loop();
                }
            });
            thread.start();
        }
    
    

    In addition you also need to change build.gradle and add gradle.properties to get it compiled.

    It would be nice when you try an example (Comm)  that you don't have to start solving bugs or compiler issues but thats probably... life.