React Native安卓APP实现USSD会话自动交互的Java模块需求
React Native 安卓USSD会话交互模块实现
一、原生Java模块开发
1. 创建USSD处理核心模块
新建USSDModule.java文件,封装USSD指令执行与步骤流转逻辑:
package com.yourprojectname; // 替换为你的项目包名 import android.content.Context; import android.telephony.TelephonyManager; import android.telephony.UssdResponse; import android.util.Log; import androidx.annotation.NonNull; import com.facebook.react.bridge.*; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class USSDModule extends ReactContextBaseJavaModule { private static final String TAG = "USSDModule"; private final Executor executor = Executors.newSingleThreadExecutor(); private TelephonyManager telephonyManager; private AccessibilityServiceHelper accessibilityHelper; public USSDModule(ReactApplicationContext reactContext) { super(reactContext); telephonyManager = (TelephonyManager) reactContext.getSystemService(Context.TELEPHONY_SERVICE); accessibilityHelper = new AccessibilityServiceHelper(reactContext); } @NonNull @Override public String getName() { return "USSDModule"; } @ReactMethod public void interactWithUssd(String shortCode, String stepValues, Promise promise) { String[] steps = stepValues.split("\\*"); executor.execute(() -> { try { telephonyManager.sendUssdRequest(shortCode, new TelephonyManager.UssdResponseCallback() { int currentStep = 0; @Override public void onReceiveUssdResponse(TelephonyManager telephonyManager, String request, UssdResponse response) { super.onReceiveUssdResponse(telephonyManager, request, response); Log.d(TAG, "USSD响应: " + response.getReturnMessage()); if (currentStep < steps.length) { accessibilityHelper.inputAndSend(steps[currentStep]); currentStep++; } else { promise.resolve("USSD会话执行完成"); } } @Override public void onReceiveUssdResponseFailed(TelephonyManager telephonyManager, String request, int failureCode) { super.onReceiveUssdResponseFailed(telephonyManager, request, failureCode); promise.reject("USSD_ERROR", "执行失败,错误码: " + failureCode); } }, executor); } catch (SecurityException e) { promise.reject("PERMISSION_ERROR", "缺少CALL_PHONE权限"); } }); } @ReactMethod public void openAccessibilitySettings() { AccessibilityServiceHelper.openAccessibilitySettings(getReactApplicationContext()); } }
2. 无障碍服务辅助类(自动输入/提交)
新建AccessibilityServiceHelper.java,处理USSD对话框的自动输入与提交:
package com.yourprojectname; // 替换为你的项目包名 import android.content.Context; import android.content.Intent; import android.view.accessibility.AccessibilityNodeInfo; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; public class AccessibilityServiceHelper extends android.accessibilityservice.AccessibilityService { private Context context; public AccessibilityServiceHelper(Context context) { this.context = context; } public void inputAndSend(String input) { AccessibilityNodeInfo rootNode = getRootInActiveWindow(); if (rootNode != null) { findAndFillInput(rootNode, input); } } private void findAndFillInput(AccessibilityNodeInfo node, String input) { if (node.getClassName().equals("android.widget.EditText")) { Bundle args = new Bundle(); args.putCharSequence(AccessibilityNodeInfoCompat.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, input); node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args); findSendButton(node.getParent()); return; } for (int i = 0; i < node.getChildCount(); i++) { AccessibilityNodeInfo child = node.getChild(i); if (child != null) { findAndFillInput(child, input); } } } private void findSendButton(AccessibilityNodeInfo node) { if (node.getClassName().equals("android.widget.Button")) { CharSequence text = node.getText(); if (text != null && (text.equals("发送") || text.equals("OK") || text.equals("Send"))) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK); return; } } for (int i = 0; i < node.getChildCount(); i++) { AccessibilityNodeInfo child = node.getChild(i); if (child != null) { findSendButton(child); } } } @Override public void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent event) {} @Override public void onInterrupt() {} public static void openAccessibilitySettings(Context context) { Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } }
3. 注册原生模块
新建USSDPackage.java,将模块注册到React Native:
package com.yourprojectname; // 替换为你的项目包名 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.ArrayList; import java.util.Collections; import java.util.List; public class USSDPackage implements ReactPackage { @NonNull @Override public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new USSDModule(reactContext)); return modules; } @NonNull @Override public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) { return Collections.emptyList(); } }
最后在MainApplication.java的getPackages()方法中添加模块:
@Override protected List<ReactPackage> getPackages() { List<ReactPackage> packages = new PackageList(this).getPackages(); packages.add(new USSDPackage()); // 注册USSD模块 return packages; }
二、React Native JS层封装与调用
1. 封装JS工具类
创建USSDHelper.js:
import { NativeModules } from 'react-native'; const { USSDModule } = NativeModules; export const interactWithUssd = async (shortCode, stepValues) => { try { await USSDModule.interactWithUssd(shortCode, stepValues); console.log('USSD会话执行完成'); } catch (error) { console.error('USSD执行失败:', error); throw error; } }; export const openAccessibilitySettings = () => { USSDModule.openAccessibilitySettings(); };
2. 业务层调用示例
import { interactWithUssd, openAccessibilitySettings } from './USSDHelper'; // 示例参数 const shortCode = "*144#"; const stepValues = "1*7*1*1225"; // 触发USSD交互 const handleUssd = async () => { try { await interactWithUssd(shortCode, stepValues); } catch (err) { // 处理错误逻辑 } }; // 引导用户开启无障碍服务 const requestAccessPermission = () => { openAccessibilitySettings(); };
三、权限与配置
在AndroidManifest.xml中添加权限与服务声明:
<uses-permission android:name="android.permission.CALL_PHONE" /> <service android:name=".AccessibilityServiceHelper" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service>
在res/xml目录下创建accessibility_service_config.xml:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeWindowStateChanged|typeViewClicked" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canPerformGestures="true" android:canRetrieveWindowContent="true" android:description="@string/accessibility_desc" />
在res/values/strings.xml添加服务描述:
<string name="accessibility_desc">自动处理USSD会话的输入与提交操作</string>
四、关键注意事项
- 版本限制:
sendUssdRequest仅支持Android 8.0(API 26)及以上版本,低版本需用反射兼容。 - 无障碍授权:用户必须手动在系统设置中开启APP的无障碍服务,否则无法自动输入。
- 权限申请:运行时需动态申请
CALL_PHONE权限,否则无法执行USSD指令。 - 兼容性适配:不同运营商的USSD对话框布局可能不同,需根据实际情况调整控件查找逻辑。
内容的提问来源于stack exchange,提问作者Peniel Dialu
相关产品推荐
相关产品推荐

