Programmatic Broadcast Receiver

176 views
Skip to first unread message

jst...@gmail.com

unread,
Oct 11, 2016, 12:29:00 PM10/11/16
to Tasker - Developers
I'm trying to understand how the tasker plugin actions are broadcast to the broadcast receivers.  For instance, I know that putting the broadcast receiver in the manifest XML that listens for "com.twofortyfouram.locale.intent.action.FIRE_SETTING" will cause tasker to instantiate an instance of this receiver and send it the intent.

In my case, I am working with a long-running service that programmatically registers a broadcast receiver when it starts up but it doesn't seem that it receives any of the tasker intents.  This flow would be ideal for me because the broadcast receiver can communicate directly with the service because it has a reference to it.  My workaround has been to have the manifest XML broadcast receiver to send intents to the service receiver but that seems to just add another layer of async calls which might not fit the tasker plugin spec.  Does tasker only work with manifest-instantiated broadcast receivers and if so, is there a better architecture I can be using to communicate with a long-running background service?

Pent

unread,
Oct 12, 2016, 1:28:58 AM10/12/16
to Tasker - Developers

In my case, I am working with a long-running service that programmatically registers a broadcast receiver when it starts up but it doesn't seem that it receives any of the tasker intents.

From the Tasker code, I can't see anything that would prevent that, but ...
 
 This flow would be ideal for me

... I think inherently a statically declared receiver is going to be more reliable
than a dynamic one in a service.

I don't see the indirection as being particularly bad.

Tasker supports asynchronous results for action plugins, other
plugin hosts might be more problematic, I don't know.

Pent

Jim Stys

unread,
Oct 12, 2016, 7:57:28 AM10/12/16
to Tasker - Developers
Okay, I'll likely refactor to use the static broadcast receiver if that's the case.  I just was under the impression that maybe tasker had some mechanism to broadcast to only the static manifest broadcast receiver and that's why it complained when I omitted it from the XML altogether.  If that's not the case then maybe there was an issue with the dynamic receiver not actually registering for the intents as expected and might be worth a second look.

Thanks for the help

Crafty Apps Support

unread,
Oct 12, 2016, 9:43:05 AM10/12/16
to task...@googlegroups.com

> Okay, I'll likely refactor to use the static broadcast receiver if
> that's the case. I just was under the impression that maybe tasker
> had some mechanism to broadcast to only the static manifest broadcast
> receiver and that's why it complained when I omitted it from the XML
> altogether.

I would need to see the complaint to comment on that.
> If that's not the case then maybe there was an issue with the dynamic
> receiver not actually registering for the intents as expected and
> might be worth a second look.

I still don't recommend it from a reliability perspective.

Pent

Jim Stys

unread,
Oct 12, 2016, 12:14:27 PM10/12/16
to Tasker - Developers
I would need to see the complaint to comment on that.
 
The toast error message that flashes when I try to choose my action plugin is "Error: plugin error: missing, disabled, not exported or no permission, or too many receivers".  This is when I exclude the broadcast receiver from my manifest.xml altogether and attempt to only use the dynamic receiver.

Crafty Apps Support

unread,
Oct 12, 2016, 12:31:27 PM10/12/16
to task...@googlegroups.com

I would need to see the complaint to comment on that.
 
The toast error message that flashes when I try to choose my action plugin is "Error: plugin error: missing, disabled, not exported or no permission, or too many receivers".  This is when I exclude the broadcast receiver from my manifest.xml altogether and attempt to only use the dynamic receiver.

If you enable system logging (Menu / Prefs / More / Debug To System Log)
we should be able to get more detail.

Pent

Jim Stys

unread,
Oct 12, 2016, 12:40:31 PM10/12/16
to Tasker - Developers
Looks to just create the logcat message saying "Plugin: warning: no acceptable receiver for package com.geminiapps.mqttsubscriber".  This is even after I have verified that my service is running and the "registerReceiver" method was called for the tasker intents.  This is why I was under the assumption that tasker requires a manifest static broadcast receiver.

Crafty Apps Support

unread,
Oct 12, 2016, 2:39:14 PM10/12/16
to task...@googlegroups.com
The only way I can see that is possible to have only that warning
is if there were one or more receivers found, but none matched your package
name.

Pent

Pent

unread,
Oct 12, 2016, 2:43:08 PM10/12/16
to Tasker - Developers

Jim Stys

unread,
Oct 12, 2016, 3:07:08 PM10/12/16
to Tasker - Developers
This leads me to believe that tasker is using the "queryBroadcastReceivers" to find a registered receiver (within the manifest only according to the SO article you linked).  If that is true then tasker would require that a broadcast receiver be present in the manifest even if one is registered programatically due to queryBroadcastReceivers not finding it.  So a workaround would be to have a dummy broadcast receiver be registered via the manifest and the real one would be registered programatically.  This is the case that I implemented first but my dynamic receiver was not receiving the tasker intents upon initial testing.  

If there is indeed no mechanism that tasker is using to send the broadcast ONLY to the registered receivers that it finds in "queryBroadcastReceivers", then there must just be an issue with my dynamic receiver's registration/lifecycle.  The only thing I can think of on the top of my head is that my receiver is in a different package from the tasker plugin but to me this shouldn't matter because it is still registering with the same intent-filter that tasker is broadcasting on.

Jim Stys

unread,
Oct 12, 2016, 3:10:36 PM10/12/16
to Tasker - Developers
Depending on implementation, this would all make sense if tasker is using the "setPackage" method on the broadcast intent since I have conflicting package names between my programmatic broadcast receiver and the tasker plugin.

