Open Source • Background Tasks: Itoo 🚀

Hi, Is there a way use this extension to make an event block like CloudDB1.DataChanged kept alive in the background and even get the parameter values and use/send them in some other block(ex. TaifunNotification1.Send block)?

My goal is to make an app that retrieves the data that has been changed in a specific CloudDB and then checks if the tag is equal to the current logged in user's account ID(which starts with u- and the rest is encrypted in AES256), and if it returns true, then send a notification to the user that lasts until the user interacts(click or deletes) it.

Hello @cnitll311, please check this similar tutorial by @TIMAI2 where he demonstrates the use of CloudDB

Here is what I came up with for the UI to determine whether or not the audio Player running in the itoo background service is playing:

Procedure AudioPlayerIsPlaying (returning true or false) is called from the UI which:

  1. Sets itoo property PlayingStatus to "Unknown"
  2. Calls SetAudioPlayerStatus to run in background [ [which calls Player.IsPlaying and sets PlayingStatus accordingly ("Playing" or "NotPlaying)].
  3. Waits (loops) until property PlayingStatus has changed from "Unknown".
  4. Returns true/false based on new value being "Playing" or "NotPlaying"

Here is AudioPlayerIsPlaying called withing the UI:

...and here is the procedure that runs in the BG:

I have a couple of questions/clarifications:

  1. Will this work as I intend it to, returning to the UI caller the current state of the BG player? I am counting on the BG process/service/thread being able to execute SetAudioPlayerStatus while the UI is executing the wait loop. (UI - BG concurrency)

  2. I think I have already been told "no", but I ask anyway: is here not some call that could be made within the spin-to-wait loop which would allow other processes to execute, hence be more efficient?

  3. Is there a better way to implement this itoo Player.IsPlaying function from the UI?

Kind regards,
Randal

It looks like it should work, you should try it.


There arent many solutions, you may also look into broadcast mechanism, the echo technique. There will be further efforts in the future to solve these specific problems.

1 Like

Ok. I have attempted to implement a ui IsPlaying function within the itooMusic demo app.
ItooMusic_IsPlaying.aia (4.2 MB)

I added a button to call the ui_ function which sets a temp value in the itoo property, PlayerStatus, and then calls a procedure from the background that checks Player1.IsPlaying and stores a result in the itoo property PlayerStatus (set to Playing or NotPlaying).

The ui_ function then waits, repeatedly checking the itoo property - PlayerStatus, until it is updated and then returns the updated value to the ui caller. The result is displayed in a label.

Note that on occasion, when the ui_ procedure fetches the PlayerStatus, it finds nothing there (value TagNotThere).

Any ideas? What have I done / not done?

-Randal

I have found that by changing the wait looping condition from:

to:

... the value "TagNotThere" does not terminate the wait, and the problem does disappear.

But I wonder, is there reason to believe that this is a valid fix or is it just an "apparent" fix that is not valid?

-Randal

It seems you are over complicating a very simple problem.

If I were you, I would start a clock in background that times every 5 secs and queries properties/states of all the important components in background and write it to Itoo storage. You may also update the UI from this clock event. And if the clock does not update the storage values, you can deem that the background is not operational.

But wouldn't the read from the UI of these itoo variables also be subject to the same occasional "valueIfTagNotThere" return as the test case (ItooMusic_IsPlaying)?

Does the test case not show that when the UI reads (Itoo.FetchProperty) from itoo storage, that if the background service is modifying the value, that neither the value being updated from nor the value being updated to is guaranteed be returned - but instead, sometimes, valueIfTagNotThere is returned as if the property/variable had never been written (never existed)?

If this is the case, then wouldn't the same thing happen (UI read sometimes getting valueIfTagNotThere returned) if the storage was being updated by the background clock and read by the UI?

???,
-Randal

PS Please excuse my long sentences. I hope they are punctuated well enough to make sense :frowning:

That's just a whole lot of complication my friend. There are more than enough functionality offered by the extension to solve this problem, but you seem to be wanting the best-in-class-sophisticated solution.

What's the problem in simply writing a log property? Why would there be valueIfTagNotThere? This dosent make sense.

Just do these things and you should be super fine:

  1. Start the background
  2. Start a timer clock for every x seconds
  3. When timer, save a list to Itoo storage, a list comprising of all the properties of all the components.
    list = [list_update_time, element1_timer_playing, element2_timer.... ]
  4. Now query this in the user interface, if last update time greater than y time, that means background stopped.

Ah. I like the idea of storing a single element which is a list which contains a time ....

So, if the tag is present, a list will be returned - the validity of the content can be assessed by looking at the list's time component.

It still seems to me (perhaps you can explain to me otherwise :slight_smile: ) that there is a possibility, demonstrated by the test case, that the UI will FetchProperty and nothing will be there, thus the valueIfTagNotThere value will be returned...

But I can watch for that and ignore it if it happens, continuing to FetchProperty until a list is returned with a time is later than the time of the first UI request (the first FetchProperty of the list). If it is then use the values stored in the list, if not keep fetching. If the time on the list does not advance with the passage of "x" seconds (the timer interval), then the timer has stopped for one reason or the other (no process or timer not enabled).

Does that sound good? or am I still on the wrong track?

A time-tagged list generated by a clock/timer is a great idea!

Thanks,
Randal

1 Like

Yes you can do that
However you should not use a while loop for that...

Aa far as I understand you just could just use an if statement ...

If it is a list
Then do something

What about considering all the suggestions from @Kumaraswamy and providing an updated screenshot?

Taifun

Working on it :slight_smile:

Randal

I implemented a background clock event to store a list which contained the IsPlaying value, the name of the music file, and the time (Clock1.Now).

With a timer interval of 100ms (I know this is very short, but I think would need it to be this short or shorter for this app - I explain further down**) there is a possibility of getting an empty FetchProperty as indicated here:

With a timer interval of 5 sec or so, I am sure this "collision" would almost never occur. However, my current design is for a function which returns a value rather quickly from which I can branch - just as you said:

and if it is NOT a list - meaning that the fetch returned no valid value - then what? My solution is to fetch again - repeatedly until a list is returned, and then do A or B based on the value obtained from the list. I am fine with the loop (inefficient and clumsy as it is).

What is the alternative?

**What the app does is to allow the selection of a live event audio stream which is then delayed manually (by inserting a pause or series of pauses) so that it is sync'd with a video of the same live event. I am not sure that getting a 5 second delayed response to the "is playing" function would work. Maybe I could redesign the app so that it does not need to know Player1.IsPlaying in this way...

Perhaps you could elaborate on why I should not spin in a while loop until a valid value is returned.

Thanks for taking time to help me understand this.

Randal

Start with 1000ms

Do nothing
In 1000ms you check again

To not block the background task
You check periodically anyway, for example 1000ms... you do not want to block several threads in the background and then when data is available all blocked threads continue running at the same time...

Taifun

Understood. But since there is no mechanism to give up the processor for a time, like unix sleep(), one has to design the app so that the conditional processing based on IsPlaying can be abandoned and then have it repeated later.

If the processing is in response to an immediate user action (like btnPauseUnPause shown here), then an Alert could be issued to prompt the user to repeat the action.

However, my existing app currently requires IsPlaying in other places where the connection is not as direct to a user input to which it is responding...

But before I go with the "do while" :-1: I'll see if the abandon-retry will work in these other places as well :slight_smile:.

Thanks again,
Randal

I have two issues.

I open my app which runs a service in the background using Itoo after a while the notification of Itoo comes up. If you press it, it re-opens my app and I have two apps running (doubles my current screen). When I press the mobile's "back" button it goes back to my first app.
Is there a way to stop this ?

Also I can't use AI companion if Itoo is included in my app.

You can reprogram the notification click functionality using melon notification.


Noted.

I found the blocks you are referring to but I'm not sure how to re-program.
My understanding is that if you click the notification it should open the app. If the app is already opened it re-opens another instance. I don't use any button and I don't want to run any Itoo procedure.

Also even if I fix this I will still have the same issue with the fixed Itoo notification that comes up from the CreateProcess block. If you click that it also opens another instance of the app

Why do I get this error every time I connect to MIT Companion:


I downloaded the latest version of Itoo extension

There currently is an issue with the companion app to load extensions, see also String IndexOutOfBounds Exception while using extensions in companion app - #65 by jis

However if you want to use itoo, you have to test after building and use the apk file anyway...

Taifun