android - 以编程方式连接到热点(无互联网)的 android 设备切换回带互联网的 wifi
问题描述
对不起我的英语不好。我正在编写代码以连接到另一个 android 设备热点。它得到连接。但是,就我而言,热点将没有互联网。现在连接的设备切换回另一个带有互联网的 wifi 网络。除了我的方式之外,还有什么更好的方式来连接热点吗?我的代码如下:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout);
AppCompatButton btnConnect=findViewById(R.id.btnConnect);
btnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
registerReceiver(mWifiBroadcastReceiver , new IntentFilter("android.net.wifi.STATE_CHANGE"));
EditText eSSID=findViewById(R.id.ssid);
EditText ePassword=findViewById(R.id.password);
String ssid = eSSID.getText().toString();
String key = ePassword.getText().toString();
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = String.format("\"%s\"" , ssid);
wifiConfig.preSharedKey = String.format("\"%s\"" , key);
connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
int netId = wifiManager.addNetwork(wifiConfig);
wifiManager.disconnect();
wifiManager.enableNetwork(netId , true);
wifiManager.reconnect();
}
});
}
接收者是:
private BroadcastReceiver mWifiBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context , Intent intent) {
switch (intent.getAction()) {
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean isConnected = info.isConnected();
boolean isConnecting = info.isConnectedOrConnecting();
//TODO: probably better to use the EXTRA_ info here
String ssid = wifiManager.getConnectionInfo() != null ?
wifiManager.getConnectionInfo().getSSID() : null;
ssid = normalizeAndroidWifiSsid(ssid);
String stateName = "";
switch (info.getState()) {
case CONNECTED:
stateName = "connected";
break;
case CONNECTING:
stateName = "connecting";
break;
case DISCONNECTED:
stateName = "disconnected";
break;
case DISCONNECTING:
stateName = "disconnecting";
break;
case SUSPENDED:
stateName = "suspended";
break;
case UNKNOWN:
stateName = "unknown";
break;
}
if (Build.VERSION.SDK_INT >= 21) {
if (isConnected) {
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
final String connectedSsid = ssid;
connectivityManager.registerNetworkCallback(builder.build() , new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
//This is always the SSID if it's wifi, even though this is *not* documented
String networkSsid = networkInfo.getExtraInfo();
if (networkSsid.equals(connectedSsid)) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context,"Connected Successfully",Toast
.LENGTH_LONG).show();
}
});
/*
* We can now use network.openURLConnection and network.getSocketFactory()
* to communicate using the wifi network that has no Internet
*/
connectivityManager.unregisterNetworkCallback(this);
}
}
});
}
}
break;
}
}
};
解决方案
由于 Android 中 WiFi 处理的异步性质,我将专注于这 4 行寻找解决方案
int netId = wifiManager.addNetwork(wifiConfig);
wifiManager.disconnect();
wifiManager.enableNetwork(netId , true);
wifiManager.reconnect();
disconnect
并且reconnect
这里的调用是错误的,它们只是混淆了内部 wifi 状态机。使用设置为的enableNetwork
参数调用足以以编程方式选择 wifi。boolean attemptConnect
true
所以只需使用:
int netId = manager.addNetwork(wifiConfig);
manager.enableNetwork(netId, true);
老实说,我尝试过扫描内部资源,但内部状态机相当复杂。如果您有兴趣,您可以在此处查找状态机,并在此处查看 wifi 配置数据库是如何处理的。
此外,为避免有多个配置条目,在调用 addNetwork 之前,请检查已创建的配置以查找要连接的 SSID,然后仅调用enableNetwork
.
List<WifiConfiguration> networks = manager.getConfiguredNetworks();
for(WifiConfiguration c : networks) {
if (isThisWifiAppSpecific(c.SSID)) {
manager.enableNetwork(c.networkId, true);
return;
}
}
我在生产中使用它并且工作正常。从未在低于 24 的 API 级别进行测试。
推荐阅读
- java - 如何正确地为密码做一个while循环
- reactjs - TypeError:无法获取未定义或空引用的属性“文本”
- javascript - 使用立即需要该状态进行 API 调用的 useState 挂钩时,如何等待 setState 调用完成?
- react-native - 类 FBSDKPackage 中的构造函数 FBSDKPackage 不能应用于给定类型
- java - 在不删除前一个圆圈的情况下绘制圆圈
- installation - 安装 TIBCO 以构建 EAR 文件
- google-sheets - 如何避免在对两列求和的查询顶部看到“sum()”?
- ios - UITableViewCell Auto Layout crashed
- java - 坚持使用最大值适用于小值但不适用于大值
- python - 在火车上运行分类器不起作用