Skip to content

rick427/react-native-developer-mode

Repository files navigation

react-native-developer-mode

npm version npm downloads license GitHub stars

TypeScript React Native Java Objective-C++

iOS Android


A simple, lightweight React Native library that detects whether Developer Mode (Android Developer Options / iOS Developer Mode) is active on the device — including real-time detection while the app is running or backgrounded.


Features

  • ✅ Android: Detects Developer Options and USB debugging (ADB)
  • ✅ iOS 16+: Detects Developer Mode via Apple's DeviceCheck framework
  • ✅ Real-time listener — catches users who enable dev mode while the app is open or backgrounded
  • ✅ Zero dependencies
  • ✅ Fully typed (TypeScript)
  • ✅ Promise-based async API

Requirements

Peer dependency Version
react ≥ 18
react-native ≥ 0.71
Platform Minimum version
Android API 16 (Android 4.1)
iOS 12.0 (Developer Mode detection requires iOS 16+)

Installation

npm install @rick427/react-native-developer-mode
# or
yarn add @rick427/react-native-developer-mode

iOS

cd ios && pod install

The podspec declares the DeviceCheck system framework, which is used on iOS 16+ to read DCDevice.developerModeEnabled. No manual Xcode configuration is needed.

Android

No extra steps required — the module is auto-linked.


Usage

One-shot read

Call isDeveloperModeEnabled() once to get the current state — e.g. on app launch.

import { isDeveloperModeEnabled, checkDeveloperMode } from '@rick427/react-native-developer-mode';

// Full result
const result = await isDeveloperModeEnabled();
console.log(result.isDeveloperModeEnabled); // true | false
console.log(result.isAdbEnabled);           // true | false (Android only)

// Boolean shorthand
const isDevMode = await checkDeveloperMode();
console.log(isDevMode); // true | false

Real-time listener

Use addDeveloperModeListener to react the moment a user enables dev mode — even if they do it while the app is backgrounded.

import { useEffect } from 'react';
import { addDeveloperModeListener } from '@rick427/react-native-developer-mode';

function useDevModeGuard() {
  useEffect(() => {
    const subscription = addDeveloperModeListener(({ isDeveloperModeEnabled, isAdbEnabled }) => {
      if (isDeveloperModeEnabled) {
        console.warn('Developer mode was enabled!');
        // e.g. show a warning dialog, log a security event, etc.
      }
      if (isAdbEnabled) {
        console.warn('USB debugging (ADB) was enabled!');
      }
    });

    // Always remove the listener on unmount to avoid memory leaks
    return () => subscription.remove();
  }, []);
}

Complete hook (read + listen)

This pattern gives you the current state on mount and keeps it updated in real time.

import { useState, useEffect } from 'react';
import {
  isDeveloperModeEnabled,
  addDeveloperModeListener,
  type DeveloperModeResult,
} from '@rick427/react-native-developer-mode';

function useDeveloperMode(): DeveloperModeResult {
  const [state, setState] = useState<DeveloperModeResult>({
    isDeveloperModeEnabled: false,
    isAdbEnabled: false,
  });

  useEffect(() => {
    // Read current state on mount
    isDeveloperModeEnabled().then(setState);

    // Subscribe to future changes
    const subscription = addDeveloperModeListener(setState);
    return () => subscription.remove();
  }, []);

  return state;
}

// Usage in a component
function App() {
  const { isDeveloperModeEnabled, isAdbEnabled } = useDeveloperMode();

  if (isDeveloperModeEnabled) {
    return <DeveloperModeWarning />;
  }

  return <MainApp />;
}

API

isDeveloperModeEnabled(): Promise<DeveloperModeResult>

Reads the current developer-mode state once. Returns { isDeveloperModeEnabled: false, isAdbEnabled: false } on unsupported platforms.

checkDeveloperMode(): Promise<boolean>

Convenience helper. Resolves to true if developer mode is active. Equivalent to reading only the isDeveloperModeEnabled field from isDeveloperModeEnabled().

addDeveloperModeListener(callback): EmitterSubscription

Subscribes to real-time developer-mode state changes.

Parameter Type Description
callback (result: DeveloperModeResult) => void Called whenever the state changes

Returns an EmitterSubscription. Call .remove() when done.

DeveloperModeResult

Field Type Description
isDeveloperModeEnabled boolean Whether Developer Options (Android) or Developer Mode (iOS 16+) is enabled
isAdbEnabled boolean Whether USB debugging (ADB) is enabled. Android only — always false on iOS

Platform behaviour

Scenario Android iOS
Dev mode toggled while app is open ✅ Fires instantly ⚠️ Fires on next foreground
Dev mode toggled while app is backgrounded ✅ Fires instantly on toggle ✅ Fires when app foregrounds
App cold-started after dev mode was already on ✅ One-shot read returns true ✅ One-shot read returns true

Android uses a ContentObserver on the system settings database URI. It fires the instant DEVELOPMENT_SETTINGS_ENABLED or ADB_ENABLED changes, regardless of app state. No permissions are required.

iOS has no system-level callback for this setting. The module registers for UIApplicationWillEnterForegroundNotification and re-reads DCDevice.currentDevice.developerModeEnabled each time the app comes to the foreground, emitting only when the value has changed since the last check. On iOS < 16 the value is always false.


Changelog

1.1.0

  • New: addDeveloperModeListener — real-time state changes via ContentObserver (Android) and foreground notification (iOS)

1.0.1

  • Fixed module resolution: main now points to compiled lib/index.js
  • Added CI/CD via GitHub Actions (lint + publish on version tags)

1.0.0

  • Initial release: isDeveloperModeEnabled and checkDeveloperMode

Authors

Richard Njoku Richard Njoku

License

MIT © Richard Njoku

About

A lightweight React Native library to detect if developer mode is enabled on Android and iOS.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors