如何在Android源码中访问setPreferredNetworkType
我有一个问题想问您,我正在尝试在 Android 手机上选择首选网络类型。 您可以通过执行以下步骤来完成:
- 拨打##4636##
- 选择“电话信息”
- 转到底部
- 在菜单上选择首选网络类型
因此在对源代码进行了一些搜索之后我找到了正确的类:Phone.java in (\frameworks\base\telephony\java\com\android\internal\telephony)
所以有了 Vinay 的好提示: 如何在 Android 上禁用移动数据 谁在使用java反射来访问隐藏类,我也尝试这样做:
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 });
但问题是我在DDMS上遇到了这个错误:
03-25 18:18:45.937: 警告/系统错误(2989):java.lang.NoSuchMethodException:setPreferredNetworkType 03-25 18:18:45.937: WARN/System.err(2989): 在 java.lang.ClassCache.findMethodByName(ClassCache.java:308)
那么你有想法访问setPreferredNetworkType或以编程方式选择我的首选网络类型吗?
有关信息(在 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;
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:
- Dial ##4636##
- Choose "Phone Information"
- Go bottom
- Choose preferred Network Type on menu
So after some searches on the source code I found the right class: Phone.java in (\frameworks\base\telephony\java\com\android\internal\telephony)
So with the nice tips of Vinay: How to disable Mobile Data on Android
Who is using java reflexion to acces to hidden classes, I tried too by doing:
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:
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)
So do you have an idea to access setPreferredNetworkType or choose programmaticaly my preferred network type ?
For information (In 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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这是一个关于如何访问内部 API 的很好的指南:
https://devmaze.wordpress。 com/2011/01/18/using-com-android-internal-part-1-introduction/
根据我自己的经验,我可以告诉你访问通常可以工作,但你会得到一个运行时异常,因为只有系统应用程序有设置首选网络类型的权限。
这意味着您的应用程序还必须安装在系统文件夹中,并且必须使用系统密钥进行签名,这是问题的关键......
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/
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....
首先,您必须在清单中添加以下权限;
然后使用下面的代码设置首选网络(请注意,您的应用程序必须经过 OEM 签名 [系统权限] 才能运行);
在上面,您可以使用 RILConstants.java 整数值作为“networkType”。
First you have to add below permission in your manifest;
Then use below code to set preferred network (please note your app has to be OEM signed [System permission] for below to work);
In above you can use the RILConstants.java Integer values as 'networkType'.
以下是一些核心反思https://github.com/TheMasterBaron/Toggle-2G
Here are some hardcore reflection https://github.com/TheMasterBaron/Toggle-2G
您可以尝试这篇文章:http://www.josemauricio.net/?p=486
它使用这些 AT 命令:
KitKat: echo "AT^SYSCONFIG=13,1,1,2\r" > /dev/smd0
Lollipop: echo "AT+WS46=12\r" > /dev/umts_at0
主要问题之一是找到设备使用的正确命令和串行端口。
You can try this post: http://www.josemauricio.net/?p=486
It's using these AT commands:
KitKat: echo "AT^SYSCONFIG=13,1,1,2\r" > /dev/smd0
Lollipop: echo "AT+WS46=12\r" > /dev/umts_at0
One of the main issues, is founding the right command and serial port your device uses.
为此,您的应用必须使用系统密钥进行签名或拥有运营商权限。否则应用程序将抛出
java.lang.SecurityException: 无修改权限或运营商权限。
我的应用程序在 Android 5.1 Lollipop(API 22) 上运行,并使用系统密钥进行签名,因此这是我可以确定的唯一配置有效。我无法确认运营商特权方法。
AndroidManifest.xml
将此权限添加到您的应用清单中。如果您使用的是 Android Studio,它可能会将这一行标记为错误,因为只有系统应用程序才能拥有此权限。如果您可以使用系统密钥签署您的应用程序,请不用担心。
获取首选网络
返回值在 RILConstants.java 中定义,例如
RILConstants.NETWORK_MODE_WCDMA_PREF
设置首选方法。
该参数必须基于
RILConstants.java
,例如:RILConstants.NETWORK_MODE_LTE_ONLY
这是访问隐藏API 方法的实用方法。
For this to work, your app must be signed with the system key or have carrier privilege. Otherwise the app will throw
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.
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.
Get Preferred Network
The return is defined in RILConstants.java, e.g.
RILConstants.NETWORK_MODE_WCDMA_PREF
Set Preferred Method.
The parameter must be based on
RILConstants.java
, e.g.:RILConstants.NETWORK_MODE_LTE_ONLY
This is an utility method to access the hidden API methods.