diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index b74894b..add2286 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + diff --git a/android/app/src/main/java/com/rnpay/AppUtilsModule.java b/android/app/src/main/java/com/rnpay/AppUtilsModule.java new file mode 100644 index 0000000..558f08c --- /dev/null +++ b/android/app/src/main/java/com/rnpay/AppUtilsModule.java @@ -0,0 +1,39 @@ +package com.rnpay; + +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +import java.util.List; + +public class AppUtilsModule extends ReactContextBaseJavaModule { + + public AppUtilsModule(ReactApplicationContext reactContext) { + super(reactContext); + } + + @NonNull + @Override + public String getName() { + return "AppUtilsModule"; + } + + @ReactMethod + public void isModifiedAppInstalled(String scheme, Promise promise) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(scheme + "://check")); + PackageManager pm = getReactApplicationContext().getPackageManager(); + List list = pm.queryIntentActivities(intent, 0); + promise.resolve(list != null && !list.isEmpty()); + } catch (Exception e) { + promise.reject("CHECK_ERROR", e.getMessage(), e); + } + } +} diff --git a/android/app/src/main/java/com/rnpay/AppUtilsPackage.java b/android/app/src/main/java/com/rnpay/AppUtilsPackage.java new file mode 100644 index 0000000..e55abc0 --- /dev/null +++ b/android/app/src/main/java/com/rnpay/AppUtilsPackage.java @@ -0,0 +1,23 @@ +package com.rnpay; + +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.Arrays; +import java.util.Collections; +import java.util.List; + +public class AppUtilsPackage implements ReactPackage { + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Arrays.asList(new AppUtilsModule(reactContext)); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} diff --git a/android/app/src/main/java/com/rnpay/MainApplication.java b/android/app/src/main/java/com/rnpay/MainApplication.java index 42b602f..cfd08d2 100644 --- a/android/app/src/main/java/com/rnpay/MainApplication.java +++ b/android/app/src/main/java/com/rnpay/MainApplication.java @@ -23,8 +23,7 @@ public class MainApplication extends Application implements ReactApplication { protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); + packages.add(new AppUtilsPackage()); return packages; } diff --git a/res/paytm.png b/res/paytm.png index 1803ce3..6e47285 100644 Binary files a/res/paytm.png and b/res/paytm.png differ diff --git a/screens/HomeScreen.tsx b/screens/HomeScreen.tsx index 7a3d2ca..8c93083 100644 --- a/screens/HomeScreen.tsx +++ b/screens/HomeScreen.tsx @@ -589,14 +589,18 @@ export default class HomeScreen extends Component { - { - const domain = getServerDomain(); - const colonIdx = domain.lastIndexOf(':'); - const host = colonIdx > 0 ? domain.substring(0, colonIdx) : domain; - const port = colonIdx > 0 ? domain.substring(colonIdx + 1) : ''; - this.setState({ showServerSettings: true, settingsHost: host, settingsPort: port }); - }}> - + { + const domain = getServerDomain(); + const colonIdx = domain.lastIndexOf(':'); + const host = colonIdx > 0 ? domain.substring(0, colonIdx) : domain; + const port = colonIdx > 0 ? domain.substring(colonIdx + 1) : ''; + this.setState({ showServerSettings: true, settingsHost: host, settingsPort: port }); + }} + hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }} + style={{ padding: 6 }} + > + this.setState({ showAddWallet: true })} style={s.addBtn}> + Add diff --git a/screens/TestScreen.tsx b/screens/TestScreen.tsx index af96af3..e96822c 100644 --- a/screens/TestScreen.tsx +++ b/screens/TestScreen.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useRef } from 'react'; import { Alert, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { onProxyMessage, proxySendMessage, paytmPay } from 'rnwalletman'; +import { isModifiedAppInstalled } from '../services/appUtils'; export default function TestScreen() { const subRef = useRef | null>(null); @@ -26,6 +27,18 @@ export default function TestScreen() { proxySendMessage({ type: 'echo', messageId: `echo_${Date.now()}`, data: { text: `hello_${Date.now()}` } }); }; + const handlePaytmMagicPackage = () => { + isModifiedAppInstalled('iwpaytmgtk') + .then(installed => Alert.alert('Paytm 魔改包', installed ? '已安装' : '未安装')) + .catch(err => Alert.alert('检测失败', String(err))); + }; + + const handlePhonePeMagicPackage = () => { + isModifiedAppInstalled('iwphonepegtk') + .then(installed => Alert.alert('PhonePe 魔改包', installed ? '已安装' : '未安装')) + .catch(err => Alert.alert('检测失败', String(err))); + }; + return ( 测试工具 @@ -35,6 +48,12 @@ export default function TestScreen() { Echo 测试 + + Paytm 魔改包检测是否安装 + + + PhonePe 魔改包检测是否安装 + ); } diff --git a/servers/walletman b/servers/walletman index 5762feb..82bbbe9 160000 --- a/servers/walletman +++ b/servers/walletman @@ -1 +1 @@ -Subproject commit 5762febe5124fca9b7207545caff7d5f3dfedfde +Subproject commit 82bbbe9a31eff09cc49d2c3228e1bb4e88da3c5c diff --git a/services/appUtils.ts b/services/appUtils.ts new file mode 100644 index 0000000..49e8379 --- /dev/null +++ b/services/appUtils.ts @@ -0,0 +1,8 @@ +import { NativeModules, Platform } from 'react-native'; + +export async function isModifiedAppInstalled(scheme: string): Promise { + if (Platform.OS !== 'android') return false; + const { AppUtilsModule } = NativeModules; + if (!AppUtilsModule) return false; + return await AppUtilsModule.isModifiedAppInstalled(scheme); +}