Android应用程序创建热点以及自动链接Wifi,我遇到的问题以及我是怎么解决的
急速传歌这个功能需要App能够自动去连接另一个手机创建的热点,本文先说Wifi创建热点以及连接Wifi的原理,然后再讲我遇到的问题和我是怎么解决问题的。
B手机创建热点是一个自动的过程,A手机去连接B手机的热点也是一个自动的过程,此时手机B充当路由器的角色。
自动连接Wifi功能,就像我们通过系统设置WLAN里面,选择一个Wifi并且输入密码(如果有密码)的过程一样,只不过App知道了这个Wifi(带某个前缀)的密码,然后通过相关设置,可以自动去连接。
Android应用如何自动链接Wifi
Android开发里操作Wifi功能的api就在android.net.wifi.WifiManager
这个类中,包括:
getConnectionInfo()
获取当前Wifi连接信息,返回WifiInfo
对象,包括SSID
,BSSID
,networkId
,ipAddress
,macAddress
等信息disableNetwork(int netId)
禁用这个network(即使Wifi扫描到这个热点也不会主动去连接),参数netId
就是WifiInfo
中的networkId
值disconnect()
断开当前连接getConfiguredNetworks()
返回已经保存的Wifi网络列表,返回值是List<WifiConfiguration>
updateNetwork(WifiConfiguration config)
更新Wifi配置,比如更新密码或网络的优先级addNetwork(WifiConfiguration config)
添加一个新的Wifi配置,当我们在设置->WLAN中选择一个网络并输入密码连接后,系统会自动帮我们记住这个网络,这个方法返回int
,是networkId
值enableNetwork(int netId, boolean disableOthers)
调用这个方法后,一般手机会去自动去连接这个wifi网络,但是部分手机会连接失败saveConfiguration()
; 部分手机的连接失败reconnect()
;
Android应用如何创建一个热点
Android开发中,创建热点的方法也是在WifiManager
类中,不过都已经被Google @hide
了。
@hide
annotation就是Google隐藏了不稳定的方法,当稳定之后,自然会公开,如果我们现在要用这些方法,那么必须通过Java反射来调用
创建一个热点最重要的就是:配置一个WifiConfiguration
对象,通过配置
SSID
: 热点的名字preSharedKey
热点密码hiddenSSID
: 是否隐藏SSIDstatus
:是否启用这个热点配置allowedAuthAlgorithms
:IEEE 802.11认证算法 OPENallowedGroupCiphers
:组秘钥TKIP+CCMPallowedPairwiseCiphers
:对称秘钥TKIP+CCMPallowedKeyManagement
:秘钥管理WPA_PSKallowedProtocols
:加密协议WPA+RSN
启动热点也需要通过Java反射调用WifiManager
类中的setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)
方法,第一个参数就是前面配置的WifiConfiguration
对象,第二个参数true
表示打开,false
表示关闭热点。
当时连接wifi的主要的代码就是,先配置好WifiConfiguration
对象,然后就是添加向添加一个WifiConfiguration
,这样就会返回这个Wifi配置的id
,然后就enable
这个Wifi配置,到此为止,一般的手机都可以连接成功
int networkId = mWifiManager.addNetwork(wifiConfig);
boolean enabled = mWifiManager.enableNetwork(networkId, true);
我遇到的第一个问题:
手机A不能自动的去连接手机B创建的热点,那么问题是手机B创建的热点有问题还是手机A连接热点的配置信息有问题?但是手机C又可以去连接手机B的热点,那么是否说明手机B的热点创建就没问题了呢?
试了很多手机之后,发现都可以连接到手机B的热点,那么我们初步判定就是手机A 的连接Wifi配置信息有问题!后来,我就用手机A系统设置里的Wifi连接功能去连接手机B的热点,可以连接!那么问题就是手机A 连接热点的配置有问题!
问题又来了:
同样的Wifi配置信息,为什么大部分手机都可以连接热点成功,而一些手机就不可以呢?而连接Wifi的方法都是在WifiMnager
类中
我看到了一个方法public void connect(WifiConfiguration config, ActionListener listener)
方法,看文档就是用来连接Wifi的!!!!但不幸的是,这个方法被@hide
了!!!!肯跌啊@_@还好,在文档中可以看到:
For a new network, this function is used instead of a sequence of
addNetwork()
,enableNetwork()
,saveConfiguration()
andreconnect()
而这4个方法是pulic并且没有@hide
的!!然后按照文档写的,再添加两行代码:
非常关键的两行代码,有些手机必须要在saveConfiguration操作之后才能成功连接热点
mWifiManager.saveConfiguration();
mWifiManager.reconnect();
手机A就可以连接成功了!!
我遇到的第二个问题:
HTC手机创建热点时热点的配置信息中的热点名字不起作用!HTC手机可以成功自动连接Wifi,也可以创建热点,但是不能改热点的名字!!这就导致了其他所有手机都不能自动连HTC手机的热点!那么问题显而易见就是创建热点的时候信息配置有问题!!那么为什么配置有问题呢?其他手机不是都可以的吗?
问题大致已经找到了,但是为什么这样呢?必须求助强大的Google了~~~经过一番搜索之后重要找到了!!!
WIFI热点设置,htc setWifiApEnabled Wificonfiguration
HTC 通过 WifiConfiguration 修改 SSID
原因就在于: HTC就喜欢自己去改一些Android系统的api,导致很多手机都可以正常运行的功能,到了HTC手机上就不能正常运行了!!!这不是肯跌吗?(╯‵□′)╯︵┻━┻
找到原因也找到了解决办法,这个bug就这么愉快的解决了~真的多谢强大的Google啊~~
说到最后
我们做事情过程中,一定会遇到很多各种各样的问题,
找到问题的原因(为什么会这样)比怎样去解决重要的多
怎样把大象放进冰箱呢? 打开冰箱,然后把大象放进去!
怎么解决问题呢?
先找到问题的原因,然后在找解决问题的办法
还是那句话,找到问题的原因比找到解决问题的办法更重要.
找到问题所在的原因,如果你不能解决,那么你可以求助于其他人,而当你不知道问题的原因的时候,你去求助别人的时候,别人还有帮你去找问题的原因,这肯定会浪费很多时间的。先不要找解决问题的办法,先找问题的原因~