You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 7.0+ 下如何通过代码调用*#*#4636#*#*等隐秘代码?

解决Android 7.0+触发隐秘代码(如*##4636##*)的问题

我完全懂你的困扰——Android 7.0之后Google大幅收紧了系统权限和隐秘操作的限制,那些五年前的老方案自然就失效了。咱们一步步拆解问题,再给出可行的解决方案:

为什么之前的方法都不行?

先搞清楚底层原因,避免再踩坑:

  • ACTION_DIAL:这个Intent只是帮你把号码填进拨号器,但不会自动触发代码执行。隐秘菜单的触发需要系统拨号应用的内部逻辑响应,单纯填号码没有用,必须模拟用户点击拨号键的动作。
  • SECRET_CODE广播:Android 7.0+彻底限制了这个广播的使用范围,只有拥有系统签名的应用才能发送并触发,普通第三方应用发送这个广播要么直接崩溃,要么毫无反应。
  • tel:##4636## URI:系统会自动过滤掉*#这类非标准电话号码字符,所以最终只会拨出*,根本触达不到隐秘菜单的触发逻辑。

可行解决方案

方案一:借助AccessibilityService模拟用户操作(第三方应用首选)

因为普通应用没有权限直接触发隐秘代码,所以只能通过辅助服务模拟用户在拨号器里输入代码并点击拨号的动作。这是目前第三方应用唯一可行的方法:

  1. 注册AccessibilityService
    AndroidManifest.xml中添加服务声明:

    <service
        android:name=".SecretCodeAccessibilityService"
        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_config" />
    </service>
    
  2. 配置辅助服务参数
    res/xml下创建accessibility_config.xml

    <?xml version="1.0" encoding="utf-8"?>
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityEventTypes="typeWindowStateChanged"
        android:accessibilityFeedbackType="feedbackGeneric"
        android:canRetrieveWindowContent="true"
        android:canPerformGestures="true"
        android:description="@string/accessibility_desc" />
    

    记得在strings.xml里添加对应的描述文本,比如"辅助服务用于自动输入系统隐秘代码"

  3. 实现辅助服务逻辑
    编写SecretCodeAccessibilityService类,监听拨号器打开事件,自动输入代码并触发:

    public class SecretCodeAccessibilityService extends AccessibilityService {
        private static final String SECRET_CODE = "*#*#4636#*#*";
    
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
            if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                return;
            }
    
            // 判断当前打开的是否是系统拨号器界面
            String packageName = event.getPackageName().toString();
            String className = event.getClassName().toString();
            if (packageName.contains("com.android.dialer") || className.contains("Dialer")) {
                AccessibilityNodeInfo rootNode = getRootInActiveWindow();
                if (rootNode == null) return;
    
                // 找到拨号输入框(不同厂商可能需要适配ID)
                List<AccessibilityNodeInfo> inputNodes = rootNode.findAccessibilityNodeInfosByViewId("com.android.dialer:id/digits");
                if (inputNodes.isEmpty()) {
                    // 如果找不到ID,尝试通过文本提示查找
                    inputNodes = rootNode.findAccessibilityNodeInfosByHintText("输入号码");
                }
    
                if (!inputNodes.isEmpty()) {
                    AccessibilityNodeInfo inputNode = inputNodes.get(0);
                    // 输入隐秘代码
                    inputNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT,
                            AccessibilityNodeInfo.obtainArguments(SECRET_CODE));
    
                    // 找到拨号按钮并点击
                    List<AccessibilityNodeInfo> dialButtons = rootNode.findAccessibilityNodeInfosByContentDescription("拨号");
                    if (!dialButtons.isEmpty()) {
                        dialButtons.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }
                rootNode.recycle();
            }
        }
    
        @Override
        public void onInterrupt() {}
    }
    
  4. 在Activity中调用逻辑
    先检查辅助服务是否启用,未启用则引导用户开启,然后打开拨号器:

    private boolean isAccessibilityEnabled() {
        int enabled = Settings.Secure.getInt(getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, 0);
        if (enabled == 0) return false;
    
        String enabledServices = Settings.Secure.getString(getContentResolver(),
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        return enabledServices != null && enabledServices.contains(
                getPackageName() + "/.SecretCodeAccessibilityService");
    }
    
    private void openAccessibilitySettings() {
        Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
        startActivity(intent);
    }
    
    // 触发隐秘代码的入口方法
    public void trigger4636Menu() {
        if (!isAccessibilityEnabled()) {
            Toast.makeText(this, "请先启用辅助服务以完成操作", Toast.LENGTH_LONG).show();
            openAccessibilitySettings();
        } else {
            startActivity(new Intent(Intent.ACTION_DIAL));
        }
    }
    

方案二:系统应用专属——使用SECRET_CODE广播

如果你的应用拥有系统签名(比如是定制ROM的预装应用),可以直接发送广播触发:

Intent secretIntent = new Intent("android.provider.Telephony.SECRET_CODE",
        Uri.parse("android_secret_code://4636"));
sendBroadcast(secretIntent);

但普通第三方应用绝对无法使用这个方法,Android 7.0+已经把这条路彻底封死了。

注意事项

  • 辅助服务必须用户手动启用:这是Android的安全机制,无法绕过,所以一定要给用户清晰的引导。
  • 适配不同厂商拨号器:不同品牌的手机(比如小米、华为)拨号器的View ID可能不同,需要多做适配,比如通过提示文本查找输入框,而不是硬编码ID。
  • 权限声明:确保在Manifest中正确声明BIND_ACCESSIBILITY_SERVICE权限,否则辅助服务无法正常工作。

内容的提问来源于stack exchange,提问作者Alex S

火山引擎 最新活动