Skip to content

Application

@symbiote-native/application wraps expo-application — native app version/build/name/ID, the Android ID, install-referrer and install/update-time lookups, and the iOS vendor ID / release type / push-notification-service environment — so every SymbioteNative adapter can read it. Like local auth (and unlike sensorsEventEmitter + live-subscription surface), everything here is either a plain constant resolved once at import time or a one-shot async call with no per-instance state.

OS platform Support
iOS ✅ live
Android ✅ live
Framework adapter Support
React ✅ live
Vue ✅ live
Angular ✅ live
Svelte ✅ live
Terminal window
pnpm add @symbiote-native/application

expo-application 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 app-level permission strings are needed — every function here reads app/device metadata that carries no runtime or manifest permission.

All four adapters — React, Vue, Angular, Svelte — re-export the exact same constants and free functions; there is no per-adapter hook/composable/service to reach for, since nothing here holds live state or a subscription.

import { useEffect, useState } from 'react';
import { Platform, Text, View } from '@symbiote-native/react';
import {
applicationId,
applicationName,
getInstallationTimeAsync,
nativeApplicationVersion,
nativeBuildVersion,
} from '@symbiote-native/application/react';
export default function ApplicationInfo() {
const [installedAt, setInstalledAt] = useState<Date | null>(null);
useEffect(() => {
getInstallationTimeAsync().then(setInstalledAt);
}, []);
return (
<View>
<Text>{applicationName} ({applicationId})</Text>
<Text>v{nativeApplicationVersion} (build {nativeBuildVersion})</Text>
{Platform.OS === 'android' && installedAt && (
<Text>Installed {installedAt.toLocaleDateString()}</Text>
)}
</View>
);
}

Resolved once, eagerly, at import time:

Field Type Description
nativeApplicationVersion string | null Human-readable app version, e.g. "2.11.0"
nativeBuildVersion string | null Internal build version app stores use to distinguish binaries, e.g. "114"
applicationName string | null The app’s home-screen display name
applicationId string | null The Android application ID or iOS bundle ID
Signature Description
getAndroidId(): string The value of Settings.Secure.ANDROID_ID — a hex string unique per app-signing-key/user/device combination. Throws immediately if called off Android, without touching the native module. @platform android
getInstallReferrerAsync(): Promise<string> The Google Play Install Referrer URL, e.g. "utm_source=google-play&utm_medium=organic". @platform android
getIosIdForVendorAsync(): Promise<string | null> The iOS “identifier for vendor” (IDFV); may resolve null shortly after a device restart before the device is unlocked. @platform ios
getIosApplicationReleaseTypeAsync(): Promise<ApplicationReleaseType> The iOS release channel the app was built for. @platform ios
getIosPushNotificationServiceEnvironmentAsync(): Promise<PushNotificationServiceEnvironment> 'development', 'production', or null on the simulator (which doesn’t support APN registration). @platform ios
getInstallationTimeAsync(): Promise<Date> When the app was first installed (a reinstall after uninstalling resets this)
getLastUpdateTimeAsync(): Promise<Date> When the app was last updated via the Google Play Store. @platform android
Field Value Description
UNKNOWN 0 Release type could not be determined
SIMULATOR 1 Running on the iOS Simulator
ENTERPRISE 2 An enterprise-distributed build
DEVELOPMENT 3 A development build
AD_HOC 4 An ad-hoc distributed build
APP_STORE 5 Distributed via the App Store

A plain string-literal union, not a struct — carries no I prefix (ts-js-best-practices): 'development' | 'production' | null, mapping to the aps-environment entitlement key.

@symbiote-native/application ships zero React/Vue/Angular logic in expo-application itself — its constants and functions are hand-ported, verbatim, into this package’s own core/, resolving the native module through expo-modules-core’s requireNativeModule rather than the expo meta-package this project never installs:

packages/application/src/
├── core/ # framework-agnostic: every constant + function above, ApplicationReleaseType,
│ # PushNotificationServiceEnvironment; native-module.ts resolves the native module
│ # via expo-modules-core's requireNativeModule
├── react/ # @symbiote-native/application/react — export * from '../core'
├── vue/ # @symbiote-native/application/vue — export * from '../core'
├── svelte/ # @symbiote-native/application/svelte — export * from '../core'
└── angular/ # @symbiote-native/application/angular — export * from '../core'

Same shape as local auth’s three adapter entries: single-file re-exports with no lifecycle code at all, since every export here is either an eagerly-resolved constant or a stateless one-shot call — there is nothing for a hook, composable, or service to subscribe to or clean up. The native code itself is never vendored or copied — expo-modules-autolinking resolves it straight out of node_modules (see the native setup guide).