Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client
117
fork

Configure Feed

Select the types of activity you want to include in your feed.

README.md

Expo Receive Android Intents#

An Expo module that handles incoming Android intents for sharing text, images, and videos into the Bluesky app.

What It Does#

This module intercepts Android share intents (when a user shares content from another app to Bluesky) and converts them into deep links that the app can handle. It supports:

  • Text sharing - Share plain text to compose a post
  • Image sharing - Share single or multiple images (up to 4) to attach to a post
  • Video sharing - Share a single video to attach to a post

The module operates entirely in native Android code and requires no JavaScript API calls. It automatically registers itself with Expo's module system and handles intents when the app is launched or receives new intents.

Platform Support#

  • Android: Fully supported
  • iOS: No-op (iOS handles share intents differently)
  • Web: No-op

How It Works#

Architecture#

The module uses Expo's module lifecycle hooks to intercept Android intents at two key moments:

  1. OnCreate - When the app is first launched from an intent
  2. OnNewIntent - When the app receives a new intent while already running

Intent Processing Flow#

  1. Intent Reception: Android sends an ACTION_SEND or ACTION_SEND_MULTIPLE intent
  2. Type Detection: Module determines content type (text, image, or video)
  3. Content Processing:
    • Text: URL-encodes the text
    • Images: Saves to app cache, extracts dimensions (limited to 4 images max)
    • Video: Copies to app cache with extension detection, extracts dimensions
  4. Deep Link Generation: Creates a bluesky://intent/compose URL with encoded parameters
  5. App Launch: Starts a new activity with the deep link, which is handled by useIntentHandler

The module generates deep links in the following formats:

# Text only
bluesky://intent/compose?text=<encoded-text>

# Images (single or multiple)
bluesky://intent/compose?imageUris=<uri1>|<width>|<height>,<uri2>|<width>|<height>&text=<encoded-text>

# Video (single only)
bluesky://intent/compose?videoUri=<uri>|<width>|<height>&text=<encoded-text>

All URIs use the file:// scheme pointing to files in the app's cache directory. Dimensions are included to avoid expensive measurement operations in JavaScript.

Security Considerations#

  • Images and videos are copied to the app's private cache directory before being passed to the app
  • The JavaScript handler (useIntentHandler.ts) validates image URIs with a regex to prevent external URLs
  • Image URIs containing http:// or https:// are filtered out
  • Multiple image sharing is limited to 4 images maximum

Key Files#

Module Configuration#

  • expo-module.config.json - Declares the module and registers it with Expo (Android-only)

Native Implementation#

  • ExpoReceiveAndroidIntentsModule.kt - Main module class with intent handling logic

    • handleIntent() - Routes intents based on type
    • handleTextIntent() - Processes text sharing
    • handleAttachmentIntent() - Processes single image/video
    • handleAttachmentsIntent() - Processes multiple images
    • getImageInfo() - Saves images to cache and extracts dimensions
    • getVideoInfo() - Extracts video dimensions using MediaMetadataRetriever
  • android/build.gradle - Gradle build configuration

    • Version: 0.4.1
    • Requires: Kotlin, expo-modules-core
    • Compile SDK: 33, Min SDK: 21, Target SDK: 34
  • android/src/main/AndroidManifest.xml - Empty manifest (intent filters configured in main app)

JavaScript Integration#

The deep links generated by this module are handled by:

  • src/lib/hooks/useIntentHandler.ts - useComposeIntent() parses the deep link parameters and opens the composer with pre-populated content

Installation#

No manual installation is required. Gradle automatically includes this module during the Android build process. The module is auto-linked through Expo's module system.

Configuration#

Intent filters must be configured in the main app's AndroidManifest.xml to declare which MIME types the app accepts. The module itself has an empty manifest.

Implementation Notes#

Android Version Compatibility#

The module uses version-specific APIs for Android 13+ (API 33):

  • getParcelableExtra() with type parameter on Android 13+
  • Legacy getParcelableExtra() on older versions

File Handling#

  • Temporary files are created using File.createTempFile() in the app's cache directory
  • Image files use .jpeg extension and are compressed at 100% quality
  • Video files preserve their original extension, defaulting to .mp4 if none is detected

Limitations#

  • Video sharing only supports a single video
  • Multiple video sharing is not implemented
  • Images are always converted to JPEG format
  • Maximum of 4 images can be shared at once