Android创建wifi热点爬坑总结
最近想学习下Android上打开热点的方法,在网上找了好多篇相关的博客,代码基本上都是一个样子,都是几年前的老代码了,现在根本行不通。好在爬坑了一下午,终于给爬出来了。
1.下面先说一下Android开启wifi热点的基本套路。
首先需要获取到WifiManager系统服务类,获取方式如下
WifiManager mWifiManager = (WifiManager) context.getApplicationContext().getSystemService(context.WIFI_SERVICE);
由于目前安卓系统上开启wifi热点的api方法不稳定,谷歌没有向开发者开放这个方法,将其隐藏了,也就是下面这个。
setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)
因此我们需要利用java的反射机制来调用这个方法,解释下上面的两个参数。
WifiConfiguration :配置wifi热点的一些参数,包括热点名称,密码,加密方式等
boolean :是否开启热点
public void createWifitHot(String name, String password) { try { //wifi和热点不能同时打开,所以先判断wifi是否打开,打开则关闭 if (mWifiManager.isWifiEnabled()) { mWifiManager.setWifiEnabled(false); } //java反射机制得到Method Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class); //配置热点信息 WifiConfiguration config = new WifiConfiguration(); config.SSID = name; config.preSharedKey = password; config.hiddenSSID = true; config.status = WifiConfiguration.Status.ENABLED; config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); config.allowedKeyManagement.set(4); config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); //通过java反射调用WifiManager的setWifiApEnabled方法 method.invoke(mWifiManager, config, true); } catch (Exception e) { e.printStackTrace(); } }
注意:
1. password这个参数,密码至少要包含8个字符,否则热点创建失败。
2. config.allowedKeyManagement.set(4)这个方法是用来设置热点的加密方式,这个4代表什么意思呢,谷歌向开发者暴露的参数只有下面这4个。
public static final int NONE = 0;
public static final int WPA_PSK = 1;
public static final int WPA_EAP = 2;
public static final int IEEE8021X = 3
网上找的一些代码这里填的就是WifiConfiguration.KeyMgmt.WPA_PSK,如果你在6.0以上的手机上运行你会发现代码上设置了wifi密码,但开启热点后并没有加密,而是开放的。因为6.0后的手机只有WPA2_PSK这种加密方式,但是这种加密方式谷歌没有暴露给开发者,好在通过WifiConfiguration的源码得知WPA2_PSK这种加密方式的int值为4,所以就明白这里的4是怎么来的了。
补充:在小米MiUi系统上测试时会出现加密安全性为无的情况,原因是小米系统对WPA2_PSK值做了更改,(官方值为4,小米为6,如果指定为4,小米会变为无密码热点)。请使用下面代码来创建加密热点。
int indexOfWPA2_PSK = 4;//从WifiConfiguration.KeyMgmt数组中查找WPA2_PSK的值for (int i = 0; i < WifiConfiguration.KeyMgmt.strings.length; i++) { if (WifiConfiguration.KeyMgmt.strings[i].equals("WPA2_PSK")) { indexOfWPA2_PSK = i; break; }}apConfig.allowedKeyManagement.set(indexOfWPA2_PSK);
2 关闭热点就比较简单了,利用java反射机制把setWifiApEnabled方法的boolean参数设为false即可。
public void closeWifiHot() { try { Method method = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class); method.invoke(mWifiManager, null, false); } catch (Exception e) { e.printStackTrace(); } }
最后别忘了在Manifest文件里添加相应权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/><uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>//允许修改系统设置<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
注意,别得意的太早。此处还有坑,在6.0以上的系统,由于安全机制,修改系统的设置还需要在Manifest文件里添加允许修改系统设置权限,并在java代码里申请。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 判断是否有WRITE_SETTINGS权限if(!Settings.System.canWrite(this)) if (!Settings.System.canWrite(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 1); } else { //创建热点 ... ... } }
然后重写onActivityResult方法处理
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 判断是否有WRITE_SETTINGS权限 if (Settings.System.canWrite(this)) { //创建热点 ... ... } else { //没有权限 ... ... } } } super.onActivityResult(requestCode, resultCode, data); }
最后附上监听热点状态方法,监听系统发出的广播即可。
BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ("android.net.wifi.WIFI_AP_STATE_CHANGED".equals(action)) { //state状态为:10---正在关闭;11---已关闭;12---正在开启;13---已开启 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0); switch (state) { case int: ... ... break; } } }};IntentFilter mIntentFilter = new IntentFilter("android.net.wifi.WIFI_AP_STATE_CHANGED");registerReceiver(mReceiver, mIntentFilter);
至此,所有的坑就爬完了。感谢阅读!
更多相关文章
- Mars Android视频学习笔记——01_16_SQLite使用方法
- android 登陆、提交数据或加载数据时提示页面
- Flutter 混合开发(Android)Flutter跟Native相互通信
- Android中ViewGroup等容器控件的使用
- Android高效编程注意事项
- Android的SDK,NDK以及JNI
- Android之Action Bar
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用