3rd party actions triggered by Di2 buttons - #345
cnoons-cyq wants to merge 3 commits into
Conversation
Allow third-party apps to register as external action providers that can be triggered by Di2 switch events. Providers are discovered via intent services, communicate actions over broadcast intents, and appear as options in the switch preference lists. Includes a sample-provider module demonstrating the provider API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use queryBroadcastReceivers() instead of queryIntentServices() so the ACTION_PROVIDER intent-filter lives on the receiver directly. This eliminates the need for a separate stub service class in providers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without this, queryBroadcastReceivers() returns zero results for external apps targeting SDK 30+, so providers are never discovered and LIST_ACTIONS is never sent. Verified on Karoo 2 (Android 12 / API 32) with an external provider installed: discovery and LIST_ACTIONS round-trip both fire. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Pushed Hit a discovery issue while testing this against an external provider on a Karoo 3 (Android 12 / API 32): Root cause is Android 11+ package visibility (introduced at API 30): an app targeting SDK 30+ can only resolve receivers in apps it has explicit visibility into. Ki2 targets SDK 34 with no Fix is a four-line addition to <queries>
<intent>
<action android:name="com.valterc.ki2.ACTION_PROVIDER" />
</intent>
</queries>This grants Ki2 visibility into any installed app whose receiver matches the discovery action — exactly the set you want to enumerate, nothing broader. Sample provider didn't expose this earlier because it ships in the same Gradle build and gets installed/observed via the install path; cross-app providers go through the visibility filter. Verified end-to-end on Karoo 2 (Android 12 / API 32) after the fix:
Note for third-party providers: they also need the inverse — a |
|
Hi, thanks for the PR. I had this plan myself but didn't make it because of Android limitations. I don't think it's a good idea for Ki2 to be handling data from other apps and invoking actions on other apps directly, this goes way of out scope and possibly create side effects that I don't want to deal with. There are feature requests for Hammerhead to allow extensions to provide custom actions and commands, that would allow this feature without Ki2 having to manage all these registrations and lookup between apps. Otherwise what I might end up doing is just publishing in a broadcast manner, which places the responsibility of handling the commands on the receiving app, not in Ki2. |
|
Hi, thanks for your response! I can understand all of that. I had previously put the initial PR changes together in one go whilst building the first iteration of my app, and long before I'd had a play with the BonusActions in karoo-ext as I only had a karoo 2 on hand. I was reading the discussions on the BonusAction PR in karoo-ext yesterday and it would be great to see something like BonusTriggers being mapped to BonusActions in Karoo OS. Whilst I'd love to see Hammerhead make that happen, I'd also be keen to see a simple broadcast on button press as well. I completely respect your view of not wanting to handle data from, or invoke actions on other apps. I'll sit tight and wait to see what happens in the future. |
Allows third-party apps to register as external action providers that can be triggered by Di2 switch events. Providers are discovered via broadcast receivers, communicate actions over broadcast intents, and appear as options in the Ki2 switch preference lists.
Includes a sample-provider module demonstrating the provider API.
Why
I'm working on an app for Cycliq that will use BLE on Karoo devices to control, monitor and report device status through a data field. I learned a lot through your Ki2 repo and thought this could be a cool feature for people using Ki2 and Cycliq devices down the track.
My exact use case will be things like using the Di2 shifter buttons to trigger light mode changes on a BLE device, or sending commands to cause the device to make footage locked so it isn't overwritten, or to take a picture!
My app is still a little while away, some more testing is required, but thought I could get the ball rolling early on this PR!
Reasons for Intent Based services
My first implementation used AIDL for IPC between Ki2 and providers. This would require providers to copy AIDL interface files and a shared ExternalAction Parcelable class into their project which I felt was a nuisance. I considered the option of a new ki2-ext-actions package to work around this, but I doubt you want to maintain a package for something you haven't implemented!
Using an Intent-based protocol eliminates the need for shared code and need for external dependencies: providers only need documented string constants and standard Android APIs (BroadcastReceiver, Intent, org.json).
During development, Ki2 calling startService() to communicate with providers was found to be blocked by Android's background service restrictions on Karoo 2 hardware. After this, the protocol was revised to use sendBroadcast() with setPackage() for all provider communication, which works reliably from any execution context.
Prior to discovering this I had been testing on a Karoo 3 but I don't have access to it right now, and I need to test further on the Karoo 3 to ensure core functionality works... Providers declare a manifest to handle broadcasts, giving them an opportunity to start their own services and execute their actions.
Protocol
Changes
standard ListPreference dialog)