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方法处理

@Override
protected 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);

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

你可能感兴趣的:(Android)