[资料分享] 通过wifi与设备进行通信(Android)

灞波儿奔   2019-2-17 21:39 楼主
通过wifi与设备进行通信(Android) 最近leader决定把app与设备之间的通信改为wifi,通过http协议实现设备之间的通信。 相对与之前的蓝牙通信,的确简单不少,但实际编码当中也有坑。现在分享出来,希望能给需要的鞋童以帮助,有啥问题大家也可以讨论一下。 切换手机wifi到指定wifi热点 在baidu或者google输入以上内容搜索,会出现很多相关资料,但是点开之后,才发现大多都是一样,那么实用性怎么样,于是我验证了一下。 大致思路是,首先创建WifiConfiguration,按照wifi加密方式分为无密码,有密码(WEP,WPA)。 // 创建 WifiConfiguration public WifiConfiguration CreateWifiInfo(String ssid, String password, int type) { WifiConfiguration config = new WifiConfiguration(); config.SSID = "\"" + ssid + "\""; WifiConfiguration tempConfig = this.IsExsits(ssid); if(tempConfig != null) { mWifiManager.removeNetwork(tempConfig.networkId); } if(Type == 1) //WIFICIPHER_NOPASS { 此处省略…… } if(Type == 2) //WIFICIPHER_WEP { 此处省略…… } if(Type == 3) //WIFICIPHER_WPA { 此处省略…… } return config; } 从代码中看,之中还判断ssid是否存在,如果存在就用removeNetwork将此ssid的wifi从已配置信息wifi列表中remove掉。这一步是必要的,因为ssid就是手机wifi列表中wifi的名称。具有相同ssid的wifi可能并不是同一wifi,如果使用了上次保留的配置信息,就可能到导致自动连接wifi失败。但此代码因为是很早之前写的,所以在android6.0版本上并不适用。android6.0新特性加强了对手机权限控制,同时在wifi模块也不再允许对已保存的wifi配置列表进行更新和删除,这将会导致removeNetwork操作失败。 下面看一下添加切换手机到指定wifi热点的代码 // 更改前写法 public boolean addNetwork(WifiConfiguration wcg) { int wcgID = mWifiManager.addNetwork(wcg); boolean b = mWifiManager.enableNetwork(wcgID, true); return b; } 此代码的确能使部分手机成功切换到指定wifi,但其实代码并不规范,这将会导致在部分手机中切换失败。下面介绍正确写法 //更改后写法 public boolean addNetwork(WifiConfiguration wifiConfiguration) { mWifiManager.disconnect(); int networkId = mWifiManager.addNetwork(wifiConfiguration); boolean res = mWifiManager.enableNetwork(networkId, true); mWifiManager.saveConfiguration(); mWifiManager.reconnect(); return res; } 指定通过wifi进行http请求 不要以为这样就完了,还有个大坑在等我们 在测试过程中,突然发现,在手机wifi和数据流量同时存在时,部分手机会直接使用数据流量进行通信,这样就导致手机与设备之间无法通信,因为手机与设备只有处在同一局域网下才能正常通信。 这可麻烦了,于是到处到解决办法,终于在WifiManager 这个类找到一个方法enableNetwork上面有一大段英文,我们一起看一下。 /** * Allow a previously configured network to be associated with. If * disableOthers is true, then all other configured * networks are disabled, and an attempt to connect to the selected * network is initiated. This may result in the asynchronous delivery * of state change events. *

* Note: If an application's target SDK version is * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may * instead be sent through another network, such as cellular data, * Bluetooth tethering, or Ethernet. For example, traffic will never use a * Wi-Fi network that does not provide Internet access (e.g. a wireless * printer), if another network that does offer Internet access (e.g. * cellular data) is available. Applications that need to ensure that their * network traffic uses Wi-Fi should use APIs such as * {@link Network#bindSocket(java.net.Socket)}, * {@link Network#openConnection(java.net.URL)}, or * {@link ConnectivityManager#bindProcessToNetwork} to do so. * * @param netId the ID of the network in the list of configured networks * @param disableOthers if true, disable all other networks. The way to * select a particular network to connect to is specify {@code true} * for this parameter. * @return {@code true} if the operation succeeded */ 原来解决办法在 ConnectivityManager 这个类的方法 requestNetwork 可以指定使用 wifi 或者蜂窝数据等访问网络。如果要指定用蜂窝数据进行通信,将 addTransportType 设置为TRANSPORT_CELLULAR即可。在有可用指定传输类型连接上后,onAvailable方法就会调用,其实主要就是获取到 Network 。 Network 通过 openConnection 得到 HttpURLConnection ,相信大家对HttpURLConnection十分熟悉,直接用它发起网络请求就可以了。 本帖最后由 灞波儿奔 于 2019-2-17 21:40 编辑

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复