Ticket Created
over 4 years ago

ACROPOLIS-2252

background process doesn't start on device

device: fenix 6, ciq 3.2.4, fw 15.71

the code (no code format - forum error as usually) below not start background (either with Duration or TMoment  in registerForTemporalEvent)

///app

using Toybox.Application    as APP;
using Toybox.WatchUi        as UII;
using Toybox.Background        as BAG;
using Toybox.System         as SYS;
using Toybox.Time             as TIM;


(:background)
class batteryusageSD extends SYS.ServiceDelegate
{
    function initialize()
    {
        ServiceDelegate.initialize();
    }

    function onTemporalEvent()
    {
        if(APP.getApp().getProperty("BAGkill"))
        {
            SYS.println("onTemporalEvent kill BAG");//not call on sim
            
            BAG.exit(null);
        }else
        {
            SYS.println("onTemporalEvent keep BAG");
            BAG.exit(true);
        }         
    }
}


(:background)
class batteryusageApp extends APP.AppBase
{
    var mV;
    
    function initialize()
    {
        AppBase.initialize();
    }

    // onStart() is called on application start up
    function onStart(state)
    {
    }

    // onStop() is called when your application is exiting
    function onStop(state)
    {
    }

    // Return the initial view of your application here
    function getInitialView()
    {
        mV = new batteryusageView();
        return [ mV, new batteryusageDelegate() ];
    }
    
    function getServiceDelegate()
    {
        return [new batteryusageSD()];
    }
    
    function startBAG()
    {
        setProperty("BAGkill", false);
        //BAG.registerForTemporalEvent(new TIM.Duration(300));
        var let = BAG.getLastTemporalEventTime();
        if(let)
        {
            let = let.add(new TIM.Duration(300));
        } else
        {
            let = TIM.now().add(new TIM.Duration(15));
        }
        BAG.registerForTemporalEvent(let);
    }
    
    function stopBAG()
    {
        setProperty("BAGkill", true);
        BAG.deleteTemporalEvent();
    }
    
    function onBackgroundData(d)
    {
        SYS.println("onBackgroundData");
        if(mV)
        {
            setProperty("IsMV", true);
               mV.onMeasureTMR("a.onBackgroundData");
           }else
           {
               setProperty("IsMV", false);
               UII.requestUpdate();
           }
    }
}

//delgate

using Toybox.WatchUi         as UII;
using Toybox.Application    as APP;

class batteryusageDelegate extends UII.BehaviorDelegate {

    function initialize()
    {
        BehaviorDelegate.initialize();
    }

    function onMenu()
    {
        UII.pushView(new Rez.Menus.MainMenu(), new batteryusageMenuDelegate(), WatchUi.SLIDE_UP);
        return true;
    }
    
    
    function onSelect()
    {
        return APP.getApp().mV.onSelect();
    }
    
    function onBack()
    {
        return APP.getApp().mV.onBack();
    }
    
    
    function onNextPage()
    {
        UII.requestUpdate();
    }
    
    function onPreviousPage()
    {
        UII.requestUpdate();
    }
}

//view

using Toybox.WatchUi            as UII;
using Toybox.Timer                 as TMR;
using Toybox.Time.Gregorian     as GRE;
using Toybox.Time                 as TIM;
using Toybox.Graphics             as GRA;
using Toybox.Math                 as MAT;
using Toybox.System             as SYS;
using Toybox.Background            as BAG;
using Toybox.Application        as APP;

class batteryusageView extends UII.View
{
    var mDrawNumTMR, mDrawNumTOT = 0 ,
    //mTMR,
    mIsMeasuring = false, mMeasureStartTIM, mMeasureStartBAT;
    
    function initialize()
    {
        View.initialize();
        //mTMR = new TMR.Timer();
        APP.getApp().setProperty("IsMV", null);
    }
    
    function onLayout(dc)
    {
        //prv(me, "onLayout");
//        setLayout(Rez.Layouts.MainLayout(dc));
        return true;
    }

    function getCurrentData()
    {
        return [MAT.floor(SYS.getSystemStats().battery), new TIM.Moment(TIM.now().value())];
    }
    
    function onBack()
    {
        tmrStop();
        return false;//exit app
    }
    
    function onMeasureTMR(from)
    {
        SYS.println("onMeasureTMR, from: " + from);
        mDrawNumTMR++;
        requestUpdate();
    }
    
    function tmrStart()
    {
        mIsMeasuring = true;
        
        var c= getCurrentData();
        mMeasureStartBAT = c[0];
        mMeasureStartTIM = c[1];
        
        mDrawNumTMR = 0;
        
        APP.getApp().startBAG();
//            mTMR.start(
//                method(:onMeasureTMR),
//                1000*60,
//                true);
        onMeasureTMR("v.onSelect tmr.start");
    }
    
    function tmrStop()
    {
        mIsMeasuring = false;
        //mTMR.stop();
        APP.getApp().stopBAG();
        onMeasureTMR("v.onSelect tmr.stop");
    }

    function onSelect()
    {
        if(mIsMeasuring)
        {
            tmrStop();
        }else
        {
            tmrStart();
        }
        return true;
    }
    
