You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:27:58