Add Media Plugin Support (GIFs, WebDAV, etc.)#2500
Open
mozzwald wants to merge 1 commit into
Open
Conversation
Introduce a generic AIDL media provider contract so external plugins can supply image and video media without adding network permissions to HeliBoard. Add provider discovery, search/browse support, thumbnail preview handling, and a hosted in-keyboard picker so IME focus is preserved for commitContent insertion. Add media insertion plumbing with MIME and size validation, rich-content commitContent support, and ACTION_SEND fallbacks for apps that do not accept rich content. Keep public MediaStore export as an explicit opt-in final fallback for targets that reject private content URIs, while skipping private URI attempts for known-bad targets such as AOSP/Graphene Messaging. Gate all media entry points behind the Media Plugins setting, default media plugins and public MediaStore fallback to off, expose minimal settings, and add only the emoji-toolbar share entry point. HeliBoard remains permission-neutral with no internet or storage/media permissions added.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a generic media plugin system to HeliBoard.
The goal is to allow optional media sources (GIF search, WebDAV/Nextcloud browsers, etc.) without requiring internet permission or bundled online services inside the keyboard itself.
The keyboard stays offline-only by default, while separate plugin apps handle network access, searching, downloading, authentication, and media browsing. HeliBoard can now discover external apps that expose themselves as media providers using the new plugin intent/API.
Plugins provide:
HeliBoard handles:
commitContent()into the target app when supportedKeeping the picker inside the IME was important because launching external Activities caused focus loss in apps, which breaks media insertion. The picker is opened by going to the emoji keyboard and on the far right is a new image/media icon.

Media plugin support must be explicitly enabled by the user in Settings >> Preferences under Emoji (seemed logical fit since the icon is on emoji toolbar). After a plugin installation, the user must enable support for it from "Manage media plugins". The Public Media fallback option was added because I'm using GrapheneOS, and its default SMS/MMS app currently does not accept private content URIs (more info). When enabled, this fallback creates a temporary MediaStore image that any app can access. Since this makes the media publicly accessible to other apps on the device, the feature is optional and disabled by default.
I also put together two proof-of-concept plugins for testing:
And the keyboard branch itself:
The WebDAV plugin was mainly built as a proof of concept to show that the API works for more than just GIF search.
This is likely draft-PR territory, but the overall architecture is working well and I wanted to have the maintainers have a look to make sure it's the right direction.
Tested so far with:
commitContent()Would appreciate feedback on: