What is expo-dev-launcher?
The expo-dev-launcher package is a development tool for Expo applications that allows developers to launch and test their apps in a development environment. It provides functionalities to reload the app, open the developer menu, and handle deep links, among other features.
What are expo-dev-launcher's main functionalities?
Reload the App
This feature allows developers to programmatically reload the application, which is useful for testing changes without manually restarting the app.
import { reloadAsync } from 'expo-dev-launcher';
async function reloadApp() {
await reloadAsync();
}
Open Developer Menu
This feature enables developers to open the developer menu programmatically, providing quick access to development tools and options.
import { openMenu } from 'expo-dev-launcher';
function openDevMenu() {
openMenu();
}
Handle Deep Links
This feature allows the app to handle deep links, making it easier to test and debug deep linking functionality during development.
import { addDeepLinkListener } from 'expo-dev-launcher';
addDeepLinkListener((url) => {
console.log('Deep link received:', url);
});
Other packages similar to expo-dev-launcher
react-native-restart
The react-native-restart package provides a simple way to programmatically restart a React Native application. While it focuses solely on restarting the app, it lacks the broader set of development tools provided by expo-dev-launcher.
react-native-deep-link
The react-native-deep-link package is designed to handle deep linking in React Native applications. It offers similar deep link handling capabilities as expo-dev-launcher but does not include other development tools like reloading the app or opening the developer menu.
react-native-dev-menu
The react-native-dev-menu package allows developers to customize and open the developer menu in React Native applications. It provides similar functionality to the developer menu feature in expo-dev-launcher but does not include other features like reloading the app or handling deep links.
expo-dev-launcher
expo-dev-launcher
is an npm package installable in any Expo or React Native project. Once installed, any Debug builds of your application will gain the ability to load projects from Expo CLI. Release builds of your application will not change other than the addition of a few header files. This package is intended to be included in your project through expo-dev-client
.
⚙️ Installation
Firstly, you need to add the expo-dev-launcher
package to your project.
yarn
yarn add expo-dev-launcher expo-dev-menu-interface
npm
npm install expo-dev-launcher expo-dev-menu-interface
Then you can start to configure the native projects using steps below.
🤖 Android
-
Initialize the DevLauncherController
.
Open your MainApplication.{java|kt}
and add the following lines:
Java
...
import expo.modules.devlauncher.DevLauncherController;
...
public class MainApplication extends Application implements ReactApplication {
...
@Override
public void onCreate() {
super.onCreate();
...
DevLauncherController.initialize(this, mReactNativeHost);
}
}
Kotlin
...
import expo.modules.devlauncher.DevLauncherController;
...
public class MainApplication : Application(), ReactApplication {
...
override public fun onCreate() {
super.onCreate();
...
DevLauncherController.initialize(this, mReactNativeHost);
}
}
-
Wrap the default ReactActivityDelegate
with the one from DevLauncher
.
Open your MainActivity.{java|kt}
and add the following lines:
Java
...
import expo.modules.devlauncher.DevLauncherController;
...
public class MainActivity extends DevMenuAwareReactActivity {
...
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return DevLauncherController.wrapReactActivityDelegate(
this,
() -> new ReactActivityDelegate(this, getMainComponentName())
);
}
}
Kotlin
...
import expo.modules.devlauncher.DevLauncherController;
...
public class MainActivity : DevMenuAwareReactActivity() {
...
protected override fun ReactActivityDelegate createReactActivityDelegate(): ReactActivityDelegate {
return DevLauncherController.wrapReactActivityDelegate(this) {
ReactActivityDelegate(this, getMainComponentName())
});
}
}
-
Pass new intents to the DevLauncherController
.
Note: This step is not required but without it, deep-link handling won't work.
Open your MainActivity.{java|kt}
and add the following method:
Java
...
public class MainActivity extends DevMenuAwareReactActivity {
...
@Override
public void onNewIntent(Intent intent) {
if (DevLauncherController.tryToHandleIntent(this, intent)) {
return;
}
super.onNewIntent(intent);
}
}
Kotlin
...
public class MainActivity : DevMenuAwareReactActivity() {
...
public override fun onNewIntent(intent: Intent) {
if (DevLauncherController.tryToHandleIntent(this, intent)) {
return;
}
super.onNewIntent(intent);
}
}
🍏 iOS
-
Run npx pod-install
after installing the npm package.
-
Set up the EXDevLauncherControllerDelegate
.
Objective-C
Open your AppDelegate.h
and implement EXDevLauncherControllerDelegate
.
...
#import <EXDevLauncherController.h>
...
@interface AppDelegate : UMAppDelegateWrapper <RCTBridgeDelegate, EXDevLauncherControllerDelegate> // Here you're implementing the `EXDevLauncherControllerDelegate`
@end
Open your AppDelegate.m
and add the following method:
...
@implementation AppDelegate
...
- (void)developmentClientController:(EXDevLauncherController * )devLauncherController
didStartWithSuccess:(BOOL)success
{
devLauncherController.appBridge = [self initializeReactNativeApp];
}
...
@end
Swift
Open your AppDelegate.swift
and implement EXDevLauncherControllerDelegate
.
...
@UIApplicationMain
class AppDelegate: UMAppDelegateWrapper, EXDevLauncherControllerDelegate {
...
func developmentClientController(_ devLauncherController: EXDevLauncherController!, didStartWithSuccess success: Bool) {
devLauncherController.appBridge = initializeReactNativeBridge()
}
...
}
-
Start the EXDevLauncherController
.
Open your AppDelegate.{m|swift}
and add the following lines:
Objective-C
@implementation AppDelegate
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
EXDevLauncherController *controller = [EXDevLauncherController sharedInstance];
[controller startWithWindow:self.window delegate:self launchOptions:launchOptions];
}
...
@end
Swift
...
@UIApplicationMain
class AppDelegate: UMAppDelegateWrapper {
...
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let controller = EXDevLauncherController.sharedInstance()
controller?.start(with: window, delegate: self, launchOptions: launchOptions);
}
...
}
-
Change the source URL.
Open your AppDelegate.{m|swift}
and add the following lines:
Objective-C
...
@implementation AppDelegate
...
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
{
return [[EXDevLauncherController sharedInstance] sourceUrl];
}
...
@end
Swift
...
@UIApplicationMain
class AppDelegate: UMAppDelegateWrapper {
...
func sourceURL(for bridge: RCTBridge!) -> URL! {
return EXDevLauncherController.sharedInstance()?.sourceUrl()
}
...
}
-
Handle deep links.
Open your AppDelegate.{m|swift}
and add the following lines:
Objective-C
...
#import <React/RCTLinkingManager.h>
...
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
if ([EXDevLauncherController.sharedInstance onDeepLink:url options:options]) {
return true;
}
return [RCTLinkingManager application:application openURL:url options:options];
}
...
@end
Swift
...
class AppDelegate: UMAppDelegateWrapper {
...
func initializeReactNativeBridge() -> RCTBridge? {
if let bridge = RCTBridge(delegate: self, launchOptions: EXDevelopmentClientController.sharedInstance()!.getLaunchOptions()) {
...
}
}
...
override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if (useDevClient && EXDevLauncherController.sharedInstance()!.onDeepLink(url, options: options)) {
return true;
}
return RCTLinkingManager.application(app, open: url, options: options)
}
...
}