# SDK Installation Complete installation and configuration guides for the Airship React Native module. # Install and Set Up the React Native Module > How to install the Airship React Native module. The Airship React Native module provides a TypeScript-first interface for React Native apps. It wraps the native iOS and Android Airship SDKs, giving you full access to all platform features while maintaining a JavaScript/TypeScript developer experience with strong typing and modern async/await patterns. ## Requirements For supported versions and React Native compatibility, see [Supported Versions](https://github.com/urbanairship/react-native-airship?tab=readme-ov-file#supported-versions). ### iOS * Xcode `15.3+` * minimum deployment target iOS `15+` ### Android * minSdkVersion `23+` * compileSdkVersion `36+` ## Standard React Native Setup Install the plugin using yarn or npm: `yarn add @ua/react-native-airship` ## Expo Setup Apps using Expo's managed workflows can use the `airship-expo-plugin` to configure the project. `expo install airship-expo-plugin` `yarn add @ua/react-native-airship` ### Configure the plugin Add the plugin to the `app.json` with the app's config: ```js "plugins":[ [ "airship-expo-plugin", { "android":{ "icon": "./assets/ic_notification.png", "customNotificationChannels": "./assets/notification_channels.xml", "airshipExtender": "./assets/AirshipExtender.kt" }, "ios":{ "mode": "development", "notificationService": "./assets/NotificationService.swift", "notificationServiceInfo": "./assets/NotificationServiceExtension-Info.plist", "notificationServiceTargetName": "NotificationServiceExtension", "developmentTeamID": "MY_TEAM_ID", "deploymentTarget": "15", "airshipExtender": "./assets/AirshipPluginExtender.swift" } } ] ] ``` Android Config: - icon: Required. Local path to an image to use as the icon for push notifications. 96x96 all-white png with transparency. The name of the icon will be the resource name. - customNotificationChannels: Optional. The local path to a Custom Notification Channels resource file. - airshipExtender: Optional. The local path to a AirshipExtender.kt file. iOS Config: - mode: Required. The APNS entitlement. Either `development` or `production`. - notificationService: Optional. The local path to a custom Notification Service Extension or `DEFAULT_AIRSHIP_SERVICE_EXTENSION` for Airship's default one. - notificationServiceInfo: Optional. Airship will use a default one if not provided. The local path to a Notification Service Extension Info.plist. - notificationServiceTargetName: Optional. Defaults to NotificationServiceExtension if not provided. - developmentTeamID: Optional. The Apple Development Team ID used to configure the Notification Service Extension target. - deploymentTarget: Optional. The minimum Deployment Target version used to configure the Notification Service Extension target. Defaults to iOS 15. - airshipExtender: Optional. The local path to a AirshipPluginExtender.swift file. ## Calling TakeOff `takeOff` should be called in a standard application at the beginning of the lifecycle. Once `takeOff` is called, the config will be stored and applied for future app inits. If `takeOff` is called again with a different config, the new config will not be applied until the next app init. ```ts import Airship from '@ua/react-native-airship'; Airship.takeOff({ default: { appKey: "YOUR_APP_KEY", appSecret: "YOUR_APP_SECRET" }, site: "us", // use "eu" for EU cloud projects urlAllowList: ["*"], android: { notificationConfig: { icon: "ic_notification", accentColor: "#00ff00" } } }); ``` For a complete list of configuration options, see the [AirshipConfig reference](https://www.airship.com/docs/reference/libraries/react-native/latest/interfaces/AirshipConfig.html). ## Test the integration After completing the setup, verify your integration: 1. **Build and run your app** on your iOS or Android device/simulator/emulator. 2. **Check the console output** for Airship channel creation: - **iOS**: Look for a log message in Xcode console: `Channel ID: ` - **Android**: Look for a log message in logcat: `Airship channel created: ` - The channel ID confirms successful SDK initialization. - For more detailed logging, see [Logging](https://www.airship.com/docs/developer/sdk-integration/react-native/installation/logging/). If you see the channel ID in the console and no errors, your integration is successful. ## Next steps - [Advanced Configuration](https://www.airship.com/docs/developer/sdk-integration/react-native/installation/advanced-configuration/): Configure URL allowlists and other advanced settings - [Extending Airship](https://www.airship.com/docs/developer/sdk-integration/react-native/installation/extending-airship/): Access native SDK features for advanced customization - [Push Notifications](https://www.airship.com/docs/developer/sdk-integration/react-native/push-notifications/getting-started/): Configure push notifications - [Deep Links](https://www.airship.com/docs/developer/sdk-integration/react-native/deep-links/): Handle deep links in your app If you don't see a channel ID or encounter errors during initialization, see [Troubleshooting Initialization](https://www.airship.com/docs/developer/sdk-integration/react-native/troubleshooting/initialization/) for common problems and solutions. # Logging > Configure log levels and privacy settings to control how the Airship SDK logs messages. The Airship SDK provides configurable log levels to help you debug issues without overwhelming the console. By default, the log level is set to **Info** for development builds and **Error** for production builds to ensure clean logs in a live environment. ## Log levels The following log levels are available, ordered from most to least verbose. | Log Level | Description | | :-------- | :---------- | | **Verbose** | Reports highly detailed SDK status, which is useful for deep debugging and troubleshooting. | | **Debug** | Reports general SDK status with more detailed information than `Info`. | | **Info** | Reports general SDK status and lifecycle events. | | **Warning** | Used for API deprecations, invalid setup, and other potentially problematic situations that are generally recoverable. | | **Error** | Used for critical errors, exceptions, and other situations that the SDK cannot gracefully handle. | | **None** | Disables all logging. | ## Configuring log levels You can set the log level in the Airship config options that are passed during takeOff. This setting acts as a minimum, and only logs at that level and higher will be logged. ```typescript // Available log levels: verbose, debug, info, warning, none await Airship.takeOff({ default: { logLevel: "verbose" }, ... }); ``` > **Note:** Due to how takeOff caches config, you may need to restart the app after the new takeOff before the log levels take effect. ## Log privacy levels For better security in production environments, you can control the visibility of log contents using privacy levels. This is especially useful when you need to debug a release build without exposing sensitive information. ### private (default) This is the default setting, designed to protect data in a production environment. * **iOS**: Uses `os.Logger` to log all messages at the `private` level. The content of most logs will be redacted and will not be visible in the Console app unless a special profile is installed on the device. * **Android**: Uses the standard `android.util.Log`. In production builds, `verbose` and `debug` messages are completely dropped and will not be logged. ### public This setting increases log visibility, making it easier to capture detailed information from release builds. * **iOS**: All logs are sent to `os.Logger` with a `public` privacy level, preventing their content from being redacted. * **Android & iOS**: To ensure visibility in production builds, `verbose` and `debug` messages are automatically elevated to the `info` log level. ## Setting the privacy level You can set the privacy level in the Airship config options that are passed during takeOff. ```typescript await Airship.takeOff({ default: { logLevel: "verbose", ios: { logPrivacyLevel: "public" }, android: { logPrivacyLevel: "public" } }, ... }); ``` > **Note:** Due to how takeOff caches config, you may need to restart the app after the new takeOff before the log levels take effect. # Locale > Configure locale behavior and override the default locale that Airship uses. The Airship SDK is localized in 48 different languages for all strings included within the SDK. The strings within the app will automatically use the device's or app's configured [Locale](https://www.airship.com/docs/reference/glossary/#locale). Airship uses the user's locale for various locale-sensitive tasks, including selecting the language for messages and reporting for analytics. Apps can override the locale so that Airship uses a different locale than the device's current locale for messaging. ## Overriding the locale You can override the locale programmatically at runtime, which takes precedence over the device's locale settings. ```typescript await Airship.locale.setLocaleOverride("de"); ``` ## Clearing the locale override To remove a locale override and return to using the device's locale: ```typescript await Airship.locale.clearLocaleOverride(); ``` ## Getting the current locale To retrieve the locale that Airship is currently using: ```typescript const locale = await Airship.locale.getCurrentLocale(); ``` # Advanced Configuration > Configure advanced settings like URL allowlists and other options for the Airship React Native module. ## URL Allowlist The URL allowlist controls which URLs the Airship SDK is able to act on. Configure the URL allowlist in your `takeOff` config options using the following properties: - `urlAllowListScopeOpenUrl`: Only URLs allowed for this scope can be opened from an action, displayed in landing page, displayed in an HTML in-app message, or displayed as media in an In-App Automation. Defaults to any Airship-originated URLs and YouTube URLs. - `urlAllowListScopeJavaScriptInterface`: These URLs are checked before the Airship JavaScript interface is injected into the webview. Defaults to any Airship-originated URLs. - `urlAllowList`: Both scopes are applied to these URLs. ```ts Airship.takeOff({ default: { appKey: "YOUR_APP_KEY", appSecret: "YOUR_APP_SECRET" }, site: "us", urlAllowList: ["*"], // Accept all URLs // Or configure specific scopes: urlAllowListScopeOpenUrl: ["https://example.com/*", "https://*.youtube.com/*"], urlAllowListScopeJavaScriptInterface: ["https://example.com/*"] }); ``` **Valid URL pattern syntax** ```text := '*' | '://'/ | '://' | ':/' | ':///' := := '*' | '*.' | := ``` To accept any URL within the SDK, set the `urlAllowList` to `["*"]`. For a complete list of configuration options, see the [AirshipConfig reference](https://www.airship.com/docs/reference/libraries/react-native/latest/interfaces/AirshipConfig.html). # Extend Airship > How to extend the Airship React Native module to access native iOS and Android SDK features not exposed through the React Native API. You can provide a plugin extender that will be automatically loaded for the app. The extender can be used to modify the Airship config before SDK initialization and to access the underlying native SDK once Airship is ready. This gives the app a chance to customize parts of Airship that are not configurable through React Native, such as setting up [iOS Live Activities](https://www.airship.com/docs/developer/sdk-integration/react-native/live-activities/) and [Android Live Updates](https://www.airship.com/docs/developer/sdk-integration/react-native/live-updates/). ## iOS For iOS, create a Swift file named `AirshipPluginExtender.swift` and needs to be included in the main app target. Make sure the class has the `@objc(AirshipPluginExtender)` annotation and inherits `AirshipPluginExtenderProtocol`. ```swift import Foundation import AirshipKit import AirshipFrameworkProxy import ActivityKit @objc(AirshipPluginExtender) public class AirshipPluginExtender: NSObject, AirshipPluginExtenderProtocol { public static func onAirshipReady() { // Called when Airship is ready on the MainActor } public static func extendConfig(config: inout AirshipConfig) { // Called to extend the AirshipConfig before SDK initialization } } ``` ## Android Create a file in the App's src directory named `AirshipExtender`. It needs to extend `com.urbanairship.android.framework.proxy.AirshipPluginExtender` and have an empty constructor. ```kotlin // Replace with your package package com.example import android.content.Context import androidx.annotation.Keep import com.urbanairship.AirshipConfigOptions import com.urbanairship.UAirship import com.urbanairship.android.framework.proxy.AirshipPluginExtender @Keep public final class AirshipExtender: AirshipPluginExtender { override fun onAirshipReady(context: Context, airship: UAirship) { // Called when Airship is ready on a background thread. // Avoid doing long running, blocking work or it will delay Airship } override fun extendConfig( context: Context, configBuilder: AirshipConfigOptions.Builder ): AirshipConfigOptions.Builder { // Called to extend the AirshipConfig before SDK initialization return configBuilder } } ``` Register the extender in the manifest: ```xml ```