您的位置:首页 > 移动开发 > Android开发

修改WIFI热点的默认名称

2016-05-19 17:23 791 查看
    需要将WIFI热点定制化为AMAZON-XXXX的形式(厂商名-XXXX)。在我的奇酷手机上,看到已经是这样实现的,看来还是有需求的。基于当前的高通平台Android 5.1实现。下面会详细的一步一步说明如何查找到相关的地方,并进行修改。对于Android平台比较熟悉的朋友可能有点啰嗦,请直接看文章最后一部分文字。对于初次接触或者接触不久的朋友,可以耐心一点看完。

全局搜索高通的8909平台源码,发现是在下面的地方发现wifi热点相关的菜单(进到设置里面去看,通过子串查找对应的代码,这个在Android项目修改的时候经常用到的方法。通过某个界面上的子串,找到这个界面后面的逻辑代码):

find ./ -name "*.xml" | xargs grep "Set up WLAN hotspot"
./vendor/qcom/proprietary/qrdplus/Extension/res-overlay/packages/apps/Settings/res/values/strings.xml:
<string name="wifi_tether_configure_ap_text">Set up WLAN hotspot</string>
再搜索字串ID引用,发现如下:
mSsid.setText(mWifiConfig.SSID);
这个mWifiConfig是初始化WifiApDialog类的时候调用的。
HotspotSettings.java: mDialog = new WifiApDialog(getActivity(), this, mWifiApConfig);
TetherSettings.java: mDialog = new WifiApDialog(activity, this, mWifiConfig);
继续追踪:
mWifiApConfig = mWifiManager.getWifiApConfiguration();
都是调用这个来获取wifi热点的设置。

发现是在WifiServiceImpl extends IWifiManager.Stub中:
public WifiConfiguration getWifiApConfiguration() {
enforceAccessPermission();
return mWifiStateMachine.syncGetWifiApConfiguration();
}
mInterfaceName =  SystemProperties.get("wifi.interface", "wlan0");
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller);

WifiStateMachine.java
public WifiConfiguration syncGetWifiApConfiguration() {
Message resultMsg = mWifiApConfigChannel.sendMessageSynchronously(CMD_REQUEST_AP_CONFIG);
WifiConfiguration ret = (WifiConfiguration) resultMsg.obj;
resultMsg.recycle();
return ret;
}
if (mWifiApConfigChannel == null) {
mWifiApConfigChannel = new AsyncChannel();
WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
mContext, getHandler());
wifiApConfigStore.loadApConfiguration();
mWifiApConfigChannel.connectSync(mContext, getHandler(),
wifiApConfigStore.getMessenger());
}

上面的wifi相关的内容涉及到了状态机,这里就不讨论了。继续查看wifiApConfigStore.loadApConfiguration函数。
void loadApConfiguration() {
DataInputStream in = null;
try {
WifiConfiguration config = new WifiConfiguration();
in = new DataInputStream(new BufferedInputStream(new FileInputStream(
AP_CONFIG_FILE)));
int version = in.readInt();
if (version != 1) {
Log.e(TAG, "Bad version on hotspot configuration file, set defaults");
setDefaultApConfiguration();
return;
}
config.SSID = in.readUTF();
int authType = in.readInt();
config.allowedKeyManagement.set(authType);
if (authType != KeyMgmt.NONE) {
config.preSharedKey = in.readUTF();
}
mWifiApConfig = config;
} catch (IOException ignore) {
setDefaultApConfiguration();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {}
}
}
}

