npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yemirhan/android-debugger-sdk

v2.0.0

Published

React Native SDK for Android Debugger

Readme

@yemirhan/android-debugger-sdk

React Native SDK for Android Debugger - sends console logs, network requests, and custom events to the desktop debugging tool.

Installation

npm install @yemirhan/android-debugger-sdk
# or
yarn add @yemirhan/android-debugger-sdk
# or
pnpm add @yemirhan/android-debugger-sdk

Quick Start

import { AndroidDebugger } from '@yemirhan/android-debugger-sdk';

// Initialize in your app entry point (App.tsx or index.js)
AndroidDebugger.init();

Note: No network configuration required. The SDK connects to localhost on the device, and the desktop app forwards that port to itself with adb reverse. Just make sure your device is connected via USB or wireless ADB, and selected in Android Debugger.

The SDK never writes its traffic to the app's logs. Your Metro terminal, React Native DevTools console and adb logcat only show what your app logs itself.

Configuration Options

AndroidDebugger.init({
  // Optional: Intercept console.log/warn/error (default: true)
  interceptConsole: true,

  // Optional: Intercept fetch/XMLHttpRequest (default: true)
  interceptNetwork: true,

  // Optional: Intercept WebSocket connections (default: false)
  interceptWebSocket: false,

  // Optional: Messages kept while the desktop app isn't connected (default: 1000)
  maxQueueSize: 1000,

  // Optional: Device port the SDK connects to (default: 8347)
  port: 8347,

  // Optional: 'websocket' (default) or 'logcat' (SDK 1.x transport, see below)
  transport: 'websocket',
});

Features

Automatic Console Capture

All console.log, console.info, console.warn, console.error, and console.debug calls are automatically sent to the desktop app.

console.log('User logged in', { userId: 123 });
console.error('Failed to load data', error);

Automatic Network Capture

All fetch() and XMLHttpRequest calls are automatically captured, including:

  • Request URL, method, headers, body
  • Response status, headers, body
  • Request duration
  • Errors
// Automatically captured
const response = await fetch('https://api.example.com/users');
const data = await response.json();

React Native's own requests to Metro (LogBox symbolication, "open in editor") are not captured, so they don't bury your app's traffic.

Axios Support

For Axios users, you can intercept Axios instances for more reliable request tracking:

import axios from 'axios';
import { AndroidDebugger } from '@yemirhan/android-debugger-sdk';

// Initialize the SDK first
AndroidDebugger.init();

// Create your axios instance
const api = axios.create({
  baseURL: 'https://api.example.com',
});

// Intercept the axios instance
AndroidDebugger.interceptAxios(api);

// All requests through this instance are now tracked
const response = await api.get('/users');

You can intercept multiple axios instances:

const publicApi = axios.create({ baseURL: 'https://public-api.example.com' });
const privateApi = axios.create({ baseURL: 'https://private-api.example.com' });

AndroidDebugger.interceptAxios(publicApi);
AndroidDebugger.interceptAxios(privateApi);

// You can also intercept the global axios instance
import axios from 'axios';
AndroidDebugger.interceptAxios(axios);

The interceptor captures:

  • Request URL (with baseURL resolution)
  • Request method, headers, body
  • Response status, headers, body (including error responses)
  • Request duration
  • Network errors and timeouts

Custom Events

Track custom events with arbitrary data:

// Track a button press
AndroidDebugger.trackEvent('button_press', {
  buttonId: 'submit',
  screen: 'login'
});

// Track a screen view
AndroidDebugger.trackEvent('screen_view', {
  screen: 'HomeScreen'
});

// Track any custom event
AndroidDebugger.trackEvent('purchase_completed', {
  productId: 'abc123',
  price: 9.99
});

State Snapshots

Send snapshots of your app state for debugging:

// Send current user state
AndroidDebugger.sendState('user', {
  id: 123,
  name: 'John',
  isLoggedIn: true,
});

// Send navigation state
AndroidDebugger.sendState('navigation', {
  currentScreen: 'Home',
  history: ['Login', 'Home'],
});

Performance Marks

Measure the duration of operations:

// Start timing
AndroidDebugger.markStart('api_call');

// ... do some work ...
const data = await fetchUserData();

// End timing - automatically sends duration to desktop
AndroidDebugger.markEnd('api_call');

Redux Integration

Use the built-in Redux middleware to automatically track actions and state:

import { createStore, applyMiddleware } from 'redux';
import { AndroidDebugger } from '@yemirhan/android-debugger-sdk';

const store = createStore(
  rootReducer,
  applyMiddleware(
    AndroidDebugger.createReduxMiddleware(),
    // ... other middleware
  )
);

This will automatically:

  • Send every dispatched action as a custom event
  • Send state snapshots after each action

API Reference

AndroidDebugger.init(options)

Initialize the SDK. Call this once at app startup.

AndroidDebugger.destroy()

Disconnect and cleanup. Call this when you want to stop debugging.

AndroidDebugger.destroy();

AndroidDebugger.isReady()

Check if the SDK is initialized and ready to send messages.

if (AndroidDebugger.isReady()) {
  console.log('Debugger is ready');
}

AndroidDebugger.isConnected()

