diff --git a/App.tsx b/App.tsx index 4da9053..b302b7a 100644 --- a/App.tsx +++ b/App.tsx @@ -1,5 +1,6 @@ import React, { Component } from "react"; -import { Alert, Modal, StyleSheet, Text, TouchableOpacity, View } from "react-native"; +import { Alert, AppState, AppStateStatus, Modal, StyleSheet, Text, TouchableOpacity, View } from "react-native"; +import DeviceInfo from 'react-native-device-info'; import { PaytmBusinessBind, PhonePeBusinessBind, @@ -33,7 +34,7 @@ import { PhonePePersonalBind, SmsMessage, NotificationMessage, - TcpProxy, + proxyManager, } from "rnwalletman"; import BarcodeScanning from '@react-native-ml-kit/barcode-scanning'; @@ -43,7 +44,7 @@ interface AppProps { } -interface AppState { +interface WalletmanAppState { showPaytmBusinessBind: boolean; showPaytmPersonalBind: boolean; showPhonePePersonalBind: boolean; @@ -99,10 +100,8 @@ const styles = StyleSheet.create({ class Api { - public static readonly BASE_URL = 'http://192.168.1.111:16000'; + public static readonly BASE_URL = 'http://192.168.1.117:16000'; private static _instance: Api | null = null; - private ws: WebSocket | null = null; - private clientId: string = ''; private userId: number = 0; private constructor() { @@ -123,43 +122,6 @@ class Api { return Api._instance; } - public setWebSocket(ws: WebSocket, clientId: string) { - this.ws = ws; - this.clientId = clientId; - ws.onmessage = (event) => { - try { - const msg = JSON.parse(event.data); - if (msg.type === 'proxyRequest') { - const { host, port } = msg.data; - TcpProxy.createProxy( - msg.messageId, - host, - port, - (data: string) => { - ws.send(JSON.stringify({ type: 'proxyData', messageId: msg.messageId, data: { data } })); - }, - () => { ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); }, - () => { ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); } - ).then(success => { - if (success) ws.send(JSON.stringify({ type: 'proxyReady', messageId: msg.messageId })); - }).catch(() => { - ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); - }); - } - if (msg.type === 'proxyData' && msg.data?.data) { - TcpProxy.writeProxy(msg.messageId, msg.data.data).catch(() => { - ws.send(JSON.stringify({ type: 'proxyClose', messageId: msg.messageId })); - }); - } - if (msg.type === 'proxyClose') { - TcpProxy.closeProxy(msg.messageId).catch(() => {}); - } - } catch (e) { - console.error('[API]', e, event.data); - } - }; - } - private headers(): Record { const h: Record = { 'Content-Type': 'application/json' }; if (this.userId) h['X-User-ID'] = String(this.userId); @@ -213,10 +175,11 @@ class Api { } -export default class App extends Component { +export default class App extends Component { private deviceId: string; private tuneUserId: string; - private clientId: string; + private clientId: string = ''; + private appStateSubscription?: any; constructor(props: AppProps) { super(props); @@ -234,10 +197,20 @@ export default class App extends Component { // 临时使用测试成功的固定 ID this.deviceId = 'B6C1AB6DA4B659C287EA76AA96EC154B80E8D28D'; this.tuneUserId = 'b5bfa7df-e571-4ac8-bb51-90afc05d1d59'; - this.clientId = `android_${Date.now()}`; } async componentDidMount() { + /* 获取真实 Android ID */ + try { + this.clientId = await DeviceInfo.getAndroidId(); + console.log('[设备ID]', this.clientId); + } catch (error) { + this.clientId = `android_${Date.now()}`; + console.warn('[设备ID] 获取失败,使用随机ID:', this.clientId); + } + /* 监听应用状态 */ + this.appStateSubscription = AppState.addEventListener('change', this.handleAppStateChange); + /* 登录获取 userId */ try { await Api.instance.login('test123', '123456'); @@ -308,78 +281,75 @@ export default class App extends Component { * 初始化代理客户端 */ async initProxyClient() { - try { - const serverUrl = `ws://${Api.BASE_URL.replace('http://', '')}/ws`; - console.log(`[WebSocket] 连接服务器: ${serverUrl}, 客户端ID: ${this.clientId}`); - - // 创建WebSocket连接 - const ws = new WebSocket(serverUrl); - - ws.onopen = () => { - console.log('[WebSocket] ✅ 已连接'); - + const wsUrl = `ws://${Api.BASE_URL.replace('http://', '')}/ws`; + + proxyManager.start({ + wsUrl, + clientId: this.clientId, + userId: Api.instance.getUserId(), + debug: true, + onConnected: () => { + console.log('[代理] ✅ 已连接'); + }, + onDisconnected: () => { + console.log('[代理] ❌ 已断开'); + }, + onError: (error) => { + console.error('[代理] 错误:', error); + }, + // 自定义注册逻辑(可选) + onRegister: (ws, clientId, userId) => { + // 可以在这里自定义发送的注册消息 ws.send(JSON.stringify({ type: 'register', - clientId: this.clientId, + clientId, messageId: 'register_' + Date.now(), - data: { userId: Api.instance.getUserId() } - })); - Api.instance.setWebSocket(ws, this.clientId); - - // 启动心跳 - this.startHeartbeat(ws); - }; - - ws.onerror = (error) => { - console.error('[WebSocket] 错误:', error); - }; - - ws.onclose = () => { - console.log('[WebSocket] 连接关闭'); - this.stopHeartbeat(); - // 3秒后重连 - setTimeout(() => this.initProxyClient(), 3000); - }; - } catch (error) { - console.error('[WebSocket] 连接失败:', error); - } - } - - /** - * 启动心跳 - */ - startHeartbeat(ws: WebSocket) { - this.stopHeartbeat(); - - this.wsHeartbeatTimer = setInterval(() => { - if (ws.readyState === WebSocket.OPEN) { - ws.send(JSON.stringify({ - type: 'ping', - messageId: 'ping_' + Date.now(), - clientId: this.clientId + data: { + userId, + // 可以添加额外参数 + deviceInfo: { + platform: 'android', + version: '1.0.0' + } + } })); } - }, 20000); // 每20秒发送一次心跳 + }).catch(err => { + console.error('[代理] 启动失败:', err); + }); } /** - * 停止心跳 + * 停止代理客户端 */ - stopHeartbeat() { - if (this.wsHeartbeatTimer) { - clearInterval(this.wsHeartbeatTimer); - this.wsHeartbeatTimer = undefined; - } + stopProxyClient() { + proxyManager.stop(); } componentWillUnmount(): void { - // 停止心跳 - this.stopHeartbeat(); + // 清理应用状态监听 + this.appStateSubscription?.remove(); + + // 停止代理 + this.stopProxyClient(); stopSmsListener(); stopNotificationListener(); } + /** + * 处理应用状态变化 + */ + handleAppStateChange = (nextAppState: AppStateStatus) => { + if (nextAppState === 'background' || nextAppState === 'inactive') { + console.log('[AppState] 应用进入后台,关闭代理'); + this.stopProxyClient(); + } else if (nextAppState === 'active') { + console.log('[AppState] 应用回到前台,重连代理'); + this.initProxyClient(); + } + } + decodeQRFromUrl = async (url: string) => { const localPath = `${RNFS.CachesDirectoryPath}/temp_qr_${Date.now()}.jpg`; diff --git a/android/.idea/gradle.xml b/android/.idea/gradle.xml index b215a9d..d8b3189 100644 --- a/android/.idea/gradle.xml +++ b/android/.idea/gradle.xml @@ -25,6 +25,7 @@