java Android源码中如何访问setPreferredNetworkType
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5436251/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to access setPreferredNetworkType in Android source
提问by snakeman
I have a question for you, I am trying to select the Preferred Network Type on my Android phone. As you can do by doing following steps:
我有一个问题要问您,我正在尝试在我的 Android 手机上选择首选网络类型。正如您可以通过执行以下步骤:
- Dial ##4636##
- Choose "Phone Information"
- Go bottom
- Choose preferred Network Type on menu
- 拨##4636# #
- 选择“电话信息”
- 去底部
- 在菜单上选择首选网络类型
So after some searches on the source code I found the right class: Phone.java in (\frameworks\base\telephony\java\com\android\internal\telephony)
因此,在对源代码进行一些搜索后,我找到了正确的类:Phone.java in (\frameworks\base\telephony\java\com\android\internal\telephony)
So with the nice tips of Vinay: How to disable Mobile Data on AndroidWho is using java reflexion to acces to hidden classes, I tried too by doing:
所以有了Vinay的好提示:How to disable Mobile Data on Androidwho is using java reflexion to access to hidden classes,我也尝试了这样做:
Method setPrefNetmethod;
Class telephonyManagerClass;
Object ITelephonyStub;
Class ITelephonyClass;
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());
Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");
getITelephonyMethod.setAccessible(true);
ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);
ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());
setPrefNetmethod = ITelephonyClass.getDeclaredMethod("setPreferredNetworkType",new Class[] { Integer.class, Message.class });
Message response = Message.obtain();
setPrefNetmethod.setAccessible(false);
setPrefNetmethod.invoke(ITelephonyStub, new Object[] { network_mode, response });
But the problem is that I have this error on DDMS:
但问题是我在 DDMS 上有这个错误:
03-25 18:18:45.937: WARN/System.err(2989): java.lang.NoSuchMethodException: setPreferredNetworkType 03-25 18:18:45.937: WARN/System.err(2989): at java.lang.ClassCache.findMethodByName(ClassCache.java:308)
03-25 18:18:45.937: WARN/System.err(2989): java.lang.NoSuchMethodException: setPreferredNetworkType 03-25 18:18:45.937: WARN/System.err(2989): 在 java.lang.ClassCache。 findMethodByName(ClassCache.java:308)
So do you have an idea to access setPreferredNetworkType or choose programmaticaly my preferred network type ?
那么您是否有想法访问 setPreferredNetworkType 或以编程方式选择我的首选网络类型?
For information (In RILConstants.java) :
有关信息(在 RILConstants.java 中):
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */
int NETWORK_MODE_GSM_ONLY = 1; /* GSM only */
int NETWORK_MODE_WCDMA_ONLY = 2; /* WCDMA only */
int NETWORK_MODE_GSM_UMTS = 3; /* GSM/WCDMA (auto mode, according to PRL)
AVAILABLE Application Settings menu*/
int NETWORK_MODE_CDMA = 4; /* CDMA and EvDo (auto mode, according to PRL)
AVAILABLE Application Settings menu*/
int NETWORK_MODE_CDMA_NO_EVDO = 5; /* CDMA only */
int NETWORK_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
AVAILABLE Application Settings menu*/
int PREFERRED_NETWORK_MODE = NETWORK_MODE_WCDMA_PREF;
回答by Noogler
Here's a nice guide how to access the internal API: https://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/
这是如何访问内部 API 的一个很好的指南:https: //devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/
From own experience I can tell you that the access generally works but you will get a runtime exception because only system apps have permissions for setting Preferred Network Type.
根据自己的经验,我可以告诉您访问通常有效,但您会收到运行时异常,因为只有系统应用程序有权设置首选网络类型。
This means your app also has to be installed in the system folder AND has to be signed with system key, which is the crux of the matter....
这意味着您的应用程序还必须安装在系统文件夹中并且必须使用系统密钥进行签名,这是问题的关键....
回答by CelinHC
Here are some hardcore reflection https://github.com/TheMasterBaron/Toggle-2G
回答by José Maurício
You can try this post: http://www.josemauricio.net/?p=486
你可以试试这个帖子:http: //www.josemauricio.net/?p= 486
It's using these AT commands:
它使用这些 AT 命令:
KitKat: echo "AT^SYSCONFIG=13,1,1,2\r" > /dev/smd0
KitKat: echo "AT^SYSCONFIG=13,1,1,2\r" > /dev/smd0
Lollipop: echo "AT+WS46=12\r" > /dev/umts_at0
棒棒糖:echo "AT+WS46=12\r" > /dev/umts_at0
One of the main issues, is founding the right command and serial port your device uses.
主要问题之一是确定设备使用的正确命令和串行端口。
回答by Tulio F.
For this to work, your app mustbe signed with the system key or have carrier privilege. Otherwise the app will throw
java.lang.SecurityException: No modify permission or carrier privilege.
为此,您的应用程序必须使用系统密钥进行签名或具有运营商权限。否则应用程序将抛出
java.lang.SecurityException: No modify permission or carrier privilege.
My app runs on Android 5.1 Lollipop(API 22) and is signed with the system key, so this is the only configuration I can confirm for sure that works. I can't confirm the carrier privilege approach.
我的应用程序在 Android 5.1 Lollipop(API 22) 上运行并使用系统密钥进行签名,因此这是我可以确认有效的唯一配置。我无法确认运营商特权方法。
AndroidManifest.xml
AndroidManifest.xml
Add this permission to your app manifest. If you are using Android Studio, it will probably mark this line as an error because only system apps can have this permission. If you can sign your app with the system keys, don't worry.
将此权限添加到您的应用清单。如果您使用的是 Android Studio,它可能会将这一行标记为错误,因为只有系统应用程序才能拥有此权限。如果您可以使用系统密钥签署您的应用程序,请不要担心。
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
Get Preferred Network
获取首选网络
The return is defined in RILConstants.java, e.g. RILConstants.NETWORK_MODE_WCDMA_PREF
返回在 RILConstants.java 中定义,例如 RILConstants.NETWORK_MODE_WCDMA_PREF
public int getPreferredNetwork() {
Method method = getHiddenMethod("getPreferredNetworkType", TelephonyManager.class, null);
int preferredNetwork = -1000;
try {
preferredNetwork = (int) method.invoke(mTelephonyManager);
Log.i(TAG, "Preferred Network is ::: " + preferredNetwork);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return preferredNetwork;
}
Set Preferred Method.
设置首选方法。
The parameter must be based on RILConstants.java
, e.g.: RILConstants.NETWORK_MODE_LTE_ONLY
该参数必须基于RILConstants.java
,例如:RILConstants.NETWORK_MODE_LTE_ONLY
public void setPreferredNetwork(int networkType) {
try {
Method setPreferredNetwork = getHiddenMethod("setPreferredNetworkType",
TelephonyManager.class, new Class[] {int.class});
Boolean success = (Boolean)setPreferredNetwork.invoke(mTelephonyManager,
networkType);
Log.i(TAG, "Could set Network Type ::: " + (success.booleanValue() ? "YES" : "NO"));
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
This is an utility method to access the hidden API methods.
这是访问隐藏 API 方法的实用方法。
/**
* Get a hidden method instance from a class
* @param methodName The name of the method to be taken from the class
* @param fromClass The name of the class that has the method
* @return A Method instance that can be invoked
*/
public Method getHiddenMethod(String methodName, Class fromClass, Class[] params) {
Method method = null;
try {
Class clazz = Class.forName(fromClass.getName());
method = clazz.getMethod(methodName, params);
method.setAccessible(true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return method;
}
回答by Samantha
First you have to add below permission in your manifest;
首先,您必须在清单中添加以下权限;
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions"/>
Then use below code to set preferred network (please note your app has to be OEM signed [System permission] for below to work);
然后使用以下代码设置首选网络(请注意,您的应用必须经过 OEM 签名 [系统权限] 才能在下面工作);
public boolean setPreferredNetworkType(int networkType, int timeout) {
Boolean result = false;
try {
TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
final Method getPreferredNetworkType = telephonyManager.getClass().getDeclaredMethod("getPreferredNetworkType", int.class);
final Method setPreferredNetworkType = telephonyManager.getClass().getDeclaredMethod("setPreferredNetworkType", int.class, int.class);
final Method getSubId = telephonyManager.getClass().getDeclaredMethod("getSubId");
getPreferredNetworkType.setAccessible(true);
setPreferredNetworkType.setAccessible(true);
getSubId.setAccessible(true);
Integer currentNetworkType = (Integer) getPreferredNetworkType.invoke(telephonyManager, getSubId.invoke(telephonyManager));
if (currentNetworkType != networkType) {
setPreferredNetworkType.invoke(telephonyManager, getSubId.invoke(telephonyManager), networkType);
while (timeout > 0) {
currentNetworkType = (Integer) getPreferredNetworkType.invoke(telephonyManager, getSubId.invoke(telephonyManager));
if (currentNetworkType == networkType) {
result = true;
break;
}
try {
Thread.sleep(THREAD_WAIT_TIMEOUT_IN_MS);
} catch (InterruptedException e) {
}
timeout -= THREAD_WAIT_TIMEOUT_IN_MS;
}
} else {
result = true;
}
} catch (SecurityException se) {
} catch (Exception e) {
}
return result;
}
In above you can use the RILConstants.java Integer values as 'networkType'.
在上面,您可以使用 RILConstants.java 整数值作为“networkType”。