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

expo-sms-manager

v1.0.4

Published

Complete SMS management module for React Native/Expo - send, receive, and manage SMS messages

Readme

expo-sms-manager

A comprehensive SMS management module for React Native/Expo that enables sending, receiving, and managing SMS messages directly from your app without opening the default SMS application.

Features

  • Send SMS directly - No need to open the SMS app
  • Receive SMS - Listen for incoming messages in real-time
  • Dual SIM support - Select which SIM to use for sending
  • Signal strength checking - Verify connectivity before sending
  • Delivery tracking - Get sent and delivered confirmations
  • Bulk sending - Send to multiple recipients
  • Long message support - Automatic multipart SMS handling
  • OTP extraction - Built-in utilities for OTP detection
  • Search capabilities - Find messages by sender or content

Platform Support

Android: Full support (API 21+)

Installation

For Managed Expo Projects

npx expo install expo-sms-manager

For Bare React Native Projects

npm install expo-sms-manager

Then run:

npx expo prebuild

Permissions

Add these permissions to your android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />

Quick Start

import * as SmsManager from 'expo-sms-manager';
import { PermissionsAndroid, Platform } from 'react-native';

// Request permissions (Android only)
async function requestSmsPermissions() {
  if (Platform.OS !== 'android') return false;
  
  const granted = await PermissionsAndroid.requestMultiple([
    PermissionsAndroid.PERMISSIONS.SEND_SMS,
    PermissionsAndroid.PERMISSIONS.READ_SMS,
    PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
    PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE,
  ]);
  
  return Object.values(granted).every(
    status => status === PermissionsAndroid.RESULTS.GRANTED
  );
}

// Send an SMS
async function sendMessage() {
  try {
    const result = await SmsManager.sendSms(
      '+1234567890', 
      'Hello from my app!',
      {
        simSlot: 0, // Use first SIM
        requestStatusReport: false, // Don't wait for delivery
        checkSignal: true, // Check signal before sending
      }
    );
    console.log('SMS sent:', result.messageId);
  } catch (error) {
    console.error('Failed to send SMS:', error);
  }
}

// Listen for incoming SMS
SmsManager.addSmsListener((message) => {
  console.log('New SMS from:', message.sender);
  console.log('Message:', message.message);
  
  // Check for OTP
  const otp = SmsManager.extractOtp(message.message);
  if (otp) {
    console.log('OTP detected:', otp);
  }
});

// Start listening for SMS
await SmsManager.startSmsListener();

API Reference

Core Functions

isSupported()

Check if SMS operations are supported on the current platform.

const supported = SmsManager.isSupported(); // true on Android

hasPermissions()

Check if all required SMS permissions are granted.

const hasPerms = SmsManager.hasPermissions();

Sending SMS

sendSms(phoneNumber, message, options?)

Send an SMS message directly without opening the SMS app.

const result = await SmsManager.sendSms('+1234567890', 'Hello!', {
  simSlot: 0,              // SIM slot index (0 or 1)
  requestStatusReport: false, // Request delivery confirmation
  checkSignal: true,       // Check signal before sending
});

Note: Set requestStatusReport: false for immediate response. When set to true, the promise may take longer to resolve as it waits for network confirmation.

sendSmsToMultiple(phoneNumbers, message, options?)

Send SMS to multiple recipients.

const results = await SmsManager.sendSmsToMultiple(
  ['+1234567890', '+0987654321'],
  'Bulk message',
  { simSlot: 0 }
);

sendLongSms(phoneNumber, message, options?)

Send a long SMS that will be automatically split into multiple parts.

const result = await SmsManager.sendLongSms(
  '+1234567890',
  'Very long message that exceeds 160 characters...',
  { simSlot: 0 }
);

SIM Card Management

getAvailableSimCards()

Get information about available SIM cards.

const simCards = SmsManager.getAvailableSimCards();
// Returns: [{ slot: 0, displayName: "SIM 1", carrierName: "Carrier", ... }]

