Listen to incoming SMS from React Native App using React Native Bridge
What is a bridge in React Native?
In React Native, a “bridge” typically refers to the communication mechanism that allows JavaScript code to interact with native code in order to leverage native functionality and components. React Native is a framework for building mobile applications using JavaScript and React, and it enables you to write most of your application logic in JavaScript while still having access to native APIs and components.
The bridge in React Native serves as a way to bridge the gap between JavaScript code running in a JavaScript virtual machine (typically JavaScriptCore) and the native code written in languages like Java, Objective-C that runs on the mobile device’s operating system.
Listen to incoming SMS from React Native
In this example, we will write some native Java code to listen to the incoming SMS from your Android App and will trigger the same from React Native.
1. Create a SMS Listener Native Module
To get started, Create a java class SmsListenerModule.java that extends inside android/app/src/main/java/com/your-app-name/. Then add the following content:
package com.your-app-name; // Replace it with your app-name
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsMessage;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
public class SmsListenerModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
public SmsListenerModule(ReactApplicationContext context) {
super(context);
this.reactContext = context;
registerSMSReceiver();
}
@Override
public String getName() {
return "SmsListenerModule";
}
private void sendEvent(String eventName, String message) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, message);
}
private void registerSMSReceiver() {
BroadcastReceiver smsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
Object[] pdus = (Object[]) extras.get("pdus");
for (Object pdu : pdus) {
SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdu);
String messageBody = sms.getMessageBody();
String senderPhoneNumber = sms.getOriginatingAddress();
long timestamp = sms.getTimestampMillis();
WritableMap params = Arguments.createMap();
params.putString("messageBody", messageBody);
params.putString("senderPhoneNumber", senderPhoneNumber);
params.putDouble("timestamp", (double) timestamp);
String jsonString = params.toString();
sendEvent("onSMSReceived", jsonString);
}
}
}
};
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
this.reactContext.registerReceiver(smsReceiver, filter);
}
@ReactMethod
public void startListeningToSMS() {
registerSMSReceiver();
}
}
2. Register the Module (Android Specific)
Your native module needs to be included in a ReactPackage class. This package is like a container that holds one or more native modules. You create a class that implements the ReactPackage interface and add your native module(s) to it. After creating your package, you have to register it with React Native. During React Native’s initialisation, it loops through all registered packages, and for each package, it takes all the native modules within it and makes them available for your JavaScript code.
To add your Native Module to ReactPackage, first create a new Java/Kotlin Class named SmsListenerPackage.java that implements ReactPackage inside the android/app/src/main/java/com/your-app-name/ folder:
Then add the following content:
package com.your-app-name; // replace it with your app-name;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SmsListenerPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new SmsListenerModule(reactContext));
return modules;
}
}
3. Register SmsListenerPackage in MainApplication.java
In your MainApplication.java file, import the SmsListenerPackage at the top of the file along with other import statements. Locate the getPackages method within your MainApplication class and add an instance of SmsListenerPackage to the list of packages returned:
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
packages.add(new SmsListenerPackage());
return packages;
}
4. Add Permissions to AndroidManifest.xml:
To access SMS functionality, you need to add the following permissions to your AndroidManifest.xml file:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
5. Handle SMS Data in React Native
In the provided code snippet, we start by importing the necessary dependencies, including the NativeModules object, which allows us to access native modules. To listen for incoming SMS events, the code subscribes to the ‘onSMSReceived’ event using DeviceEmitter. When a new SMS message is received, the event handler extracts the message content.
import React, {useEffect, useState} from 'react';
import {
SafeAreaView,
View,
Text,
NativeModules,
PermissionsAndroid,
Alert,
DeviceEventEmitter,
} from 'react-native';
const App = () => {
const [receiveSmsPermission, setReceiveSmsPermission] = useState('');
const requestSmsPermission = async () => {
try {
const permission = await PermissionsAndroid
.request(PermissionsAndroid.PERMISSIONS.RECEIVE_SMS);
setReceiveSmsPermission(permission);
} catch (err) {
console.log(err);
}
};
useEffect(() => {
requestSmsPermission();
}, []);
useEffect(() => {
if (receiveSmsPermission === PermissionsAndroid.RESULTS.GRANTED) {
let subscriber = DeviceEventEmitter.addListener(
'onSMSReceived',
message => {
const {messageBody, senderPhoneNumber } = JSON.parse(message);
Alert.alert(
'SMS received',
`Message Body: ${messageBody} & sender number: ${senderPhoneNumber}`,
);
},
);
return () => {
subscriber.remove();
};
}
}, [receiveSmsPermission]);
return (
<SafeAreaView style={styles.container}>
<View style={styles.container}>
<Text style={styles.titleText}>
Listen to incoming SMS from React Native App
using React Native Bridge
</Text>
</View>
</SafeAreaView>
);
};
export default App;
Test what you have built!
Launch the Android emulator on your development environment. Access the extended controls panel provided by the emulator. This can usually be accessed via the emulator menu or a keyboard shortcut. Send the SMS message from the extended controls. Verify that an alert or notification appears on the emulator’s screen containing the content of the received message as shown in the below image. If available, you can also verify the SMS reception on a physical Android device.
I hope this journey into the world of React Native bridges has been both enlightening and inspiring. Keep pushing the boundaries of what’s possible, and may your mobile applications continue to captivate and impress.
Also If you like my content and want to support my work, you can give me a cup of coffee! ☕️
Happy coding!
AJAY T S