最近公司要开发智能家居,APP要作为遥控器和控制中心,其中的原理就是智能设备开机先作为一个热点,发射Wifi信号,然后手机连上这个热点(Wifi控制),手机和智能设备建立了连接后,将家里路由器wifi的账号密码通过TCP协议,Socket通信发送给智能设备,最后智能设备收到后就能连上家里的路由器了。
<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" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<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);
}
}
public WifiControlUtils(Context context)
{
//获取wifiManager对象
mWifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
}
2.Wifi 的信息 WifiInfo,获取之前,要先判断 WifiManager 是否为空,因为 Wifi 状态会经常改变,所以获取之前判断一下是否为空,而且每次都重新获取,拿最新的 Wifi 信息。
/**
* 获取wifi连接信息
**/
public WifiInfo getWifiInfo()
{
if (mWifiManager != null)
{
return mWifiManager.getConnectionInfo();
}
return null;
}
3.Andorid 6.0以上的版本,权限改变,连接Wifi不一样。
对于从来都没连接过的 Wifi,或者是删除过的 Wifi(相当于没连接过),和以前一样,只要用 SSID (Wifi名)、密码、加密方式创建新的 WifiConfiguration,无密码的就是要 SSID;然后 mWifiManager.enableNetwork 就连上了。
/**
* 连接指定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;
}
}