Android SoftAp支持 (二)

SoftAp界面开启流程(让你的手机支持SoftAp功能)

市面上大多数手机支持SoftAp功能,有少数手机没有打开SoftAp的界面设置,所以无法开启此功能(当然有些山寨手机平板打开了此设置功能也不一定能使用SoftAP,因为此功能需要WIFI芯片与WIFI驱动的支持才能真正意义上实现)。

深入代码介绍一下手机 Portable Wi-Fi hostpot 界面开启条件

上文《Android SoftAp支持 (一)》提到当勾选Portable Wi-Fi hostpot,系统的Setting程序TetherSettings.java将响应此动作。tether这个词意思是拴绳,拴住的意思,理解起来有点晦涩,这里我的理解是分享的意思,比如 WIFI_TETHERING(用WIFI分享网路),  USB_TETHERING(用USB分享网络)……

那么这些网络分享如何满足什么条件才开启呢?疑问

从WirelessSettings开始说

在packages/apps/Settings/src/com/android/settings/WirelessSettings.java 的onCreate方法中会去检测系统是否Tether

       // Disable Tethering if it's not allowed or if it's a wifi-only device
        ConnectivityManager cm =       
                (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (isSecondaryUser || !cm.isTetheringSupported()) {
            getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
        } else {
            Preference p = findPreference(KEY_TETHER_SETTINGS);
            p.setTitle(Utils.getTetheringLabel(cm));
        }
        protectByRestrictions(KEY_TETHER_SETTINGS);

1)调用获取ConnectivityManager实例对象,并调用isTetheringSupported方法来检测是否支持Tether

2)调用getTetheringLabel查看支持哪些网络共享方式,并显示到界面

先看isTetheringSupported方法

    public boolean isTetheringSupported() {
        try {
            return mService.isTetheringSupported();
        } catch (RemoteException e) {  
            return false;
            ...

它调用了frameworks/base/services/java/com/android/server/ConnectivityService.java 的isTetheringSupported 方法

    public boolean isTetheringSupported() {
        enforceTetherAccessPermission();
        int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
        boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.TETHER_SUPPORTED, defaultVal) != 0);
        return tetherEnabledInSettings && ((mTethering.getTetherableUsbRegexs().length != 0 ||
                mTethering.getTetherableWifiRegexs().length != 0 ||
                mTethering.getTetherableBluetoothRegexs().length != 0) &&
                mTethering.getUpstreamIfaceTypes().length != 0);
    }  
读取系统ro.tether.denied的属性,返回true则表示关闭tether功能,返回false表示打开tether功能。(有些设备不能显示portable wifi 就是因为此属性返回true,这里需要修改设置为false)

之后会检测是否有配置文件配置了tether,有则使用设置的值,没有查询到配置这使用查询ro.tether.denied属性的默认值。

这里我们假设得到的tetherEnableInSettings为ture,也不意味着就能正确打开Portable Wi-Fi hostpot 界面。因为还需要检测是否支持WIFI网络共享配置

mTethering.getTetherableWifiRegexs().length!=0 检测是否支持网络共享配置,这里Android4.4 与之前的版本有一定区别,但总体不变,大家可以参考其他代码做一些变通

getTetherableWifiRegexs()方法

frameworks/base/services/java/com/android/server/connectivity/Tethering.java
return mTetherableWifiRegexs;
直接返回了一个变量。  此变量在frameworks/base/services/java/com/android/server/connectivity/Tethering.java 

updateConfiguration()方法中赋值

mTetherableWifiRegexs = tetherableWifiRegexs;
而 tetherableWifiRegexs变量赋值也在此方法中

String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
            com.android.internal.R.array.config_tether_wifi_regexs);

这里的config_tether_wifi_regexs数组由配置文件生成

配置文件config.xml

frameworks/base/core/res/res/values/config.xml

    <!-- List of regexpressions describing the interface (if any) that represent tetherable
         Wifi interfaces.  If the device doesn't want to support tethering over Wifi this
         should be empty.  An example would be "softap.*" -->
    <string-array translatable="false" name="config_tether_wifi_regexs">
    </string-array>

这里看到需要在此默认的config.xml中的   name="config_tether_wifi_regexs" 子标签下添加用作softap的接口(一般为wlan0 或者eth0 视你的WIFI驱动程序而定)

修改后的标签:

    <!-- List of regexpressions describing the interface (if any) that represent tetherable
         Wifi interfaces.  If the device doesn't want to support tethering over Wifi this
         should be empty.  An example would be "softap.*" -->
    <string-array translatable="false" name="config_tether_wifi_regexs">
    <item>"wlan0"</item>
    </string-array>

OK 此处mTethering.getTetherableWifiRegexs().length!=0 返回true, 整个isTetheringSupported 返回真

p.setTitle(Utils.getTetheringLabel(cm))

packages/apps/Settings/src/com/android/settings/WirelessSettings.java 调用到else中的

p.setTitle(Utils.getTetheringLabel(cm));函数

首先看packages/apps/Settings/src/com/android/settings/Utils.java 下的

getTetheringLabel 方法

/**
 * Return string resource that best describes combination of tethering
 * options available on this device.
 */
    
public static int getTetheringLabel(ConnectivityManager cm) {
    String[] usbRegexs = cm.getTetherableUsbRegexs();
    String[] wifiRegexs = cm.getTetherableWifiRegexs();
    String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();

    boolean usbAvailable = usbRegexs.length != 0;
    boolean wifiAvailable = wifiRegexs.length != 0;
    boolean bluetoothAvailable = bluetoothRegexs.length != 0;

    if (wifiAvailable && usbAvailable && bluetoothAvailable) {
        return R.string.tether_settings_title_all;
    } else if (wifiAvailable && usbAvailable) {
        return R.string.tether_settings_title_all;
    } else if (wifiAvailable && bluetoothAvailable) {
        return R.string.tether_settings_title_all;
    } else if (wifiAvailable) {
        return R.string.tether_settings_title_wifi;
    } else if (usbAvailable && bluetoothAvailable) {
        ...
}

这里  cm.getTetherableWifiRegexs();最终会调用到frameworks/base/services/java/com/android/server/connectivity/Tethering.java的 
getTetherableWifiRegexs()方法(与上相同,不再赘述) 


总结

讲到这里相信有些云里雾里了。

总结一下腰打开Portable Wi-Fi hostpot界面条件

需要确认:

1) 首先需要确认你的设备的WIFI芯片以及驱动是否支持softap

2) ro.tether.denied系统属性被设置为false(或者配置”tether_supported“标签并置1)

3) 在frameworks/base/core/res/res/values/config.xml  name="config_tether_wifi_regexs"标签下 添加做softap的接口

你可能感兴趣的:(android,wifi,Softap)