Check if the desktop app is connected and receiving messages. Messages sent while it isn't are queued and delivered when it connects.

AndroidDebugger.onConnectionChange(listener)

Listen for the desktop app connecting or disconnecting. Returns a function that removes the listener. Listeners survive destroy() and init().

const unsubscribe = AndroidDebugger.onConnectionChange((connected) => {
  setDebuggerConnected(connected);
});

AndroidDebugger.onMessage(listener)

Observe every message the SDK captures, inside the app itself, whether or not the desktop app is connected. Each message is a snapshot taken when it was captured. Returns a function that removes the listener. @yemirhan/android-debugger-ui's in-app debugger is built on this.

const unsubscribe = AndroidDebugger.onMessage((message) => {
  if (message.type === 'network') trackSlowRequests(message.payload);
});

AndroidDebugger.trackEvent(name, data?)

Send a custom event.

| Parameter | Type | Description | |-----------|------|-------------| | name | string | Event name | | data | any | Optional event data |

AndroidDebugger.sendState(name, state)

Send a state snapshot.

| Parameter | Type | Description | |-----------|------|-------------| | name | string | State identifier | | state | any | State object |

AndroidDebugger.markStart(name)

Start a performance measurement.

| Parameter | Type | Description | |-----------|------|-------------| | name | string | Measurement name |

AndroidDebugger.markEnd(name)

End a performance measurement and send the result.

| Parameter | Type | Description | |-----------|------|-------------| | name | string | Measurement name (must match markStart) |

AndroidDebugger.interceptAxios(axiosInstance)

Intercept an Axios instance for network request tracking.

| Parameter | Type | Description | |-----------|------|-------------| | axiosInstance | AxiosInstance | The axios instance to intercept |

Returns a function to remove the interceptor:

const removeInterceptor = AndroidDebugger.interceptAxios(api);

// Later, to stop intercepting:
removeInterceptor();

AndroidDebugger.createReduxMiddleware()

Create a Redux middleware for automatic action/state tracking.

How It Works

The SDK opens a WebSocket to ws://localhost:8347 on the device. When you select the device in Android Debugger, the desktop app runs adb reverse tcp:8347 tcp:<port>, so that connection is tunneled through ADB to the desktop app. It's the same mechanism Metro uses.

This means:

  • Clean logs - Nothing the SDK sends shows up in Metro, React Native DevTools or adb logcat
  • No network configuration required - No IP addresses to configure; works over USB, wireless ADB and on emulators
  • No firewall issues - Traffic goes through ADB, not your Wi-Fi network
  • Nothing lost at startup - Messages captured before the desktop app connects are queued (up to maxQueueSize, oldest dropped first) and delivered once it does
  • No size limits - Large responses and state snapshots aren't split into log lines

The SDK retries the connection in the background, so you can start the app and the desktop app in any order.

Release builds

Android blocks cleartext (ws://) traffic in release builds by default. Debug builds of React Native and Expo apps already allow it. If you ship the SDK in a release or staging build, allow cleartext to localhost with a network security config:

<!-- res/xml/network_security_config.xml -->
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="false">localhost</domain>
  </domain-config>
</network-security-config>

Logcat transport (legacy)

SDK 1.x wrote every message to logcat through console.log, which flooded Metro and React Native DevTools. It's still available as transport: 'logcat' for setups where adb reverse can't be used. It has no connection status (isConnected() is always false) and payloads are split into log lines.

Upgrading from 1.x

  • Needs Android Debugger desktop 1.11 or later (older versions only read logcat).
  • Nothing to change in your code. init() options from 1.x work as before.
  • AndroidDebugger.init() no longer logs a startup message.

In-App Debugger

@yemirhan/android-debugger-ui adds a floating button that opens the captured network requests, console output, events and state on the device itself:

import { DebuggerOverlay } from '@yemirhan/android-debugger-ui';

// Next to your root navigator
<DebuggerOverlay />

Troubleshooting

Messages Not Appearing in Desktop App

  1. Check the connection badge - The SDK Data panel shows "App connected" once the app is talking to the desktop app
  2. Check ADB connection - Run adb devices to verify your device is connected, and select it in Android Debugger
  3. Check the port forward - adb reverse --list should show tcp:8347. Android Debugger re-applies it every few seconds while no app is connected
  4. Release builds - Allow cleartext traffic to localhost (see Release builds)
  5. Restart ADB - Try adb kill-server && adb start-server

Console/Network Not Captured

  • Make sure interceptConsole and interceptNetwork are not set to false
  • Initialize the SDK as early as possible in your app lifecycle
  • The SDK must be initialized before the console/network calls you want to capture

Example: Complete Setup

// App.tsx
import React, { useEffect } from 'react';
import { AndroidDebugger } from '@yemirhan/android-debugger-sdk';

// Initialize outside component to run once
if (__DEV__) {
  AndroidDebugger.init();
}

export default function App() {
  useEffect(() => {
    AndroidDebugger.trackEvent('app_started');

    return () => {
      // Cleanup on unmount (optional)
      AndroidDebugger.destroy();
    };
  }, []);

  return (
    // Your app content
  );
}

License

MIT