原来是从一个文件里面读取的值啊!
private static final String AP_CONFIG_FILE = Environment.getDataDirectory() + "/misc/wifi/softap.conf";
在项目里面全局搜一下这个文件试试。
find ./ -name "softap.conf" //居然没有找到,看来像是动态生成的
find ./ -name "*" | xargs grep "softap.conf"
后来还是在WifiApConfigStore的setDefaultApConfiguration函数里面看到了相关的内容:
/* Generate a default WPA2 based configuration with a random password. We are changing the Wifi Ap configuration storage from secure settings to a flat file accessible only by the system. A WPA2 based default configuration will keep the device secure after the update */
private void setDefaultApConfiguration() {
WifiConfiguration config = new WifiConfiguration();
config.SSID = mContext.getResources().getString(
R.string.def_wifi_wifihotspot_ssid);
if (TextUtils.isEmpty(config.SSID)) {
config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
}
config.allowedKeyManagement.set(mContext.getResources().getBoolean(
R.bool.set_wifi_hotspot_security_none) ? KeyMgmt.NONE : KeyMgmt.WPA2_PSK);
config.preSharedKey = mContext.getResources().getString(
R.string.def_wifi_wifihotspot_pass);
if (TextUtils.isEmpty(config.preSharedKey)) {
String randomUUID = UUID.randomUUID().toString();
// first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
config.preSharedKey = randomUUID.substring(0, 8)
+ randomUUID.substring(9, 13);
}
sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG, config);
}
<span style="font-size:18px;">注意函数开头的解释说明。

所以最终的修改方案只需要修改这个函数即可。注意如何获取后四位数字,比如如何获取IMEI号。</span>

如何获取手机IMEI

发现在项目手机上面输入*#06#,弹出的是MEID而非(IMEI),所以看看MEID是怎么获取的。在About phone界面就有MEID的显示。

<dashboard-tile
android:id="@+id/about_settings"
android:title="@string/about_settings"
android:fragment="com.android.settings.DeviceInfoSettings"
android:icon="@drawable/ic_settings_about"
/>
看看Status.java里面的注释:
// NOTE "imei" is the "Device ID" since it represents
// the IMEI in GSM and the MEID in CDMA
if (mPhone.getPhoneName().equals("CDMA")) {
setSummaryText(KEY_MEID_NUMBER, mPhone.getMeid());
setSummaryText(KEY_MIN_NUMBER, mPhone.getCdmaMin());
所以IMEI对应GSM手机,MEID针对CDMA手机。
if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
// Show ICC ID and IMEI for LTE device
setSummaryText(KEY_ICC_ID, mPhone.getIccSerialNumber());
setSummaryText(KEY_IMEI, mPhone.getImei());
}
if (UserHandle.myUserId() == UserHandle.USER_OWNER &&
(!isMultiSimEnabled())) {
mPhone = PhoneFactory.getDefaultPhone();
}

结论

