FAILURE_DURING_TRANSFER issue again (now using Comm sample )

Environment:
- Ubuntu 16.04
- Vivoactive V4.40, CIQ1.4.2
- Android 6.0.1
- Android Studio 2.3.2
- CIQ SDK 2.2.5
- CIQ Android Mobile SDK v1.4

A detailed description of the issue:

Using modified Comm samples from CIQ SDK 2.2.5 and CIQ Android Mobile SDK v1.4, I can get to the point where any attempt at communication phone => watch results in FAILURE_DURING_TRANSFER, while in the other direction messages go through normally.

Steps to reproduce the issue:

1. Install both apps from the following repository: https://github.com/Artaud/CIQ-Comm-failure-sample and run them.
2. On Android, tap on your connected device to select it. The app will now start receiving messages from watch.
3. Try to send any message to the watch and check the Android log. You'll get FAILURE_DURING_TRANSFER very early.
4. Turn off the app on watch and try to send any message from the phone now. Normally, you should get SUCCESS even if the app is not running, but now you get FAILURE_DURING_TRANSFER forever.


Additional information:

The bug makes any serious two-way communication impossible.

Code sample to reproduce the issue:

https://github.com/Artaud/CIQ-Comm-failure-sample
  • Thanks for the update Coleman, I have the latest GCM update and will do some testing to see if my issue remains. I will also keep an eye out for status updates on the FAILURE_DURING_TRANSFER issue.
  • @Coleman.ConnectIQ Any update from your team on a fix? I've got an app ready to go out but i'm holding off until I know people won't be experiencing this issue.
  • The problem seems rather trivial. Hard to understand why it's so hard to fix.

    Below is a workaround. It intercepts the messages going to the connectiq library and replaces the IQDevice by it's identifier (long). For that, it creates a WrappedContext that is passed to connectiq for registering receivers. Instead of registering the receiver it registers a ConnectIQWrappedReceiver that fixes the intent and then forwards the message to the connecteq receiver.

    Call initializeConnectIQ(...) instead of connectiq.initialize(...).

    private static class ConnectIQWrappedReceiver extends BroadcastReceiver {
    private final BroadcastReceiver receiver;

    ConnectIQWrappedReceiver(BroadcastReceiver receiver) {
    this.receiver = receiver;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
    if ("com.garmin.android.connectiq.SEND_MESSAGE_STATUS".equals(intent.getAction())) {
    replaceIQDeviceById(intent, "com.garmin.android.connectiq.EXTRA_REMOTE_DEVICE");
    } else if ("com.garmin.android.connectiq.OPEN_APPLICATION".equals(intent.getAction())) {
    replaceIQDeviceById(intent, "com.garmin.android.connectiq.EXTRA_OPEN_APPLICATION_DEVICE");
    }
    receiver.onReceive(context, intent);
    }
    }

    private static void replaceIQDeviceById(Intent intent, String extraName) {
    try {
    IQDevice device = intent.getParcelableExtra(extraName);
    if (device != null) {
    intent.putExtra(extraName, device.getDeviceIdentifier());
    }
    } catch (ClassCastException e) {
    // It's already a long, i.e. on the simulator.
    }
    }

    private static void initializeConnectIQ(
    Context context, ConnectIQ connectIQ, boolean autoUI, ConnectIQ.ConnectIQListener listener) {
    if (connectIQ instanceof ConnectIQAdbStrategy) {
    connectIQ.initialize(context, autoUI, listener);
    return;
    }
    Context wrappedContext = new ContextWrapper(context) {
    private HashMap<BroadcastReceiver, BroadcastReceiver> receiverToWrapper = new HashMap<>();

    @Override
    public Intent registerReceiver(final BroadcastReceiver receiver, IntentFilter filter) {
    BroadcastReceiver wrappedRecv = new ConnectIQWrappedReceiver(receiver);
    synchronized (receiverToWrapper) {
    receiverToWrapper.put(receiver, wrappedRecv);
    }
    return super.registerReceiver(wrappedRecv, filter);
    }

    @Override
    public void unregisterReceiver(BroadcastReceiver receiver) {
    // We need to unregister the wrapped receiver.
    BroadcastReceiver wrappedReceiver = null;
    synchronized (receiverToWrapper) {
    wrappedReceiver = receiverToWrapper.get(receiver);
    receiverToWrapper.remove(receiver);
    }
    if (wrappedReceiver != null) super.unregisterReceiver(wrappedReceiver);
    }
    };
    connectIQ.initialize(wrappedContext, autoUI, listener);
    }
  • This workaround - as far as I can tell - is only for the error: "com.garmin.android.connectiq.IQDevice cannot be cast to java.lang.Long" but does not solve the FAILURE_DURING_TRANSFER issue, which I'm running into now too, so can I ask for an update on the task Coleman.ConnectIQ ?

    Thank you.
  • Has anyone manged to sort this issue out?
  • Has anyone manged to sort this issue out?


    Forget Garmin... They're useless... could not even fix a 1 year old bug...
  • Forget Garmin... They're useless... could not even fix a 1 year old bug...


    Under some pressure to get an app finished and this bug is driving me mad! I am guessing no one found a work around? It makes consistent communication between mobile and watch almost impossible.
  • I haven't found a programmatic workaround yet, but closing the Garmin Connect app seems to reset the connection.

    Tested with the default Comm app on a Fenix 5x.
    • Send a rapid amount of messages until you always get the FAILURE_DURING_TRANSFER message.
    • Close the Garmin Connect app on the phone
    • Reopen the Garmin Connect app ( I don't have to do this step with my own app, but the Comm app doesn't seem to refresh on its own)
    • Try to send messages from the Comm app again. Should start seeing successes almost immediately.

    It appears to be on the mobile side, not the watch. Yet another reason to open up our communication options.
  • Thanks Jonesy. I can confirm that the workaround works for me as well. Unfortunately for us it's not plausible even as a workaround since we do sleep tracking and when this happens, the user is asleep :)