我正在尝试通过代码将网络偏好从 3G 切换到 2G/EDGE,反之亦然。我可以打开和关闭移动数据连接。现在我需要知道如何通过代码在 3G 和 2G/EDGE 之间切换,反之亦然。有人可以帮我吗?提前致谢。
最佳答案
我偶然发现了一种通过反射和系统调用命令来解决这个问题的方法,并决定报告它,即使线程很旧并且有一些警告:
大部分代码是从 this answer by ChuongPham 借用/启发的。
首先,我们需要通过获取 ITelephony 类的声明字段的值来获取正确的事务代码。由于我怀疑该字段的名称可能会因平台而略有不同(对于我的字段名称是“TRANSACTION_setPreferredNetworkType_96”),我提供了一个尽可能灵活的解决方案:
private static String get3gTransactionCode(Context context) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final Class<?> mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName());
final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony");
mTelephonyMethod.setAccessible(true);
final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager);
final Class<?> mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName());
final Class<?> mClass = mTelephonyStubClass.getDeclaringClass();
for (Field f:mClass.getDeclaredFields()) {
if (f.getName().contains("setPreferredNetworkType")) {
final Field field = mClass.getDeclaredField(f.getName());
field.setAccessible(true);
return String.valueOf(field.getInt(null));
}
}
throw new NoSuchFieldException();
}
接下来我们可以通过 su 在系统调用中使用事务代码:
private static void setPreferredNetworkType(Context context, int preferredType) throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
String transactionCode = get3gTransactionCode(context);
String command = "service call phone " + transactionCode + " i32 " + preferredType;
executeCommandViaSu(context, "-c", command);
}
就我而言,我调用该方法时,第二个参数为 1 表示 2G,10 表示 3G 偏好。可以在 here 中找到不同网络类型的常量。
为了方便和完整起见,我还将 ChuongPham's answer 中的 executeCommandViaSu 方法复制粘贴到此处:
private static void executeCommandViaSu(Context context, String option, String command) {
boolean success = false;
String su = "su";
for (int i=0; i < 3; i++) {
// Default "su" command executed successfully, then quit.
if (success) {
break;
}
// Else, execute other "su" commands.
if (i == 1) {
su = "/system/xbin/su";
} else if (i == 2) {
su = "/system/bin/su";
}
try {
// Execute command as "su".
Runtime.getRuntime().exec(new String[]{su, option, command});
} catch (IOException e) {
success = false;
// Oops! Cannot execute `su` for some reason.
// Log error here.
} finally {
success = true;
}
}
}
关于android - 如何在 3G 和 2G/EDGE 之间切换?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9061291/