Exception: ViewLoop is not the current active page

Hi,

I just implemented a ViewLoop, and on my watch (not the simulator) I get this exception when switching views. It seems to happen after the view is switched, because the visually the view still changes.

Exception: ViewLoop is not the current active page
Stack: 
  - pc: 0x100026b9
    File: 'D:\Projects\EVCC Garmin\evcc\source\EvccViewLoopDelegate.mc'
    Line: 21
    Function: onNextView
  - pc: 0x30003640

My code looks like this, line 21 where the exception occurs is the changeView call.

function onNextView() {
    try {
        _viewLoop.changeView( WatchUi.ViewLoop.DIRECTION_NEXT ); // this is line 21
        return true;
    } catch ( ex ) {
        EvccHelper.debugException( ex );
        return false;
    }
}

Has anyone seen this before?

  • Some new findings: first, I was wrong, when this exception occurs, the view does not switch. Second, I can reproduce it by leaving my widget open until after three minutes or so, the watch automatically goes back to the watch face. When I then go back to the widget, I cannot change the views anymore, and get these exceptions instead.

  • If you launch your app from the widget or glance loop on a watch, it is standard that it will time out after 1-2 minutes (depending on device) without user interaction and close.

    This is something you don't see in the sim, where it never times out.

  • Yes, if I start my app via the list of apps, it does not time out like that and the issue does not occur. But even with the timeout, it seems from my logs that the app shuts down normally, just when I start it up this issue occurs.

    Could this be a bug in the SDK/Connect IQ API?

    I have used the Primates sample app from the SDK as basis of my implementation, and cannot find anything that is wrong with it. Unfortunately the Primates app does not have a glance, so no timeout and no way to see if the same issue occurs with it.

  • You can add a very simple glance view to the primates sample. Also, note that on pre CIQ 4 devices, widgets and device apps are different, but on devices with CIQ 4 or greater, there are super apps.

    Add the glance view to the primate sample and see if you can reproduce this.

  • I added the glance view to Primates but was not able to reproduce the issue. Even if I let Primates run into the timeout, after I then start it again, it works fine.

    While playing with this, I noted that generally the timeout behaves a bit erratic. Sometimes it goes from the widget to the watch face, but sometimes also from the widget to the glance. I saw this both with my own app and the modified Primates app.

    And now my app does not timeout anymore at all. I can open it from the glance and leave it open indefinitvely, it never quits. Longest I tried was ten minutes. Before it returned after ~ three minutes. The watch is lying next to me on my desk and I am not touching it at all, there is no user input for sure. I tried to reboot the watch, but still no timeout.

    Any idea what could cause the timeout to not work anymore?

  • I played around a bit further. Generally it seems right now on my watch the timeout does not work anymore for CIQ apps. Tried it with my app, with Weather Underground and with MyHomeControl. I had each of them running for at least 10 minutes and none of them timed out. Garmin stress widget still times out "normally" after about 3 minutes.

    Till yesterday also my app timed out after 2-3 minutes reliably. Not sure what has changed. It is especially weird since I researched earlier about having a widget that does not time out, and it seems the consensus is that it is not possible.

  • There have been cases over the last 9 years where a CIQ app can impact others.  It's a bit nasty for the other apps as the developers get contacted for something that another app does.

    Sounds to me that it could be your app was updated, breaking the timeout for others.  Try uninstalling your app and power cycling your Garmin.  Do timeouts with CIQ apps started from a glance  work correctly again?

    With the WU widget. over a number of years and run on a number of devices, I've never seen the glance/widget not time out correctly.

  • OK, I am back on track. Went on a longer walk, and that "Walk" activity seems to have set things right, the CIQ apps now timeout normally again.

    So now I am back to the ViewLoop issue again. I added some additional debugging code that checks WatchUi.getCurrentView() against the ViewLoop. Normally the current view is the view loop, but after I let the app run into the timout and then open it again, WatchUi.getCurrentView() returns null, which is probably the reason why then ViewLoop.changeView() complains that it is not the "active page".

    So now my big question is how can the current view be null?

    The normal cycle after getInitialView seems to be that my ViewLoopFactory.getView is called, then of the view it returns the onLayout, onShow and onUpdate. In all of these calls WatchUi.getCurrentView returns null also under normal circumstances. Then onUpdate is called again and in that call WatchUi.getCurrentView returns the ViewLoop for the first time. After that, onUpdate is called only when I request it. And when my ViewLoopDelegate.onNextView is called, WatchUi.getCurrentView continues to return the ViewLoop.

    Now, under my error condition, after the timeout, for some reason my views onUpdate function is called again and again in short succession, and WatchUi.getCurrentView remains null. When I press a button and ViewLoopDelegate.onNextView is called, it is still null, leading to the exception.

    So somehow I now think there is something wrong with my onUpdate function. I do have a try/catch block in there, but as I understand there are many errors that will not be caught by that, and that could trip up whatever code from Garmin calls the onUpdate function.

    So next, I'll add some debug code to my onUpdate function to see if it somehow behaves differently after the timeout.

  • onUpdate does not seem to be the issue. I verified that also under the error condition after the timeout, my onUpdate behaves normally and is fully executed to the end without any exception.

    So I now believe this to be a bug on Garmin's side. After the timeout, something is tripping up Garmin's code that calls onUpdate and sets the current view. Instead of setting the current view, it calls onUpdate again and again and again ...

  • One thing to consider is why this only seems to happen with your app.  When you say that onUpdate gets called again and again, are you calling WatchUi.requestUpdate() in your app?  With widgets/device apps, onUpdate isn't called automatically, as is the case with watch faces and data fields.

    How/where are you calling requestUpdate?