综上,如果要设置默认wifi热点名称为指定名称,只需要修改WifiApConfigStore的setDefaultApConfiguration函数即可。如下:
/*tel-change the default wifi hotspot name-murphy-2016.05.17-start*/
import android.telephony.TelephonyManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import android.os.UserHandle;
import android.util.Log;
/*tel-change the default wifi hotspot name-murphy-2016.05.17-end*/
private void setDefaultApConfiguration() {
WifiConfiguration config = new WifiConfiguration();
/*tel-change the default wifi hotspot name-murphy-2016.05.17-start*/
String mergeNumber = "DEEEE";//in case the mergeNumber is empty at last
Phone mPhone;
if (UserHandle.myUserId() == UserHandle.USER_OWNER &&
(!(TelephonyManager.getDefault().getPhoneCount() > 1))) {
mPhone = PhoneFactory.getDefaultPhone();
Log.d("wifihotspotname", "phone name = " + mPhone.getPhoneName());

if (mPhone.getPhoneName().equals("CDMA"))
{
mergeNumber = mPhone.getMeid();
if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE)
{
mergeNumber = mPhone.getImei();
}
}else{
mergeNumber = mPhone.getDeviceId();
}
Log.d("wifihotspotname", "mergeNumber = " + mergeNumber);
mergeNumber = mergeNumber.substring(mergeNumber.length() - 4);
}
String tempSSID = mContext.getResources().getString(
R.string.def_wifi_wifihotspot_ssid);
tempSSID = String.format(tempSSID, mergeNumber);
Log.d("wifihotspotname", "tempSSID = " + tempSSID);
config.SSID = tempSSID;
/*tel-change the default wifi hotspot name-murphy-2016.05.17-end*/
又因为引用了另外一个包里面的java类,所以需要在Android.mk里面进行声明,否则编译的时候会提示找不到该类:
#frameworks/opt/net/wifi/serivce/Android.mk
#tel-change the default wifi hotspot name-murphy-2016.05.17-start
LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt services telephony-common
#tel-change the default wifi hotspot name-murphy-2016.05.17-end修改代码,删除out目录,update-api,重新编译之后在开机界面卡死。通过adb抓取log发现:
E/AndroidRuntime( 8215): *** FATAL EXCEPTION IN SYSTEM PROCESS: WifiStateMachine
E/AndroidRuntime( 8215): java.lang.IllegalStateException: Default phones haven't been made yet!
E/AndroidRuntime( 8215): 	at com.android.internal.telephony.PhoneFactory.getDefaultPhone(PhoneFactory.java:245)
E/AndroidRuntime( 8215): 	at com.android.server.wifi.WifiApConfigStore.setDefaultApConfiguration(WifiApConfigStore.java:226)
E/AndroidRuntime( 8215): 	at com.android.server.wifi.WifiApConfigStore.loadApConfiguration(WifiApConfigStore.java:176)
E/AndroidRuntime( 8215): 	at com.android.server.wifi.WifiStateMachine$InitialState.enter(WifiStateMachine.java:5135)
E/AndroidRuntime( 8215): 	at com.android.internal.util.StateMachine$SmHandler.invokeEnterMethods(StateMachine.java:1008)
E/AndroidRuntime( 8215): 	at com.android.internal.util.StateMachine$SmHandler.handleMessage(StateMachine.java:795)
E/AndroidRuntime( 8215): 	at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 8215): 	at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime( 8215): 	at android.os.HandlerThread.run(HandlerThread.java:61)
I/Process ( 8215): Sending signal. PID: 8215 SIG: 9

原来是开机的时候根本没法获取到IMEI的后四位。当然如果不用IMEI号,使用其他字串代替也是可以的。修改setDefaultApConfiguration函数如下:
/*tel-change the default wifi hotspot name-murphy-2016.05.17-start*/
String mergeNumber = "DECFE";//in case the mergeNumber is empty at last
/*Phone mPhone;
if (UserHandle.myUserId() == UserHandle.USER_OWNER &&
(!(TelephonyManager.getDefault().getPhoneCount() > 1))) {
mPhone = PhoneFactory.getDefaultPhone();
Log.d("wifihotspotname", "phone name = " + mPhone.getPhoneName());

if (mPhone.getPhoneName().equals("CDMA"))
{
mergeNumber = mPhone.getMeid();
if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE)
{
mergeNumber = mPhone.getImei();
}
}else{
mergeNumber = mPhone.getDeviceId();
}
Log.d("wifihotspotname", "mergeNumber = " + mergeNumber);
mergeNumber = mergeNumber.substring(mergeNumber.length() - 4);
}*/
mergeNumber = mergeNumber.substring(mergeNumber.length() - 4);
String tempSSID = mContext.getResources().getString(
R.string.def_wifi_wifihotspot_ssid);
tempSSID = String.format(tempSSID, mergeNumber);
Log.d("wifihotspotname", "tempSSID = " + tempSSID);
config.SSID = tempSSID;
/*tel-change the default wifi hotspot name-murphy-2016.05.17-end*/
if (TextUtils.isEmpty(config.SSID)) {
config.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
}
注意,我已经注释了会引起异常的获取IMEI代码。编译之后,将system.img刷到手机,开机发现WIFI热点变为:AMAZON_ECFE。如果手动修改该名称,重启之后,WIFI热点依然是你修改的名称。

本文基于Android 5.1介绍了两点知识:

1. 如何获取IMEI,其中包含如何在另外一个包中引用其他包的类。

2. 如何设置手机的WIFI热点的默认名称。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android