Android Wifi连接控制、TCP、UDP通信,6.0以上适配
2018-03-24 08:16
645 查看
本文章包含内容
Wifi连接控制、Wifi广播接收,适配了Android6.0以上的版本Wifi下的TCP通信
Wifi下的UDP通信
Github项目地址
码云项目地址
最近公司要开发智能家居,APP要作为遥控器和控制中心,其中的原理就是智能设备开机先作为一个热点,发射Wifi信号,然后手机连上这个热点(Wifi控制),手机和智能设备建立了连接后,将家里路由器wifi的账号密码通过TCP协议,Socket通信发送给智能设备,最后智能设备收到后就能连上家里的路由器了。
第一步当然就是Wifi控制了,网上资料挺多的,但是Andorid6.0以上的版本,由于权限问题,不能连上指定Wifi,这就把解决方法分享出来,有一些简单的代码,我用Kotlin来练手了,关键的还是用Java (#^.^#)。
Manifest里面添加权限<!-- wifi控制和状态权限 --> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 网络状态改变的权限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <!-- 6.0以上打开蓝牙和wifi最好加上定位权限,获取wifi列表要用 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 获取IP地址 --> <uses-permission android:name="android.permission.INTERNET"/>Andorid 6.0以上要动态权限
参考资料是严振杰的动态权限方法
Github
Android 6.0 运行时权限管理最佳实践
Wifi广播,用于监听Wifi的状态,demo动态注册广播
参考资料
Android-WiFi开发之 WiFi广播监听
Android SupplicantState
/** * Created by bao on 2018/3/21. * wifi状态广播 */ public class WifiBroadcastReceiver extends BroadcastReceiver { private WifiControlUtils wifiControlUtils; @Override public void onReceive(Context context, Intent intent) { wifiControlUtils = new WifiControlUtils(context); //wifi正在改变状态 if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) { //获取wifi状态 int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLING); switch (wifiState) { case WifiManager.WIFI_STATE_DISABLED: //wifi已经关闭 break; case WifiManager.WIFI_STATE_DISABLING: //wifi正在关闭 break; case WifiManager.WIFI_STATE_ENABLED: //wifi已经开启 break; case WifiManager.WIFI_STATE_ENABLING: //wifi正在开启 break; } } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) { //网络状态改变 NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); if (NetworkInfo.State.DISCONNECTED.equals(info.getState())) { //wifi网络连接断开 } else if (NetworkInfo.State.CONNECTED.equals(info.getState())) { //获取当前网络,wifi名称 ToastUtils.showLong(context.getString(R.string.wifi_connected, wifiControlUtils.getWifiInfo().getSSID())); } } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(intent.getAction())) { //wifi密码错误广播 SupplicantState netNewState = intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE); //错误码 int netConnectErrorCode = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, WifiManager.ERROR_AUTHENTICATING); } } }
public class WifiControlActivity extends AppCompatActivity { private WifiBroadcastReceiver wifiBroadcastReceiver; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.wifi_control_activity); ButterKnife.bind(this); //动态注册wifi状态广播 wifiBroadcastReceiver = new WifiBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); intentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); registerReceiver(wifiBroadcastReceiver, intentFilter); } @Override protected void onDestroy() { super.onDestroy(); //注销广播 unregisterReceiver(wifiBroadcastReceiver); } }Wifi控制工具,网上别人的资料在Andorid6.0 以上不能连接,对其工具进行改进一下,马上解决。
参考资料 Android中自动连接到指定SSID的Wi-Fi
获取WifiManager,这里注意的就是context.getApplicationContext()获取,防止内存泄漏。
public WifiControlUtils(Context context) { //获取wifiManager对象 mWifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); }
wifimanager.jpg2.Wifi 的信息 WifiInfo,获取之前,要先判断 WifiManager 是否为空,因为 Wifi 状态会经常改变,所以获取之前判断一下是否为空,而且每次都重新获取,拿最新的 Wifi 信息。
/** * 获取wifi连接信息 **/ public WifiInfo getWifiInfo() { if (mWifiManager != null) { return mWifiManager.getConnectionInfo(); } return null; }
wifiinfo.jpg3.Andorid 6.0以上的版本,权限改变,连接Wifi不一样。对于6.0以上,如果你要连接不是自己创建的配置,只需要在mWifiManager.getConfiguredNetworks(),翻出以前连接过的的Wifi 配置,获取对应的netId,就能重新连接上。
如果以前连接过的 Wifi 密码改了,但是名称没变,你是连不上的,也没权限去修改密码和删除(可能就是为了安全吧),你就要手动去处理这个Wifi 信息了。
APP没有权限删除之前的连接过的 Wifi ,包括APP以前本身创建的 Wifi(先创建了,重装或者更新后,都不算是自己创建了)。
对于从来都没连接过的 Wifi,或者是删除过的 Wifi(相当于没连接过),和以前一样,只要用 SSID (Wifi名)、密码、加密方式创建新的 WifiConfiguration,无密码的就是要 SSID;然后 mWifiManager.enableNetwork 就连上了。
不可移除wifi.jpg
removeNetWork之后可以不用saveConfiguration.jpg我的改进后的处理方式就是这样的。
/** * 连接指定wifi * 6.0以上版本,直接查找时候有连接过,连接过的拿出wifiConfiguration用 * 不要去创建新的wifiConfiguration,否者失败 */ public void addNetWork(String SSID, String password, int Type) { int netId = -1; /*先执行删除wifi操作,1.如果删除的成功说明这个wifi配置是由本APP配置出来的; 2.这样可以避免密码错误之后,同名字的wifi配置存在,无法连接; 3.wifi直接连接成功过,不删除也能用, netId = getExitsWifiConfig(SSID).networkId;*/ if (removeWifi(SSID)) { //移除成功,就新建一个 netId = mWifiManager.addNetwork(createWifiInfo(SSID, password, Type)); } else { //删除不成功,要么这个wifi配置以前就存在过,要么是还没连接过的 if (getExitsWifiConfig(SSID) != null) { //这个wifi是连接过的,如果这个wifi在连接之后改了密码,那就只能手动去删除了 netId = getExitsWifiConfig(SSID).networkId; } else { //没连接过的,新建一个wifi配置 netId = mWifiManager.addNetwork(createWifiInfo(SSID, password, Type)); } } //这个方法的第一个参数是需要连接wifi网络的networkId,第二个参数是指连接当前wifi网络是否需要断开其他网络 //无论是否连接上,都返回true。。。。 mWifiManager.enableNetwork(netId, true); } /** * 获取配置过的wifiConfiguration */ public WifiConfiguration getExitsWifiConfig(String SSID) { wifiConfigurationList = mWifiManager.getConfiguredNetworks(); for (WifiConfiguration wifiConfiguration : wifiConfigurationList) { if (wifiConfiguration.SSID.equals("\"" + SSID + "\"")) { return wifiConfiguration; } } return null; } /** * 移除wifi,因为权限,无法移除的时候,需要手动去翻wifi列表删除 * 注意:!!!只能移除自己应用创建的wifi。 * 删除掉app,再安装的,都不算自己应用,具体看removeNetwork源码 * * @param netId wifi的id */ public boolean removeWifi(int netId) { return mWifiManager.removeNetwork(netId); } /** * 移除wifi * * @param SSID wifi名 */ public boolean removeWifi(String SSID) { if (getExitsWifiConfig(SSID) != null) { return removeWifi(getExitsWifiConfig(SSID).networkId); } else { return false; } }到这里基本结束了,TCP、UDP、Wifi更多详情,就下载源码看看吧,测试机小米6(Android8.0),三星S7edge(Andorid7.0),魅蓝note3(Android7.0),oppoR9s(Android7.0)均可以使用。小米6可以收wifi和把这个wifi热点分享出去,所以测试方便。
TCP通信
UDP通信
相关文章推荐
- TCP/UDP 详解 (可靠传输、流量控制、连接管理等核心章节的详解)
- Socket 通信原理 -- Android客户端和服务器以TCP&&UDP方式互通
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制
- Android 6.0 中的 Wifi 连接
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- Android 获取wifi状态 Wifi控制 主动连接wifi
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)(解决不可连的问题,解决方案在最后面)
- 关于TCP和UDP有连接和无连接的理解, 以及服务器间通信原理
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- Android中Socket通信之TCP与UDP传输原理
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- 浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- Android中Socket通信之TCP与UDP传输原理
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通) .
- c#网络通信框架networkcomms内核解析之十一 TCP连接与UDP连接