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

如何以编程方式获取Connectivity服务调用所需的服务代码?

解决方案:动态处理USB Tethering开启(适配多Android版本)

你的核心困扰在于不同Android版本下service call connectivity CODE中的硬编码CODE不固定,且之前的反射实现存在错误。下面提供两种更可靠的适配方案:

方案一:正确反射调用IConnectivityManager的setUsbTethering方法

这是最稳定的实现方式,直接通过反射调用系统隐藏接口的方法,完全无需依赖service call的方法序号。

实现步骤

  1. 反射获取ServiceManager类,拿到ConnectivityService的Binder实例;
  2. 反射获取IConnectivityManager.Stub类,将Binder转换为IConnectivityManager接口实例;
  3. 调用接口的setUsbTethering方法(兼容不同版本的参数类型差异)。

示例代码

import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.lang.reflect.Method;

public void enableUsbTethering() {
    try {
        // 1. 获取ServiceManager类,拿到ConnectivityService的Binder
        Class<?> serviceManagerClass = Class.forName("android.os.ServiceManager");
        Method getServiceMethod = serviceManagerClass.getMethod("getService", String.class);
        IBinder connectivityBinder = (IBinder) getServiceMethod.invoke(null, "connectivity");

        // 2. 将Binder转换为IConnectivityManager接口实例
        Class<?> iConnectivityManagerStubClass = Class.forName("android.net.IConnectivityManager$Stub");
        Method asInterfaceMethod = iConnectivityManagerStubClass.getMethod("asInterface", IBinder.class);
        Object iConnectivityManager = asInterfaceMethod.invoke(null, connectivityBinder);

        // 3. 调用setUsbTethering,兼容boolean/int两种参数类型
        Method setUsbTetheringMethod = null;
        try {
            // 优先尝试boolean参数版本
            setUsbTetheringMethod = iConnectivityManager.getClass().getMethod("setUsbTethering", boolean.class);
            setUsbTetheringMethod.invoke(iConnectivityManager, true);
        } catch (NoSuchMethodException e) {
            // 兼容部分版本的int参数(1表示开启)
            setUsbTetheringMethod = iConnectivityManager.getClass().getMethod("setUsbTethering", int.class);
            setUsbTetheringMethod.invoke(iConnectivityManager, 1);
        }

        Toast.makeText(this, "USB Tethering已开启", Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        Log.e("AUTO TETHERING", "开启USB Tethering失败", e);
        Toast.makeText(this, "失败:" + e.getMessage(), Toast.LENGTH_LONG).show();
    }
}

注意事项

  • 该方法需要Root权限或应用拥有系统签名(基础权限android.permission.CHANGE_NETWORK_STATE是前提,但修改USB Tethering通常需要更高权限);
  • 不同Android版本的setUsbTethering参数类型可能不同,代码中已做兼容处理;
  • 系统隐藏API可能在后续版本变更,需针对主流Android版本做测试验证。

方案二:动态获取service call对应的CODE

如果你坚持使用service call命令,可以通过反射获取IConnectivityManager接口中setUsbTethering方法的序号(即CODE值),无需硬编码或盲目遍历。

实现思路

service call的CODE对应AIDL接口中方法的序号(从1开始计数),可以通过反射获取IConnectivityManager.Stub类中的方法索引,转换为对应的CODE。

示例代码

import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public int getUsbTetheringServiceCode() {
    int code = -1;
    try {
        // 获取IConnectivityManager.Stub类
        Class<?> stubClass = Class.forName("android.net.IConnectivityManager$Stub");
        // 获取存储所有AIDL方法的METHODS字段
        Field methodsField = stubClass.getDeclaredField("METHODS");
        methodsField.setAccessible(true);
        Method[] methods = (Method[]) methodsField.get(null);

        // 遍历找到setUsbTethering方法,计算对应的CODE
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            if ("setUsbTethering".equals(method.getName())) {
                // service call的CODE是方法索引+1(AIDL方法序号从1开始)
                code = i + 1;
                break;
            }
        }
    } catch (Exception e) {
        Log.e("AUTO TETHERING", "获取服务CODE失败", e);
    }
    return code;
}

// 使用方式
int code = getUsbTetheringServiceCode();
if (code != -1) {
    String command = "service call connectivity " + code + " i32 1";
    // 以Root权限执行命令
    Runtime.getRuntime().exec(new String[]{"su", "-c", command});
}

注意事项

  • 该方法依赖系统隐藏的IConnectivityManager$Stub.METHODS字段,部分厂商定制系统可能修改此实现;
  • 同样需要Root权限执行service call命令;
  • 若METHODS字段无法获取,可退而求其次通过反射获取方法的transact code,但实现复杂度更高。

你之前反射失败的原因

你之前的代码this.getClass().getMethod("IConnectivityManager.setUsbTethering", Integer.class)存在两个关键错误:

  1. IConnectivityManager.setUsbTethering不是当前Activity类的方法,你需要获取系统的IConnectivityManager接口类,而非当前类;
  2. 参数类型不匹配,多数版本的setUsbTethering参数是boolean而非Integer,且必须通过Stub.asInterface获取接口实例才能调用方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:55:25