修改WIFI热点的默认名称

    需要将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热点的默认名称。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值