1. 程式人生 > >React Native實現簡訊轉發到微信上

React Native實現簡訊轉發到微信上

緣由

都說需求來源於生活我為什麼會有一個這麼奇葩的需求呢?來看一個故事。

昨天為了省點手續費導航走了3公里多去找一家工行ATM機(沒辦法窮)然後到了以後發現ATM機在人家的園區裡面,現在疫情進入要通行證,沒辦法一臉的無奈然後又走了2公里找到一個可以用的,結果卡插進去,輸入取款金額後點擊取款,原本以為一切順利,突然螢幕上彈出一個提示該卡種不能做此種交易瞬間懵逼。

然後搜尋發現沒有開通境外取現功能,打電話客服去開通,突然我就意識到我繫結的手機號碼沒帶(萬一要我手機驗證碼怎麼辦)。還好沒要(偷笑)。

天天裝兩個手機在兜裡有點笨重,於是乎就萌生了一個需求能不能把簡訊直接轉發到我主要使用的手機上,開幹。

實現效果圖



進入正題

既然要做簡訊轉發第一時間想到的就是Android(因為Android比較開放什麼都能獲取到不要IOS各種限制),瞭解了一下發現都要用原生程式碼來實現。

畢竟我們是前端就不要用純原生的東西了,之前用Flutter寫過一個小功能還行現在還有100個人左右在用,後面想想還是React比較熟悉,那就用React Native把。

我們首先需要考慮的是簡訊轉發,我們需要先監聽到簡訊的到來,通過我們的伺服器處理。

找到一個這個庫react-native-android-sms-listener可以實現,但是發現有幾個問題。

  1. 退出後臺以後就不在實現監聽了(這要程式一直保持在前臺這肯定不行
    )
  2. 測試過程中發先長簡訊拆分成幾段順序還不一致這樣轉發出效果很差
  3. 沒有簡訊接收時間(雖然可用用當前時間代替)
  4. 我手機上有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;

原始碼

  • 客戶端 提取碼: xtjn
  • 客戶端原始碼
  • 服務端原始碼