最近想学习下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);

至此,所有的坑就爬完了。感谢阅读!

更多相关文章

  1. Mars Android视频学习笔记——01_16_SQLite使用方法
  2. android 登陆、提交数据或加载数据时提示页面
  3. Flutter 混合开发(Android)Flutter跟Native相互通信
  4. Android中ViewGroup等容器控件的使用
  5. Android高效编程注意事项
  6. Android的SDK,NDK以及JNI
  7. Android之Action Bar
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android中屏幕亮度相关设置
  2. Android(安卓)点击按钮,文本文字改变
  3. Android(安卓)获取XML,DRAWABLE资源
  4. android 指南针
  5. MTK Android(安卓)P(9.0) userdebug版本
  6. Anubis,一个支持Android(安卓)apk(Androi
  7. How to Enable USB Debugging Mode on An
  8. android 涂鸦
  9. Android(安卓)Http网络数据传输备忘
  10. Android中通过当前经纬度获得城市