工作背景: 公司出口国外某国的设备, 因为该国对 4G 认证要求较高, 流程非常麻烦, 客户不想取得 4G 方面认证, 因此订单机器设备需禁用 4G, 且不能手动恢复 4G, 默认 3G/2G(auto)模式.
实现思路: 在安卓系统的设置功能里面有设置网络类型的功能, 根据设置时走的流程, 默认设置开机时网络为 3G/2G, 并删除切换网络类型的选项.
工作步骤: 首先, 了解设置中网络类型设置的实现.
安卓系统对网络设置操作过程: 设置 (settings)-> 更多 (more)-> 移动网络 (Mobile networks)-> 首选网络类型(preferred network type)
1, 设置 (settings) 模块的布局文件为: packages\apps\Settings\res\xml\dashboard_categories.xml, 其中下面部分的代码对应的是 settings 中的 more 选项:
- <!-- Operator hook -->
- <dashboard-tile
- android:id="@+id/operator_settings"
- android:fragment="com.android.settings.WirelessSettings">
- <intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" />
- </dashboard-tile>
- <!-- Other wireless and network controls -->
- <dashboard-tile
- android:id="@+id/wireless_settings"
- android:title="@string/radio_controls_title"
- android:fragment="com.android.settings.WirelessSettings"
- android:icon="@drawable/ic_settings_more"
- />
- </dashboard-category>
2, 点击 more 以后进入 Mobile networks, packages\apps\Settings\src\com\android\settings\WirelessSettings.java 文件,
发现加载: addPreferencesFromResource(R.xml.wireless_settings);
3, 通过更多 (more) 的布局文件 packages\apps\Settings\res\xml\wireless_settings.xml 文件发现, 启动了 Phone 模块的, MobileNetworkSettings.java 文件, 其中下面部分的代码对应的是 more 中的 Mobile networks 选项:
<PreferenceScreen
android:key="mobile_network_settings"
android:title="@string/network_settings_title"
settings:keywords="@string/keywords_more_mobile_networks"
android:dependency="toggle_airplane">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.android.phone"
android:targetClass="com.android.phone.MobileNetworkSettings" />
</PreferenceScreen>
目录: packages\services\Telephony\src\com\android\phone\MobileNetworkSettings.java
4, 点击移动网络 (Mobile networks) 时, 通过 MobileNetworkSettings.java 发现是里面的控件 NetWork Mode 控件: addPreferencesFromResource(R.xml.network_setting);
文件加载的 packages\services\Telephony\res\xml\network_setting.xml, 它是移动网络的布局文件. 其中下面部分的代码对应的是移动网络中的首选网络类型 (preferred network type) 选项, 根据插入的 SIM 卡的情况, 分别选择显示下面两个按钮中的哪一个:
- <ListPreference
- android:key="preferred_network_mode_key"
- android:title="@string/preferred_network_mode_title"
- android:summary="@string/preferred_network_mode_summary"
- android:entries="@array/preferred_network_mode_choices"
- android:entryValues="@array/preferred_network_mode_values"
- android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
- <ListPreference
- android:key="enabled_networks_key"
- android:title="@string/preferred_network_mode_title"
- android:summary="@string/preferred_network_mode_summary"
- android:entries="@array/enabled_networks_choices"
- android:entryValues="@array/enabled_networks_values"
- android:dialogTitle="@string/preferred_network_mode_dialogtitle" />
5, 通过 preferred_network_mode_key 回到 MobileNetworkSettings.java 中找寻 BUTTON_PREFERED_NETWORK_MODE.
- private static final String BUTTON_PREFERED_NETWORK_MODE = "preferred_network_mode_key";
- private static final String BUTTON_ENABLED_NETWORKS_KEY = "enabled_networks_key";
6, 找到语句, 确定是对象 mButtonPreferredNetworkMode:
- mButtonPreferredNetworkMode = (ListPreference) prefSet.findPreference(BUTTON_PREFERED_NETWORK_MODE);
- mButtonEnabledNetworks = (ListPreference) prefSet.findPreference(BUTTON_ENABLED_NETWORKS_KEY);
7, 找到这个 listpreference 的点击事件:
- public boolean onPreferenceChange(Preference preference, Object objValue) {
- if (preference == mButtonPreferredNetworkMode) {
- //NOTE onPreferenceChange seems to be called even if there is no change
- //Check if the button value is changed from the System.Setting
- mButtonPreferredNetworkMode.setValue((String) objValue);
然后执行里面的语句, 设置联网模式:
//Set the modem network mode
setPreferredNetworkType(modemNetworkMode); 该函数实现的方法为:
mPhone.setPreferredNetworkType(modemNetworkMode, mHandler.obtainMessage(MyHandler.MESSAGE_SET_PREFERRED_NETWORK_TYPE));
8, 跟踪到 framework 层, 找寻 Phone.java 文件, 具体目录所在: frameworks\opt\telephony\src\java\com\android\internal\telephony\Phone.java
发现 Phone.java 仅仅是一个接口, 而被 PhoneBase.java 文件所实现(PhoneBase extends Handler implements Phone), 设置网络类型的函数.
- public void setPreferredNetworkType(int networkType, Message response) {
- mCi.setPreferredNetworkType(networkType, response);
- }
其实实际上是 public CommandsInterface mCi; 接口实现的
- protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci, boolean unitTestMode) {
- this.mNotifier = notifier;
- this.mContext = context;
- mLooper = Looper.myLooper();
- mCi = ci;
- }
9, 最后网络上说在 RIL.java 文件中可以找到设置网络类型的地方(我也不知道是怎么对应的):
- @Override
- public void setPhoneType(int phoneType) { // Called by CDMAPhone and GSMPhone constructor
- if (RILJ_LOGD) riljLog("setPhoneType=" + phoneType + "old value=" + mPhoneType);
- mPhoneType = phoneType;
- }
- public void setPreferredNetworkType(int networkType , Message response) {
- RILRequest rr = RILRequest.obtain(RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response);
- rr.mParcel.writeInt(1);
- rr.mParcel.writeInt(networkType);
- mPreferredNetworkType = networkType;
- if (RILJ_LOGD) riljLog(rr.serialString() + ">" + requestToString(rr.mRequest)
- + ":" + networkType);
- send(rr);
- }
扩展 CommandsInterface 接口主要为了在 RIL.java 中实现向 modem 发送请求的方法
领导说, 此处后面的部分由安卓在 modem 中实现在 modem 中实现. 该部分不在源码中实现, 因此也无法往下分析.
*************************************************** 华丽分割线 ************************************************
过程搞懂了, 如何实现呢? 以我们公司的安卓源码为例:
1, 在 device\qcom\XXXX\system.prop 文件中定义了参数 default_network, 设置默认网络类型.
- # Start in global mode
- ro.telephony.default_network=22
2, 在 frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java 中获取默认网络类型
- type = SystemProperties.getInt("persist.radio.default_network", -1);
- if (type == TYPE_NONE) {
- type = SystemProperties.getInt("ro.telephony.default_network", RILConstants.PREFERRED_NETWORK_MODE);
- }
- String val = Integer.toString(type);
- for (int phoneId = 1; phoneId < phoneCount; phoneId++) {
- val = val + "," + type;
- }
- loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, val);
3,Settings.Global.PREFERRED_NETWORK_MODE 的定义在文件 frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\Settings.java 中:
- public static final String PREFERRED_NETWORK_MODE = "preferred_network_mode";
- MOVED_TO_GLOBAL.add(Settings.Global.PREFERRED_NETWORK_MODE);
4, 在 frameworks\base\telephony\java\com\android\internal\telephony\RILConstants.java 中定义了各种网络类型的值, 安卓中默认值为 22
int NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo */
5, 在 frameworks\opt\telephony\src\java\com\android\internal\telephony\Phone.java 中将上面的值赋值给一个全局变量, 在安卓中其他地方调用时就可以直接使用全局变量 --Phone.NT_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA
int NT_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA = RILConstants.NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA;
6, 安卓开机时会调用 frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\MobilePhone.java 中的 getDispNet(Context context)函数获取网络类型, 该函数调用 getNetworkTypeName(Context context)函数, 进一步调用 getTelNetType(Context context)函数, 最终调用 telephonyManager.getNetworkType()函数.
7,getNetworkType()函数实现方法所在目录 frameworks\base\telephony\java\android\telephony\TelephonyManager.java, 该方法最终调用的是 telephony.getDataNetworkTypeForSubscriber(subId). 注: TelephonyManager 中含有获取 SIM 卡等信息的方法, 使用如下:
- // 获取系统的 TelephonyManager
- TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
- // 获取设备编号
- mId = mTelephonyManager.getDeviceId();
- // 获取系统平台版本
- mVersion=mTelephonyManager.getDeviceSoftwareVersion();
- // 获取网络运营商代号
- mOperator=mTelephonyManager.getNetworkOperator();
- // 获取网络运营商名称
- mName=mTelephonyManager.getNetworkOperatorName();
- // 获取手机网络类型
- mType = mTelephonyManager.getPhoneType();
- // 获取设备所在位置
- mLocation=mTelephonyManager.getCellLocation();
- // 获取 SIM 卡的国别
- mIso=mTelephonyManager.getSimCountryIso();
- // 获取 SIM 卡的序列号
- mNumber=mTelephonyManager.getSimSerialNumber();
- // 获取 SIM 卡状态
- mState = mTelephonyManager.getSimState();
Android 的 Api 中已经定义了各种网络状态, 也在 TelephonyManager 里面的定义
- public static final int NETWORK_TYPE_UNKNOWN
- Network is unknown 0 (不知道网络类型)
- public static final int NETWORK_TYPE_GPRS
network is GPRS 1 (2.5G)移动和联通
public static final int NETWORK_TYPE_EDGE
network is EDGE 2 (2.75G)2.5G 到 3G 的过渡 移动和联通
public static final int NETWORK_TYPE_UMTS
network is UMTS 3 (3G)联通
- public static final int NETWORK_TYPE_CDMA
- network is CDMA: Either IS95A or IS95B 4 (2G 电信)
- public static final int NETWORK_TYPE_EVDO_0
network is EVDO revision0 5 (3G)电信
public static final int NETWORK_TYPE_EVDO_A
network is EVDO revisionA 6 (3.5G) 属于 3G 过渡
- public static final int NETWORK_TYPE_1xRTT
- network is 1xRTT 7 ( 2G )
- public static final int NETWORK_TYPE_HSDPA
- network is HSDPA 8 (3.5G)
- public static final int NETWORK_TYPE_HSUPA
- network is HSUPA 9 (3.5G)
- public static final int NETWORK_TYPE_HSPA
network is HSPA 10 (3G)联通
- public static final int NETWORK_TYPE_IDEN
- network is iDen 11 (2G)
- public static final int NETWORK_TYPE_EVDO_B
- network is EVDO revisionB 12 3G-3.5G
- public static final int NETWORK_TYPE_LTE
- network is LTE 13 (4G)
- public static final int NETWORK_TYPE_EHRPD
- network is eHRPD 14 3G(3G 到 4G 的升级产物)
- public static final int NETWORK_TYPE_HSPAP
- network is HSPA+ 15 ( 3G )
GPRS 2G(2.5) General Packet Radia Service 114kbps
EDGE 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
UMTS 3G WCDMA 联通 3G Universal Mobile Telecommunication System 完整的 3G 移动通信技术标准
CDMA 2G 电信 Code Division Multiple Access 码分多址
EVDO_0 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于 3G
EVDO_A 3G 1.8mbps - 3.1mbps 属于 3G 过渡, 3.5G
1xRTT 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G 的过渡,
HSDPA 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
HSUPA 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
HSPA 3G (分 HSDPA,HSUPA) High Speed Packet Access
IDEN 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于 2G, 来自维基百科)
EVDO_B 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
LTE 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G 过渡, 升级版 LTE Advanced 才是 4G
EHRPD 3G CDMA2000 向 LTE 4G 的中间产物 Evolved High Rate Packet Data HRPD 的升级
HSPAP 3G HSPAP 比 HSDPA 快些
来源: http://www.bubuko.com/infodetail-2689275.html