CIQ_LOG Causing crashes?

A couple of days after I launched my stopwatch app (https://apps.garmin.com/en-US/apps/e31d8308-674a-403b-813f-298ce28c9eab) on 4/22, I recieved an email saying that the app crashes on startup on a FR235. I found this odd since I tested it on the simulators, on my watch(FR230), and on a friend's FR630. You would think if the app was going to crash, it would do so on the more different 630, rather than the 235.

I sent this user a modified version of my app that has a crap ton of print statements, to try to figure out what is happening. I also had the user delete the CIQ_LOG.txt, so that only my app's errors would be there. The app crashed again. The user told me there were no print statements in the app's txt file I included to catch print statements. It seems that my app is crashing before is has even started. but once the user had reinstalled the release version the app, it worked.

A couple days later I got another email from another FR235 user. He did not have a CIQ_LOG.txt. I told him to create one, and then my app worked, as it should have. After that I left some information on the top of the description of my app that has helped users solve the crash on start problem.

I have not received another email about that since. Until today, I got another email but this time it was a 630 user.

I have not been able to recreate this issue using the simulator, or my watch. Is it possible that the internal logging is some how causing a crash on certain devices? It's only 2 data points, but it's all I got.
  • If you use Sys.println() calls, they do not go into ciq_log.txt. They go in <nameofyourapp>.txt.

    So if your app is myapp.prg, in logs, you want to pre-create myapp.txt, and that's where the Sys.println() output will go.
  • I know they go into a separate file. I supplied that to the user. That's not the focus here.
  • ciq_log.txt isn't causing crashes, but possible it's something with the way your're doing something with app-settings (for example). If it's crashing the watch (not a "IQ!") , there is a problem with the 4.30 FW on the 23x involving BT. And if it's not a IQ!, it could be you're running out of memory at times (what the simulator currently shows is your "idle" memory, but you could be using more at other times)

    Maybe if you posted your code?
  • I guess i should have been more clear. Its just an app crash (IQ!) not a device crash. Also my user ended up fixing it:

    "Managed to get it working after uninstalling as below:
    [1] Uninstall App
    [2] Create ‘CIQ_LOG.txt’ file
    [3] Install App
    [4] Save ‘Settings’

    Only thing I did differently was save the ‘Settings’ which must have created the ‘C6B028D3.SET’ file.

    Btw. the console log file ‘CIQ_LOG.txt’ is empty after running the App."

    My guess would be the checkForNull(), that is in the class initializer, but its relatively simple, its the last function.

    The Class Layout for your reference:

    - class global variables

    - initialize()
    ---- checkForNull()

    - onLayout()
    ---- load resources
    ---- define timers
    ---- light timer control

    - onShow()

    - onUpdate()
    ---- define time variables
    ---- display lap number via layout
    ---- display clock time via layout
    ---- display current lap and total time via dc
    ---- display icons and text based on stopped or not

    - onHide()

    - checkForNull()

    This is my entrance class, and this is where I would assume the problem would exist, since the app crashes on startup:
    var mainClock;
    var standbyClock;
    var stopW = new StopwatchInfo();

    class StopwatchView extends Ui.View
    {
    var myFunc = new MyFunctions();
    var pause = null;
    var play = null;
    var down = null;
    var up = null;

    function initialize()
    {
    View.initialize();
    checkForNull();
    }

    function onLayout(dc)
    {
    setLayout(Rez.Layouts.StopwatchLayout(dc));
    mainClock = new Timer.Timer();
    standbyClock = new Timer.Timer();

    //this is the way we stop too many timers
    if(stopW.stopW.getStopped() == false)
    {
    mainClock.start(method(:cycle), 100, true);
    }
    else
    {
    standbyClock.start(method(:cycle), 10000, true);
    }

    pause = Ui.loadResource(Rez.Drawables.pauseIcon);
    play = Ui.loadResource(Rez.Drawables.playIcon);
    down = Ui.loadResource(Rez.Drawables.downIcon);
    up = Ui.loadResource(Rez.Drawables.upIcon);
    }

    function onShow()
    {

    }

    function onUpdate(dc)
    {
    //time evaluation
    if(stopW.getStopped() == false)
    {
    stopW.setTotalTime(Sys.getTimer() - stopW.getOffset() + stopW.getTimeLogged());
    }
    else
    {
    stopW.setTotalTime(stopW.getTimeLogged());
    }
    var dSec = stopW.getTotalTime() / 100;
    var sec = dSec / 10;
    var min = sec / 60;
    var hr = min / 60;

    var LDSec = dSec - stopW.getLapTotals() / 100;
    var LSec = LDSec / 10;
    var LMin = LSec / 60;
    var LHr = LMin / 60;

    //current lap
    var lapView = View.findDrawableById("LapLabel");
    lapView.setText("Lap " + stopW.getLapsNo().toString());
    var lapBView = View.findDrawableById("LapLabelB");
    lapBView.setText("Lap " + stopW.getLapsNo().toString());

    //clock time
    var timeView = View.findDrawableById("TimeLabel");
    timeView.setText(myFunc.getSimpleTime());

    View.onUpdate(dc);

    //stopwatch display
    var size = 5;
    var size1 = 2;
    if(hr == 0)
    {
    //curent lap
    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
    dc.drawText(164, 61, Gfx.FONT_NUMBER_HOT, (LDSec % 10).toString(), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(119, 61, Gfx.FONT_NUMBER_HOT, (LSec % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(61, 61, Gfx.FONT_NUMBER_HOT, (LMin % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.setColor(App.getApp().getProperty("Accent Color"), Gfx.COLOR_TRANSPARENT);
    dc.fillRectangle(87, 84, size, size);
    dc.fillRectangle(87, 106, size, size);
    dc.fillRectangle(145, 106, size, size);

    //total
    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
    dc.drawText(135, 116, Gfx.FONT_NUMBER_MILD, (dSec % 10).toString(), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(113, 116, Gfx.FONT_NUMBER_MILD, (sec % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(85, 116, Gfx.FONT_NUMBER_MILD, (min % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.setColor(App.getApp().getProperty("Accent Color"), Gfx.COLOR_TRANSPARENT);
    dc.fillRectangle(98, 128, size1, size1);
    dc.fillRectangle(98, 139, size1, size1);
    dc.fillRectangle(126, 139, size1, size1);
    }
    else
    {
    //current lap
    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
    dc.drawText(194, 61, Gfx.FONT_NUMBER_HOT, (LDSec % 10).toString(), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(148, 61, Gfx.FONT_NUMBER_HOT, (LSec % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(92, 61, Gfx.FONT_NUMBER_HOT, (LMin % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(36, 61, Gfx.FONT_NUMBER_HOT, (LHr).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.setColor(App.getApp().getProperty("Accent Color"), Gfx.COLOR_TRANSPARENT);
    dc.fillRectangle(61, 84, size, size);
    dc.fillRectangle(61, 106, size, size);
    dc.fillRectangle(117, 84, size, size);
    dc.fillRectangle(117, 106, size, size);
    dc.fillRectangle(175, 106, size, size);

    //total
    dc.setColor(Gfx.COLOR_WHITE, Gfx.COLOR_TRANSPARENT);
    dc.drawText(149, 116, Gfx.FONT_NUMBER_MILD, (dSec % 10).toString(), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(127, 116, Gfx.FONT_NUMBER_MILD, (sec % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(99, 116, Gfx.FONT_NUMBER_MILD, (min % 60).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.drawText(71, 116, Gfx.FONT_NUMBER_MILD, (hr).format("%02d"), Gfx.TEXT_JUSTIFY_CENTER);
    dc.setColor(App.getApp().getProperty("Accent Color"), Gfx.COLOR_TRANSPARENT);
    dc.fillRectangle(84, 128, size1, size1);
    dc.fillRectangle(84, 139, size1, size1);
    dc.fillRectangle(112, 128, size1, size1);
    dc.fillRectangle(112, 139, size1, size1);
    dc.fillRectangle(140, 139, size1, size1);
    }

    //stopwatch drawables
    dc.setColor(App.getApp().getProperty("Accent Color"), Gfx.COLOR_TRANSPARENT);
    dc.fillRectangle(22, 155, 171, 28);
    dc.setColor(Gfx.COLOR_BLACK, Gfx.COLOR_TRANSPARENT);

    var xDown = 42;
    var xLabe1 = 61;
    var xLabelB = 62;
    var xUp = 112;
    var xLabel2 = 131;
    var xLabel2B = 132;
    var labelString1 = "Timer";
    if(stopW.getStopped() == true)
    {
    dc.drawBitmap(176, 35, play);
    if(Rez.Strings.touch == 4388)
    {
    xDown = 153;
    xLabe1 = 109;
    xLabelB = 110;
    xUp = 44;
    xLabel2 = 63;
    xLabel2B = 64;
    }
    }
    else
    {
    labelString1 = "Lap";
    xDown = 51;
    xLabe1 = 70;
    xLabelB = 71;
    xUp = 105;
    xLabel2 = 124;
    xLabel2B = 125;

    dc.drawBitmap(176, 35, pause);
    if(Rez.Strings.touch == 4388)
    {
    xDown = 145;
    xLabe1 = 116;
    xLabelB = 117;
    xUp = 52;
    xLabel2 = 70;
    xLabel2B = 71;
    }
    }

    dc.drawBitmap(xDown, 160, down);
    dc.drawText(xLabe1, 154, Gfx.FONT_MEDIUM, labelString1, Gfx.TEXT_JUSTIFY_LEFT);
    dc.drawText(xLabelB, 154, Gfx.FONT_MEDIUM, labelString1, Gfx.TEXT_JUSTIFY_LEFT);

    dc.drawBitmap(xUp, 160, up);
    dc.drawText(xLabel2, 154, Gfx.FONT_MEDIUM, "Laps", Gfx.TEXT_JUSTIFY_LEFT);
    dc.drawText(xLabel2B, 154, Gfx.FONT_MEDIUM, "Laps", Gfx.TEXT_JUSTIFY_LEFT);
    }

    function onHide()
    {

    }

    //checks for no app settings and creates defaults
    function checkForNull()
    {
    if(App.getApp().getProperty("Accent Color") == null)
    {
    App.getApp().setProperty("Accent Color", Gfx.COLOR_WHITE);
    }
    if(App.getApp().getProperty("Tones") == null)
    {
    App.getApp().setProperty("Tones", true);
    }
    if(App.getApp().getProperty("Vibrations") == null)
    {
    App.getApp().setProperty("Vibrations", true);
    }
    if(App.getApp().getProperty("Lap Screen") == null)
    {
    App.getApp().setProperty("Lap Screen", true);
    }
    }
    }
  • In your checkForNull, there is something I notice which may come into play on this one.

    Depending on versions of things like GCM/GE, you could be getting non-null values, but not what you expect. For example, there was a case where GCM/Android would be setting a Float where it should have been a Number.

    So, what you may want to do is include "instanceof Number" or "instanceof Boolean" in your conditionals

    Like:
    if(newval!=null && newval instanceof Number) {


    If you get a float, you can always do a ".toNumber()", as long as it's within the range that will convert.

    There a number of threads from when settings first came out (1.2.1 SDK) that go into how to cover for things you might not expect from GCM/GE.
  • Thanks I'll make that modification. Sadly there is no way to check if it's fixed. Other than to wait for user feedback.