    function onUpdate(dc)
    {
        dc.setColor(GRA.COLOR_TRANSPARENT, GRA.COLOR_BLACK);
        dc.clear();
    
        var f = GRA.FONT_SYSTEM_TINY;
        var t;
        
        var c= getCurrentData();
        
        if(mMeasureStartTIM)
        {
            dc.setColor(GRA.COLOR_BLUE, GRA.COLOR_TRANSPARENT);
        
            dc.drawText(130,90, f, "mDrawNumTMR=" + mDrawNumTMR, GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
            
            var m = (c[1].value() - mMeasureStartTIM.value())/60;
            var T = (m / 60).format("%02d") + ":" + (m % 60).format("%02d");
            t = GRE.info(mMeasureStartTIM, TIM.FORMAT_SHORT);
            t = t.year + "-" + t.month.format("%02d") + "-" + t.day.format("%02d") + " " +
                t.hour.format("%02d") + ":" + t.min.format("%02d") + ":" + t.sec.format("%02d") + " " + T;
            dc.drawText(130, 110, f, t, GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
            
            t = c[0] - mMeasureStartBAT;
            
            m = m ? ((c[0] - mMeasureStartBAT)/m.toFloat()).format("%.2f") : 0;
            
            dc.drawText(130, 130, f, "BatSta=" + mMeasureStartBAT.format("%.0f") + "% " + m + "%/min", GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
        }
        
        dc.setColor(GRA.COLOR_GREEN, GRA.COLOR_TRANSPARENT);
        dc.drawText(130,20, f, "IsMV=" + APP.getApp().getProperty("IsMV"), GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
        
        
        mDrawNumTOT++;
        dc.setColor(GRA.COLOR_YELLOW, GRA.COLOR_TRANSPARENT);
        
        dc.drawText(130,190, f, "mDrawNumTOT=" + mDrawNumTOT, GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
        
        t = GRE.info(c[1], TIM.FORMAT_SHORT);
        t = t.year + "-" + t.month.format("%02d") + "-" + t.day.format("%02d") + " " +
            t.hour.format("%02d") + ":" + t.min.format("%02d") + ":" + t.sec.format("%02d");
        dc.drawText(130, 210, f, t, GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
        
        dc.drawText(130, 230, f, "BatCur=" + c[0].format("%.0f") + "%", GRA.TEXT_JUSTIFY_VCENTER + GRA.TEXT_JUSTIFY_CENTER);
        return true;
    }

}

Parents
  • yes, it's app, on simulator it's ok, console:

    onMeasureTMR, from: v.onSelect tmr.start
    Background: onTemporalEvent keep BAG
    onBackgroundData
    onMeasureTMR, from: a.onBackgroundData
    onMeasureTMR, from: v.onSelect tmr.stop

    but on watch "background timer" not run even when app is in foreground

    I'm pretty sure the background will only run when the main apps isn't running.

    What does men? According documentation:

    onBackgroundData(data)

    Handle data passed from a ServiceDelegate to the application.

    When the Background process terminates, a data payload may be available. If the main application is active when this occurs, the data will be passed directly to the application's onBackgroundData() method. If the main application is not active, the data will be saved until the next time the application is launched and will be passed to the application after the onStart() method completes.

    It should mean that BAG run regardless on main is active (foreground) not active - and it run this way for wf but for app it not run at all!

Comment
  • yes, it's app, on simulator it's ok, console:

    onMeasureTMR, from: v.onSelect tmr.start
    Background: onTemporalEvent keep BAG
    onBackgroundData
    onMeasureTMR, from: a.onBackgroundData
    onMeasureTMR, from: v.onSelect tmr.stop

    but on watch "background timer" not run even when app is in foreground

    I'm pretty sure the background will only run when the main apps isn't running.

    What does men? According documentation:

    onBackgroundData(data)

    Handle data passed from a ServiceDelegate to the application.

    When the Background process terminates, a data payload may be available. If the main application is active when this occurs, the data will be passed directly to the application's onBackgroundData() method. If the main application is not active, the data will be saved until the next time the application is launched and will be passed to the application after the onStart() method completes.

    It should mean that BAG run regardless on main is active (foreground) not active - and it run this way for wf but for app it not run at all!

Children
  • in my wf I run BAG calling APP function from view like in the example above

  • simulator, emulator it's only words, this app should simulate/emulate device as much as possible but of course it can't in100%

    reading documentation and after writing wf I could expected the same behaviour:

    wf
    - app/view starts BAG by calling registerForTemporalEvent
    - go to activity = exit app but BAG still exist and is collected data
    - back to wf, if data were read it are put into onBackgroundData and I save it using setProperty
    - wf.view.onShow -> read data using getPropery saving it members/globals
    - wf.view.onUpdate -> draw data form members/globals

    app (not widget but when I run widget and enter from glance view it' like like app)
    - start
    - view/app starts BAG - in my example BAG doesn't call onBackgroundData so for it doesn't start and should
    - exit app
    - background should run in ... background If I don't use BAG.exit() from BAG - I don't need this future (yet Slight smile)  especially that it drains battery and still can't open app without question

    maybe I'm wrong,

    but now, simple, I can't start background process at all and there is no info that BAG is only for df and wf (because acording to https://developer.garmin.com/connect-iq/connect-iq-faq/how-do-i-create-a-connect-iq-background-service/ watch face or data field that can’t do communications itself) and maybe I don't have to use background

    but in sdk example BackgroundTimer BAG is started in APP.onStop maybe this example run right in foreground timer after APP.exit() BAG

  • It's a simulator, not an emulator - to quote someone I know,

    How your app works is really defined by how it works on a real device.  An obvious example in in the sim, widgets never time out, while the do on watches.