Pent

unread,
Oct 13, 2016, 2:55:04 AM10/13/16
to Tasker - Developers


This leads me to believe that tasker is using the "queryBroadcastReceivers"

Correct.
 
thing I can think of on the top of my head is that my receiver is in a different package from the tasker plugin but to me this shouldn't matter because it is still registering with the same intent-filter that tasker is broadcasting on.

It does matter, it's required to be in the same package for security reasons.

Pent

Jim Stys

unread,
Oct 13, 2016, 7:42:37 AM10/13/16
to Tasker - Developers
Okay I got it.  At this point I've already refactored my code to only use the static broadcast receiver but this has helped me get a better understanding of how the plugins / android works in general so thanks for the support.

Jim Stys

unread,
Oct 13, 2016, 4:17:23 PM10/13/16
to Tasker - Developers
One last question now that I am going with the approach that the static broadcast receiver is a proxy between tasker and my long-running service.  Triggering events from my service seems fairly straightforward because I can add a passthrough bundle that my broadcast receiver will receive when tasker queries it and it can return a result immediately based on the state of the passthrough bundle.  How do I handle state conditions when my broadcast receiver needs to send an async query to my service and wait for results?  The sample projects don't seem to highlight this area.  Can I use a wait->signal thread mechanism to wait for the asynchronous reply in the broadcast receiver from the service before returning the satisfied/unsatisfied result to tasker?

Crafty Apps Support

unread,
Oct 14, 2016, 2:59:58 AM10/14/16
to task...@googlegroups.com

Jim Stys

unread,
Oct 14, 2016, 6:36:08 AM10/14/16
to Tasker - Developers
I was under the impression that this is for action plugins (settings). Does this logic work for state plugins as well?

Pent

unread,
Oct 15, 2016, 12:28:43 PM10/15/16
to Tasker - Developers


I was under the impression that this is for action plugins (settings).  Does this logic work for state plugins as well?

Sorry, you're right, got mixed up, you can't do that with state plugins.

I'm sorry, I've never written a plugin and so never had to deal with the problem, maybe one of the plugin devs can chime in.

However, I would just return UNSATISFIED (or cached previous state) when queried by Tasker and
not ready to give an answer. When you have an answer, ask Tasker to query you again with
a REQUEST_QUERY intent.

Pent

Jim Stys

unread,
Oct 15, 2016, 12:55:03 PM10/15/16
to Tasker - Developers
Haha no problem, you can probably tell that I haven't either.  That approach makes sense to me I'm just not fully understanding how the broadcast receiver works.  Does each intent sent by tasker create a new instance or can the instance that sends the REQUEST_QUERY cache the result and respond back when it receives the query from tasker?  

This seems like the perfect approach if I'm guaranteed that only 1 instance of the broadcast receiver is being instantiated.  Seems like from what I'm reading that broadcast receivers are destroyed immediately after onReceive completes.  Leveraging shared preferences seems like an option for storing the cached state.  Only other alternative to that is probably to get my dynamic broadcast receiver working on the service side but you previously said that you had doubts about the reliability of such an approach.  Passthrough data bundles only apply to event plugins correct?  Because that could potentially work if it was possible to add it in the REQUEST_QUERY intent for state plugins.

Crafty Apps Support

unread,
Oct 16, 2016, 2:47:08 AM10/16/16
to task...@googlegroups.com

> Haha no problem, you can probably tell that I haven't either. That
> approach makes sense to me I'm just not fully understanding how the
> broadcast receiver works. Does each intent sent by tasker create a
> new instance or can the instance that sends the REQUEST_QUERY cache
> the result and respond back when it receives the query from tasker?

It will be a new instance each time (they are created by Android, not by
Tasker BTW), but you can cache
the result in your service, in a static, DB, SharedPreferences etc.
>
> about the reliability of such an approach. Passthrough data bundles
> only apply to event plugins correct?

Yes.

Pent

John Doe

unread,
Oct 16, 2016, 3:53:59 AM10/16/16
to Tasker - Developers
Locale protocol has several problems in my opinion. The state plugin schema is terrible indeed. It works well only if you can retrieve the information directly in the broadcast receiver. Since you can't bind a serivce in a broadcast receiver you can only use shared preferences, but in this case you could read old information. In this case it helps to save a timestamp or remove the entry when you read. Don't cache the result in the receiver using static field because this approach won't work at all.

Jim Stys

unread,
Oct 30, 2016, 5:16:16 PM10/30/16
to Tasker - Developers
Just to clear up some information on the original post, I've learned that sending a broadcast to a specific package is regarded as an "explicit intent" in android.  According to the android docs, dynamically registered broadcast receivers are unable to receive explicit intents at all.  This means that tasker/locale plugins can only utilize the static receivers in the manifest XMLs.  This means there is (as far as I know) no clean workaround for the problems that John Doe mentions with working with long-running services and tasker/locale plugins because the condition plugins require a quick,synchronous reply from the broadcast receiver which has no way of communicating synchronously with the service.  The tasker extensions seem to provide a workaround with action plugins returning success/failure asynchronously but not condition plugins.  

I've verified that my dynamic broadcast receiver exhibits the behavior outlined in the android docs by confirming that my static / dynamic receivers register using the same package name via some logcat output.  Not sure why android has this limitation but understand that tasker/locale need to use explicit intents for security purposes.  
Reply all
Reply to author
Forward
0 new messages