checkSignalStrength(simSlot)

Check signal strength for a specific SIM slot.

const signal = await SmsManager.checkSignalStrength(0);
// Returns: { signalStrength: 3, signalLevel: "good", hasSignal: true }

Receiving SMS

startSmsListener()

Start listening for incoming SMS messages.

await SmsManager.startSmsListener();

stopSmsListener()

Stop listening for incoming SMS messages.

await SmsManager.stopSmsListener();

addSmsListener(callback)

Add a listener for incoming SMS messages.

const subscription = SmsManager.addSmsListener((message) => {
  console.log('New SMS:', message);
});

// Later: remove the listener
subscription.remove();

Reading SMS

getRecentSms(limit)

Get recent SMS messages from the device.

const messages = await SmsManager.getRecentSms(10);

getSmsFromNumber(phoneNumber, limit)

Get SMS messages from a specific phone number.

const messages = await SmsManager.getSmsFromNumber('+1234567890', 10);

findSmsWithText(searchText, limit)

Search for SMS messages containing specific text.

const messages = await SmsManager.findSmsWithText('OTP', 5);

Event Listeners

SMS Events

// SMS received
SmsManager.addSmsListener((message) => {
  console.log('Received:', message);
});

// SMS send progress
SmsManager.addSmsProgressListener((progress) => {
  console.log('Progress:', progress.status);
});

// SMS sent confirmation
SmsManager.addSmsSentListener((event) => {
  console.log('Sent:', event.status);
});

// SMS delivered confirmation
SmsManager.addSmsDeliveredListener((event) => {
  console.log('Delivered:', event.status);
});

// Error events
SmsManager.addErrorListener((error) => {
  console.error('Error:', error.message);
});

Utility Functions

extractOtp(message, length?)

Extract OTP code from a message.

const otp = SmsManager.extractOtp('Your OTP is 123456');
// Returns: "123456"

isValidPhoneNumber(phoneNumber)

Validate phone number format.

const isValid = SmsManager.isValidPhoneNumber('+1234567890');

formatPhoneNumber(phoneNumber, countryCode?)

Format a phone number.

const formatted = SmsManager.formatPhoneNumber('1234567890', '+1');
// Returns: "+11234567890"

Types

interface SmsMessage {
  id?: number;
  sender: string;
  message: string;
  timestamp: number;
  date: string;
  type?: 'received' | 'sent';
}

interface SmsSendOptions {
  simSlot?: number;           // 0 or 1
  requestStatusReport?: boolean;
  checkSignal?: boolean;
  waitForDelivery?: boolean;  // Wait for delivery confirmation
}

interface SmsSendResult {
  messageId: string;
  sent: 'sent' | 'failed' | 'pending';
  delivered?: 'delivered' | 'pending' | 'timeout';
}

interface SimCardInfo {
  slot: number;
  displayName: string;
  carrierName?: string;
  isActive: boolean;
}

Troubleshooting

Loading Spinner Stuck After Sending SMS

If the loading spinner remains after sending an SMS, ensure you're using requestStatusReport: false for immediate response:

const result = await SmsManager.sendSms(phoneNumber, message, {
  requestStatusReport: false, // Immediate response
});

Delivery reports may not always arrive, especially on physical devices.

Permissions Issues

Always request permissions at runtime on Android:

const granted = await PermissionsAndroid.requestMultiple([
  PermissionsAndroid.PERMISSIONS.SEND_SMS,
  PermissionsAndroid.PERMISSIONS.READ_SMS,
  PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
  PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE,
]);

Google Play Store Submission

Apps using SMS permissions may require additional justification during Play Store review. Ensure your app's use case complies with Google's SMS and Call Log Permissions policy.

Example App

See the example app for a complete implementation with UI components.

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

License

MIT

Support

Changelog

Version 1.0.3

  • Initial release with full SMS sending and receiving capabilities
  • Dual SIM support
  • Signal strength checking
  • Delivery tracking
  • OTP extraction utilities

Made with ❤️ for the React Native community