Intent launcher
Send the user to the right system screen: Wi-Fi settings when the network is off, your app’s own
permission page after a denied prompt, or straight into another app.
@symbiote-native/intent-launcher wraps
expo-intent-launcher so
every SymbioteNative adapter can launch an Android intent and read another app’s icon, not just
React. Every export is a stateless free function, an enum or a plain type, so the React, Vue,
Angular, Svelte, and Solid entry points are plain re-exports of the same core.
This is Android only: upstream ships no iOS implementation, so every function throws
UnavailabilityError on iOS. Guard calls with a platform check.
| OS platform | Support |
|---|---|
| iOS | not applicable (throws) |
| Android | live |
| Framework adapter | Support |
|---|---|
| React | live |
| Vue | live |
| Angular | live |
| Svelte | live |
| Solid | live |
Installation
Section titled “Installation”npm install @symbiote-native/intent-launcherScaffolding or extending a SymbioteNative app? npx @symbiote-native/cli new --intent-launcher (or
add --intent-launcher in an existing app) installs and wires this for you - see
@symbiote-native/cli.
expo-intent-launcher and expo-modules-core come along as regular dependencies, pinned to exact
versions. Never install either yourself, and never add the expo meta-package to your project (it
bundles its own Metro/Babel pipeline, which conflicts with this project’s own).
No runtime permission or manifest edit is needed to start an activity or read an icon.
All five adapters re-export the same functions; there is no per-adapter hook, composable or service, since nothing here holds live state.
import { ActivityAction, startActivityAsync } from '@symbiote-native/intent-launcher/react';
export default function OpenWifi() { return ( <button title="Wi-Fi settings" onPress={() => startActivityAsync(ActivityAction.WIFI_SETTINGS)} /> );}<script setup lang="ts">import { ActivityAction, startActivityAsync } from '@symbiote-native/intent-launcher/vue';
function onPress() { void startActivityAsync(ActivityAction.WIFI_SETTINGS);}</script>
<template> <button title="Wi-Fi settings" @press="onPress" /></template>import { Component } from '@angular/core';import { SYMBIOTE_ELEMENTS } from '@symbiote-native/angular';import { ActivityAction, startActivityAsync } from '@symbiote-native/intent-launcher/angular';
@Component({ standalone: true, imports: [SYMBIOTE_ELEMENTS], template: `<button title="Wi-Fi settings" (press)="onPress()" />`,})export class OpenWifi { onPress(): void { void startActivityAsync(ActivityAction.WIFI_SETTINGS); }}There is no service to inject(): every function is a plain export off the core package.
<script lang="ts"> import { ActivityAction, startActivityAsync } from '@symbiote-native/intent-launcher/svelte';
function onPress(): void { void startActivityAsync(ActivityAction.WIFI_SETTINGS); }</script>
<button title="Wi-Fi settings" onPress={onPress} />import { ActivityAction, startActivityAsync } from '@symbiote-native/intent-launcher/solid';
export function OpenWifi() { return ( <button title="Wi-Fi settings" onPress={() => startActivityAsync(ActivityAction.WIFI_SETTINGS)} /> );}Open another app and read its icon
Section titled “Open another app and read its icon”import { getApplicationIconAsync, openApplication } from '@symbiote-native/intent-launcher';
openApplication('com.google.android.gm');const icon = await getApplicationIconAsync('com.google.android.gm'); // a data:image/png;base64 URIOpen your own app’s settings page
Section titled “Open your own app’s settings page”await startActivityAsync(ActivityAction.APPLICATION_DETAILS_SETTINGS, { data: 'package:com.example.myapp',});Functions
Section titled “Functions”| Signature | Description |
|---|---|
startActivityAsync(activityAction, params?): Promise<IIntentLauncherResult> |
Starts an activity and resolves once the user returns to this app. activityAction is an ActivityAction or any action string |
openApplication(packageName): void |
Opens another app by package name. Fire-and-forget |
getApplicationIconAsync(packageName): Promise<string> |
Resolves another app’s icon as a data:image/png;base64,... URI |
IIntentLauncherParams
Section titled “IIntentLauncherParams”| Field | Type | Description |
|---|---|---|
data |
string | undefined |
URI the intent operates on. Android requires a lowercase scheme |
type |
string | undefined |
MIME type of data. Omit to let Android infer it |
category |
string | undefined |
More detail about the action (Intent.addCategory) |
extra |
Record<string, unknown> | undefined |
Key-value pairs passed with the intent. Keys need a package prefix |
flags |
number | undefined |
Bitmask of intent flags (Intent.setFlags) |
packageName |
string | undefined |
Package of the component that should handle the intent |
className |
string | undefined |
Class name of that component |
IIntentLauncherResult and enums
Section titled “IIntentLauncherResult and enums”| Name | Description |
|---|---|
resultCode |
A ResultCode: Success (-1), Canceled (0) or FirstUser (1, the first custom value) |
data |
Optional data URI the activity returned |
extra |
Optional extras the activity returned |
ActivityAction |
Constants for Android’s own Settings actions, such as WIFI_SETTINGS |
- Every function throws
UnavailabilityErroroff Android. CheckPlatform.OSbefore calling. startActivityAsyncresolves when the user comes back. The result code tells you whether they finished or cancelled; do not assume the setting was changed.extrais typedRecord<string, unknown>. Upstream usesany; the value is forwarded verbatim to the native module.- It can only be verified on an Android device or emulator. The headless tests fake the native
module, so they prove the argument validation and the
UnavailabilityErrorbranches.
Common questions
Section titled “Common questions”- The call rejects with
ActivityNotFoundException. No installed app handles the intent (for example a file type nobody opens). Wrap the call intry/catchand show a fallback. packageNamewithoutclassNamerejects. The intent is then restricted to that package; if the app cannot handle it, the promise rejects.- Crash returning from a notification-settings intent. Reported with
APP_NOTIFICATION_SETTINGSand anextracarrying the package name; test that flow on a device. ERR_UNAVAILABLE. Reported withenableDangerousExperimentalLeanBuilds; Android only, there is no iOS equivalent.
Sources: expo/expo#12078, expo/expo#50511, expo/expo#21876, expo/expo#22995.
How the wrapper works
Section titled “How the wrapper works”expo-intent-launcher’s JS is hand-ported into this package’s core/, resolving the native module
through expo-modules-core rather than the expo meta-package; the native resolution is
Android-only and the base entry is an empty stub. The five adapter entry points are plain
re-exports of core (Angular stays a physical subpath for its separate ngc/AOT build). The
native code is never vendored: expo-modules-autolinking resolves it from node_modules (see
the native setup guide).