Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support bi-directional custom actions #181

Closed
ryanheise opened this issue Feb 16, 2020 · 18 comments
Closed

Support bi-directional custom actions #181

ryanheise opened this issue Feb 16, 2020 · 18 comments
Assignees
Labels
enhancement New feature or request

Comments

@ryanheise
Copy link
Owner

Note to self: Implement bi-directional custom actions. This essentially means adding a mechanism to send arbitrary messages from the background task to the UI.

@YaarPatandarAA
Copy link
Contributor

Any Updates on this?
Any workarounds until this is completed?

@ryanheise
Copy link
Owner Author

This is definitely high on my priority list. I plan to take a crack at it on the weekend.

There have always been workarounds using Dart's standard APIs to send arbitrary messages between isolates using send/receive ports (you may find mentions of the approach in past issues).

@lkho
Copy link

lkho commented Apr 19, 2020

Hi everyone,

Is it possible to support partially bi-directional actions first (by changing the void interface functions to return Future and returning the Future through the method channel)? Since currently it is not even possible to query the background for a simple value from the UI, or wait for the action to complete (awaiting from the UI does not wait for the background async function).

@ryanheise
Copy link
Owner Author

Hi @lkho

You can't send futures through a method channel. I am wondering what API would be most appropriate for this. Currently all communication from the background task to the UI is via streams, so my current thinking is to make a custom event stream.

By the way, I have added an FAQ entry in the wiki for how to use the standard isolate APIs to send messages if you need something immediately.

@lkho
Copy link

lkho commented Apr 19, 2020

I mean by changing this line to return the result (and if the result is a Future)

task.onCustomAction(
call.method.substring(_CUSTOM_PREFIX.length), call.arguments);

i.e. return task.onCustomAction(

then we can call await AudioService.customAction('foo') from the UI and receive the result from the background.

Similarly for all other onXXX methods, currently the result is not returned, thus when the UI calls await AudioService.xXX(), the await does NOT actually wait for the completion of the method in the background task, but only waits for the MethodChannel to execute the callback on

_backgroundChannel.setMethodCallHandler((MethodCall call) async {

I know this is not a perfect bi-directional communication, but at least the background task can passively react to some action and return some info.

@ryanheise
Copy link
Owner Author

I see, that could be useful as well. Maybe would integrate both ideas into the API going forward.

@ryanheise
Copy link
Owner Author

Update! I've just implemented bi-directional custom actions on git master. (I haven't yet implemented @lkho 's good suggestion, but that can be considered eventually too.)

Probably a better way to describe this is that "actions" are the messages you send to the background audio task, and "events" are what you listen to coming back, so this feature is really "custom events". To send a custom event from the background to the UI, call:

AudioServiceBackground.setCustomEvent(whatever);

And in the UI, listen to the AudioService.customEventStream stream. Please let me know if you notice any issues.

P.S. Apologies for the huge wait. I know what it's like to wait a long time for an issue to be addressed, and I originally hoped to not let that sort of thing happen on this project, but hopefully the FAQ on IsolateNameServer helped in the meantime.

@hacker1024
Copy link
Contributor

Cool! This for me personally removes some boilerplate code to start up the audio service and play a playlist/station.

Hopefully it's similar for everyone else that does those kinds of things.

@ryanheise
Copy link
Owner Author

I've now also implemented @lkho 's suggestion. I have tested this on Android, but not yet on iOS.

@lkho
Copy link

lkho commented May 2, 2020

Thanks very much! :)

@ryanheise
Copy link
Owner Author

I've finished testing this on iOS (seems to work as intended), and it is now released in 0.8.0.

@mohammadne
Copy link

in onCustomAction(name , args) in background we can send a name and any argument we want.

I want to know that is it possible to make a method in AudioServiceBackground like AudioService.customAction , which we could call it ?

because currently we only can send one type of ```

@lkho
Copy link

lkho commented Aug 2, 2020

AudioService.customAction and BackgroundAudioTask.onCustomAction is meant for sending from UI to background, not from background to UI.

If you want the reversed direction, you can use AudioServiceBackground.sendCustomEvent

@mohammadne
Copy link

I know that .
I meant we have same process of sending events from UI to background , from background to UI.

@ryanheise
Copy link
Owner Author

@mohammadne Do you mean you prefer actions rather than events? If so, I'm not sure why since sendCustomEvent is strictly more powerful than customAction as it allows class data structures to be sent. For example, you could invent your own class like this:

class MyEvent {
  String name;
  dynamic args;
}

And send instances of this as your custom events. And since you can invent your own class, you could even add fields that are more specific to your app, and you could even create subclasses for different types of event, etc.

@mohammadne
Copy link

mohammadne commented Aug 2, 2020

Hi @ryanheise
if sendCustomEvent is strictly more powerful than customAction , why do you don't change onCustomAction.

I mean that we have a similar approach in both directions.

@ryanheise
Copy link
Owner Author

There are really two issues here. I meant that sendCustomEvent is more powerful in the sense that you are able to encode any object, not just strings and ints. I will eventually make customAction support such flexible parameter values as well.

But the other issue is that in one direction we use "actions" and in the reverse direction we use "events". That is intentional because when the UI communicates with the background task, it does so synchronously. That is, it says "DO THIS NOW!". E.g. AudioService.play() says "play now!". Everything that comes back from the background task to the UI happens asynchronously. You don't know when these events will be received so you just listen to them and react to them. So the model used for communication from the background task to the UI is events.

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs, or use StackOverflow if you need help with audio_service.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Oct 18, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants