求助:基于Expo的React Native应用实现短信读取功能
在Expo React Native应用中实现短信读取与监听的可行方案
由于Expo Managed Workflow对原生模块的限制,你尝试的第三方库大多无法直接兼容。下面分两种场景给出可行方案:
一、完整功能实现(需转为Expo Bare Workflow)
如果必须读取历史短信并监听所有新短信,只能转为Bare Workflow,因为Managed模式下没有官方支持的短信读取API。
1. 转Bare Workflow
执行命令完成转换:
expo prebuild
2. 配置权限
在android/app/src/main/AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" />
3. 读取特定号码的历史短信
使用适配RN 0.70+版本的react-native-get-sms-android,先动态申请权限再读取:
import { PermissionsAndroid } from 'react-native'; import SmsAndroid from 'react-native-get-sms-android'; // 请求短信读取权限 const requestSmsPermission = async () => { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.READ_SMS, { title: '短信读取权限', message: '应用需要读取指定号码的短信内容', buttonPositive: '允许', buttonNegative: '取消', }, ); return granted === PermissionsAndroid.RESULTS.GRANTED; }; // 读取指定号码的短信 const fetchTargetSms = async (targetNumber) => { const hasPermission = await requestSmsPermission(); if (!hasPermission) return []; return new Promise((resolve, reject) => { SmsAndroid.list( JSON.stringify({ box: 'inbox', // 读取收件箱 address: targetNumber, // 目标号码 maxCount: 50, // 最多读取50条 }), (err) => reject(err), (count, smsList) => { const parsedSms = JSON.parse(smsList); // 整理短信数据 const formattedSms = parsedSms.map(sms => ({ id: sms._id, address: sms.address, body: sms.body, date: new Date(parseInt(sms.date)), })); resolve(formattedSms); }, ); }); };
4. 监听新短信接收
通过原生事件监听短信广播:
import { NativeEventEmitter, NativeModules } from 'react-native'; const { SmsReceiver } = NativeModules; const smsEventEmitter = new NativeEventEmitter(SmsReceiver); // 启动短信监听 const startSmsListener = (targetNumber, onSmsReceived) => { const subscription = smsEventEmitter.addListener('onSmsReceived', (smsData) => { // 过滤目标号码的短信 if (smsData.address === targetNumber) { onSmsReceived({ address: smsData.address, body: smsData.body, date: new Date(), }); } }); // 触发原生监听逻辑 SmsReceiver.startSmsListener(); // 返回订阅实例,用于组件卸载时取消监听 return subscription; }; // 组件内使用示例 // useEffect(() => { // const sub = startSmsListener('10086', (sms) => { // console.log('收到目标号码短信:', sms); // // 更新应用内短信列表 // }); // return () => sub.remove(); // }, []);
二、验证码场景折中方案(Expo Managed Workflow可用)
如果你的需求仅为验证码自动填充(而非读取所有历史短信),可以使用Expo官方的expo-sms-retriever,无需转Bare:
1. 安装依赖
npx expo install expo-sms-retriever
2. 监听验证码短信
import * as SMSRetriever from 'expo-sms-retriever'; const setupSmsVerification = async () => { try { // 启动短信监听 const isRegistered = await SMSRetriever.startSmsRetriever(); if (!isRegistered) { console.log('短信监听启动失败'); return; } // 监听短信接收事件 const subscription = SMSRetriever.addSmsListener((event) => { // 从短信内容中提取6位验证码(可根据实际格式调整正则) const verificationCode = event.message.match(/\d{6}/)?.[0]; if (verificationCode) { console.log('提取到验证码:', verificationCode); // 自动填充到输入框 } }); // 组件卸载时取消监听 // return () => subscription.remove(); } catch (error) { console.error('验证码监听出错:', error); } };
注意:该方案仅支持符合Google规范的验证码短信(短信需包含应用签名,格式如【你的应用名】验证码123456),且无法读取历史短信。
关键注意事项
- iOS平台:App Store审核严格限制短信读取权限,非验证码场景的权限申请几乎不会通过,仅推荐使用验证码自动填充方案。
- Android平台:从API 29(Android 10)开始,动态申请权限时必须明确说明用途,否则用户可能拒绝授权。
内容的提问来源于stack exchange,提问作者Mohsen Ghadimpour
相关产品推荐
相关产品推荐

