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

Send PROVIDER_CHANGED broadcast to all packages #822

Closed
ekalin opened this issue Aug 6, 2019 · 18 comments
Closed

Send PROVIDER_CHANGED broadcast to all packages #822

ekalin opened this issue Aug 6, 2019 · 18 comments

Comments

@ekalin
Copy link

ekalin commented Aug 6, 2019

Todo Agenda is a widget that displays calendar events and tasks, and it can display tasks from OpenTasks. (I wrote the support for tasks, but I'm not the maintainer.)

It would be nice if the widget were updated whenever a task is added/changed/completed/etc. From what I've gathered, a PROVIDER_CHANGED broadcast is sent in these cases, but on Oreo and later it's limited to OpenTasks' package only:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)

I'm not sure why that limitation (and the comment about figuring out how to do it in 8+). I've tested with a simple app that sends an equal broadcast (without specifying the package) and the widget was able to receive the broadcast.

Could that setPackage be removed, so that any app interested in knowing about changes in tasks can be notified?

@dmfs
Copy link
Owner

dmfs commented Aug 6, 2019

The problem with Android 8 is, implicit broadcasts can no longer be sent to broadcast receivers which are registered in the Manifest of an app (see https://developer.android.com/guide/components/broadcasts).

Broadcast receivers which are registered dynamically by an app running in the foreground or by a background service would still receive this broadcast, but if the app is already running, it could also use other means of getting notified when the content provider changes, like a ContentObserver.

So the usefulness of this broadcast is somewhat limited.

Do you register your receiver dynamically at runtime or in the Manifest file?

@ekalin
Copy link
Author

ekalin commented Aug 6, 2019

It's registered dynamically. It was indeed complicated to make receiving the broadcasts work, but the problem is solved.

I'd say the responsibility for making sure that the broadcasts are received should be in the listening app; OpenTasks can send the broadcast; if anyone wants to listen they can take the appropriate actions (in this case, registering them dynamically at an appropriate time).

@yvolk
Copy link

yvolk commented Aug 7, 2019

@dmfs @ekalin We fought with this problem in the widget app here: plusonelabs/calendar-widget#298
And at that time dynamic subscription to notifications was introduced.
Unfortunately, the widget app needs to run at least in the background to be able to subscribe to notifications...

So although sending anonymous broadcast is better than nothing, could we, in addition to it, have a notification specifically targeted at our ToDo Agenda app, please.

On Tasks support with a link to the Beta version please see plusonelabs/calendar-widget#308

@dmfs
Copy link
Owner

dmfs commented Aug 7, 2019

I see. Adding an explicit broadcast for every app wouldn't scale very well.

I see two options:

  • TaskProvider tries to resolve all intents which listen for the broadcast and addresses each one individually. I'm not 100% certain whether that actually works (the resolve part, I mean). I mean, it would defeat the purpose. Android introduced the broadcast limitations to save power and doing the broadcast "manually" doesn't save anything.
  • TaskProvider provides an interface for apps to register for broadcasts. I had something like that in mind when I created Plug-in mechanism #776. Well, the idea was to allow apps for registering a service intent, that OpenTasks uses to provide plug-in functionality. But I guess we could also use it to notify interested apps. After all, a widget is some sort of plug-in too.

The first option is definitely the quicker one, so I'll give it a try.

@yvolk
Copy link

yvolk commented Aug 7, 2019

@dmfs It came to me that you could create an option "App packages to notify on task updates" and allow a User (who will have an instruction in FAQ...) to type needed package(s) manually.
This will solve the problem with all possible listeners?!

@dmfs
Copy link
Owner

dmfs commented Aug 7, 2019

Let's try the first option above first, at least as a temporary solution. It should be fairly easy to implement. I'd like to avoid asking users questions about package names.

dmfs added a commit that referenced this issue Aug 8, 2019
Since Android 8 it's not possible to listen to implicit broadcasts anymore when the reciever is declared in the AndroidManifest.xml.
In a previous commit we disabled sending out broadcasts to other apps. This caused some trouble.
This commit tries to resolve all broadcast receivers which listen for PROVIDER_CHANGED and send individual broadcasts to each of them.
@dmfs
Copy link
Owner

dmfs commented Aug 8, 2019

Can you check whether the commit in branch stories/822-restore-broadcast-kind-of fixes this?

@yvolk
Copy link

yvolk commented Aug 8, 2019

@dmfs I registered another Intent.ACTION_PROVIDER_CHANGED for "org.dmfs.tasks" in ToDo Agenda app and checked.

But this your commit doesn't work: as I found out by adding debugging messages to your code, this doesn't find any receivers except your own:

List<ResolveInfo> resolveInfos = context.getPackageManager().queryBroadcastReceivers(intent, 0);
Log.i(Utils.class.getSimpleName(), "ContentUri: " + contentUri +
                ", resolved packages: " + resolveInfos);

gives:

2019-08-08 20:42:58.819 12364-12364/org.dmfs.tasks I/Utils: ContentUri: content://org.dmfs.tasks, resolved packages: [ResolveInfo{291408c org.dmfs.tasks/.homescreen.TaskListWidgetProvider m=0x308000}, ResolveInfo{1cb53d5 org.dmfs.tasks/.homescreen.TaskListWidgetProviderLarge m=0x308000}, ResolveInfo{2dbc7ea org.dmfs.tasks/.notification.TaskNotificationHandler m=0x308000}]
2019-08-08 20:42:58.820 12364-12364/org.dmfs.tasks W/ContentResolver: Failed to get type for: content://org.dmfs.tasks (Unsupported URI: content://org.dmfs.tasks)

But this causes an update in ToDo Agenda widget:

  Intent intent = new Intent(Intent.ACTION_PROVIDER_CHANGED, contentUri);
  intent.setPackage("org.andstatus.todoagenda");
  context.sendBroadcast(intent);

@ekalin
Copy link
Author

ekalin commented Aug 8, 2019

I've tested without any setPackage and it worked. That is, what the code does for version < O.

From what I understand of the changes introduced in O, only receivers are affected (in how they must register the receivers), but senders can continue doing what they did before.

@dmfs
Copy link
Owner

dmfs commented Aug 8, 2019

Without setPackage I didn't even receive the broadcast in OpenTasks itself. I guess, for the time being, we do have to hard code the supported package names. I'll prepare something to make this work.

@ekalin
Copy link
Author

ekalin commented Aug 8, 2019

I'm not 100% sure, but this might be because OpenTasks does not registers the receivers dynamically. Since this registration can be tricky (at least for widgets), one solution might be

  1. Send a broadcast with no package
  2. If on Android O or later, send a second broadcast, setting package to org.dmfs.tasks

It's not elegant, but at least there's no need to hard code applications that might be interested in the broadcast.

@dmfs
Copy link
Owner

dmfs commented Aug 8, 2019

right, that could work too. I'll ponder on this.

@yvolk
Copy link

yvolk commented Aug 9, 2019

@dmfs @ekalin Yes, my test was on Android 8 device with dynamically registered receivers.
BTW, according to Google Play stats, more than 80% of ToDo Agenda users have Android 8+ although Android v.4.0.4+ is supported.
...And more than 91% of users have Android 7+ which supports Java 8 ;-)

@yvolk
Copy link

yvolk commented Aug 11, 2019

I implemented "Register for notifications on Open Tasks provider changes" in the "Todo Agenda" app.
Please see and try the updated Beta package here: plusonelabs/calendar-widget#308 (comment)

@dmfs
Copy link
Owner

dmfs commented Aug 16, 2019

@yvolk just to be clear, you still need an explicit broadcast, right? In this case I'll hard code your package name for now.

@yvolk
Copy link

yvolk commented Aug 16, 2019

Yes, please

dmfs added a commit that referenced this issue Aug 16, 2019
Since Android 8 it's not possible to listen to implicit broadcasts anymore when the reciever is declared in the AndroidManifest.xml.
In a previous commit we disabled sending out broadcasts to other apps. This caused some trouble.
For new we hard code 3rd party receiver package names in a resource array. This is supposed to be changed later on, see #824.
@dmfs
Copy link
Owner

dmfs commented Aug 16, 2019

Ok, I've updated the branch. Please let me know if that works for you.

@yvolk
Copy link

yvolk commented Aug 16, 2019

Yes, it works, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants