緣由
都說需求來源於生活我為什么會有一個這么奇葩的需求呢?來看一個故事。
昨天為了省點手續費導航走了3公里多去找一家工行ATM機(沒辦法窮)然后到了以后發現ATM機在人家的園區里面,現在疫情進入要通行證,沒辦法一臉的無奈然后又走了2公里找到一個可以用的,結果卡插進去,輸入取款金額后點擊取款,原本以為一切順利,突然屏幕上彈出一個提示該卡種不能做此種交易瞬間懵逼。

然后搜索發現沒有開通境外取現功能,打電話客服去開通,突然我就意識到我綁定的手機號碼沒帶(萬一要我手機驗證碼怎么辦)。還好沒要(偷笑)。
天天裝兩個手機在兜里有點笨重,於是乎就萌生了一個需求能不能把短信直接轉發到我主要使用的手機上,開干。
實現效果圖



進入正題
既然要做短信轉發第一時間想到的就是Android(因為Android比較開放什么都能獲取到不要IOS各種限制),了解了一下發現都要用原生代碼來實現。
畢竟我們是前端就不要用純原生的東西了,之前用Flutter寫過一個小功能還行現在還有100個人左右在用,后面想想還是React比較熟悉,那就用React Native把。
我們首先需要考慮的是短信轉發,我們需要先監聽到短信的到來,通過我們的服務器處理。
找到一個這個庫react-native-android-sms-listener可以實現,但是發現有幾個問題。
- 退出后台以后就不在實現監聽了(
這要程序一直保持在前台這肯定不行) - 測試過程中發先長短信拆分成幾段順序還不一致這樣轉發出效果很差
- 沒有短信接收時間(
雖然可用用當前時間代替) - 我手機上有
2張卡不知道是哪張卡來的短信
自己改了改大概實現了這些功能react-native-android-sms-listener2感興趣的朋友可以去看看主要是這個文件SmsReceiver.java。
客戶端主要實現邏輯就是通過設備Id去看有沒有綁定微信,沒有則出現二維碼綁定。
import React, {useState, useEffect} from 'react';
import {StyleSheet, View, Text, PermissionsAndroid} from 'react-native';
import SmsListener from 'react-native-android-sms-listener2';
import {getUniqueId} from 'react-native-device-info';
import QRCode from 'react-native-qrcode-svg';
import axios from 'axios';
axios.defaults.baseURL = 'https://service.wx.hengkx.com';
axios.interceptors.response.use(
response => response.data,
error => Promise.reject(error.response.data),
);
async function requestReadSmsPermission() {
try {
var granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_SMS,
{
title: '閱讀短信',
message: '需要獲取閱讀短信權限',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECEIVE_SMS,
{
title: '接收短信',
message: '需要獲取接收短信權限',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('RECEIVE_SMS permissions granted', granted);
} else {
console.log('RECEIVE_SMS permissions denied');
}
} else {
console.log('sms read permissions denied');
}
} catch (err) {
console.log(err);
}
}
const App: () => React$Node = () => {
const [url, setUrl] = useState();
const [openId, setOpenId] = useState();
useEffect(() => {
requestReadSmsPermission();
axios
.get('/api/account/info', {params: {deviceId: getUniqueId()}})
.then(res => {
if (res.code === 0) {
if (res.data.url) {
setUrl(res.data.url);
const interval = setInterval(async () => {
const {data} = await axios.get('/api/account/check', {
params: {deviceId: getUniqueId()},
});
if (data) {
setUrl();
setOpenId(data.openId);
clearInterval(interval);
}
}, 1000);
} else {
setOpenId(res.data.openId);
}
}
});
SmsListener.addListener(message => {
if (openId) {
axios.post('/api/sms/receive', {
...message,
openId,
tel: message.originatingAddress,
content: message.body,
});
}
});
}, [openId, setUrl]);
return (
<>
<View style={styles.qrCodeContainer}>
{url && (
<>
<QRCode value={url} size={200} bgColor="purple" fgColor="white" />
<Text style={styles.qrCodeTip}>微信掃描二維碼綁定</Text>
</>
)}
{openId && <Text>已為您自動開啟短信轉發</Text>}
</View>
</>
);
};
const styles = StyleSheet.create({
qrCodeContainer: {
flexDirection: 'column',
alignItems: 'center',
flex: 1,
justifyContent: 'center',
},
qrCodeTip: {
marginTop: 10,
},
});
export default App;
