背景
现在安卓系统已经更新到8.0了。曾经打开手机wifi以及搜索wifi的方法可能对8.0的安卓系统不管用了。这里就提一些在开发中遇到的坑。
一. 打开wifi 以及 关闭wifi
首先需要开启修改系统设置的权限:
private void createWifiHotspot(){
if(wifiManager.isWifiEnabled()){
wifiManager.setWifiEnabled(false);
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d("MainActivity","Android 8.0及以上");
if(!Settings.System.canWrite(this)){
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS, Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
}
else{
setWifiApEnabledForAndroid_O();
}
return;
}
Log.d("MainActivity","Android 8.0及以下");
setWifiApEnabledForAndroid();
}
然后如果是SDK26以上的版本,就用下面的代码打开或关闭wifi。
在网上也能搜到一些别人提到的教程,管用的是这个:
public void setWifiApEnabledForAndroid_O(){
ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
Field iConnMgrField;
try{
iConnMgrField = connManager.getClass().getDeclaredField("mService");
iConnMgrField.setAccessible(true);
Object iConnMgr = iConnMgrField.get(connManager);
Class<?> iConnMgrClass = Class.forName(iConnMgr.getClass().getName());
Method startTethering = iConnMgrClass.getMethod("startTethering",int.class,ResultReceiver.class,boolean.class);
startTethering.invoke(iConnMgr,0,null,true);
Toast.makeText(getApplicationContext(),"热点创建成功",Toast.LENGTH_SHORT).show();
}catch (Exception e){
e.printStackTrace();
}
}
private void closeWifiHotspot_O(){
ConnectivityManager connManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
Field iConnMgrField;
try{
iConnMgrField = connManager.getClass().getDeclaredField("mService");
iConnMgrField.setAccessible(true);
Object iConnMgr = iConnMgrField.get(connManager);
Class<?> iConnMgrClass = Class.forName(iConnMgr.getClass().getName());
Method stopTethering = iConnMgrClass.getMethod("stopTethering",int.class);
stopTethering.invoke(iConnMgr,0);
Toast.makeText(getApplicationContext(),"热点关闭成功",Toast.LENGTH_SHORT).show();
}catch (Exception e){
e.printStackTrace();
}
}
记得申请对应的权限
二. 搜索wifi
其实还是用WifiManager对象的startScan()方法,但是需要申请ACCESS_COARSE_LOCATION权限,而且要动态获取。
三. 连接wifi后创建热点,却无法用socket连接上server
具体情况是:一部手机创建热点作为sever,开启新的线程,在线程里利用ServerSocket监听连接。另一部手机作为client,连接上热点后,利用WifiManager的实例的方法getDhcpInfo() 连接Server。然鹅,连接超时或连接拒绝。
原来是需要在manifest文件中申请两个权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />//向sd卡写入
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />//读取sd卡信息