检查 Wifi 连接时广播接收器未捕获所需的情况
Broadcast receiver doesn't catch required case when checking for Wifi connections
我正在构建一个应用程序,它有两个部分。在第一部分,用户扫描附近的主机点并获取可用网络列表。这部分工作正常。
第二部分,是有问题的部分。在这部分,用户选择要连接的网络,屏幕会相应更新。我实现了一个广播接收器来捕捉用户连接到所选网络的时间。当移动数据关闭时,广播接收器捕捉到正确的情况并且一切正常。但是,如果移动数据打开,广播接收器在连接到 wifi 时不会捕捉到这种情况,尽管我可以看到 phone 已经连接到 wifi。
这是我的广播接收器代码片段:
mConnectivityReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
new Thread(new Runnable() {
@Override
public void run() {
final ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isAvailable()){
Log.e("connectivityReceiver", "networkInfo type " + networkInfo.getTypeName());
switch (networkInfo.getType()){
case ConnectivityManager.TYPE_WIFI://When mobile data is on, I never reach this case
updateUI(networkInfo);
break;
case ConnectivityManager.TYPE_MOBILE:
//do nothing.
break;
}
}
}
public void updateUI(final NetworkInfo networkInfo){
if(networkInfo.isAvailable() && networkInfo.getExtraInfo()!= null){
Log.e("connectivityReceiver","networkInfo extra: " + networkInfo.getExtraInfo());
if(networkInfo.getExtraInfo() != null){
if(networkInfo.getExtraInfo().contains(selectedNetwork)) {
networks.clear();
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
mDiscoverNetworksBtn.setEnabled(true);
mDiscoverNetworksBtn.setVisibility(View.VISIBLE);
mProgressbar.setVisibility(View.GONE);
mWaitMessage.setVisibility(View.GONE);
}
});
unregisterReceiver(mConnectivityReceiver);
}
else if(!networkInfo.getExtraInfo().equals("<unknown ssid>")){
Log.e("connectivityReceiver", "Error occurred while trying to connect to " + selectedNetwork);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(IoTSetupActivity.this, "Error occurred while trying to connect to " + selectedNetwork, Toast.LENGTH_LONG).show();
mProgressbar.setVisibility(View.GONE);
mWaitMessage.setVisibility(View.GONE);
mListview.setVisibility(View.VISIBLE);
}
});
}
}
}
}
}).start();
}
};
这是我用来连接到所选网络的代码片段:
private void connectToNetwork(final Network network){
final WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + network.getNetworkName() + "\"";
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.addNetwork(conf);
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for(WifiConfiguration i : list){
if(i.SSID != null && i.SSID.equals(conf.SSID)){
registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
Log.e("connectToNetwork", "Disconnecting from " + wifiManager.getConnectionInfo().getSSID());
boolean isDisconnected = wifiManager.disconnect();
Log.v("connectToNetwork", "isDisconnected: " + isDisconnected);
boolean isEnabled = wifiManager.enableNetwork(i.networkId, true);
Log.v("connectToNetwork", "isEnabled: " + isEnabled);
Log.e("connectToNetwork", "Trying to reconnect to " + conf.SSID);
boolean isReconnected = wifiManager.reconnect();
Log.v("connectToNetwork", "isReconnected: " + isReconnected);
// Toast.makeText(IoTSetupActivity.this,"Connected to " + conf.SSID, Toast.LENGTH_LONG).show();
break;
}
}
}
根据 Denis 的回答编辑:
public class ConnectivityNetworkCallback extends ConnectivityManager.NetworkCallback{
@Override
public void onAvailable(android.net.Network network) {
super.onAvailable(network);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
mConnectivityManager.bindProcessToNetwork(network);
else
ConnectivityManager.setProcessDefaultNetwork(network);
NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
int connectionType = networkInfo.getType();
Log.e("networkCallback", "connectionType: " + networkInfo.getTypeName());
switch(connectionType){
case ConnectivityManager.TYPE_WIFI:
String networkName = networkInfo.getExtraInfo();
Log.e("networkCallback","network type wifi, extra: " + networkName);
break;
case ConnectivityManager.TYPE_MOBILE:
Log.e("networkCallback","network type mobile, extra: " + networkInfo.getExtraInfo());
break;
}
}
现在我的问题是,当我同时打开移动数据和 Wifi 并在 wifi 网络之间切换时,有时第一个日志会打印我已连接到移动设备,并且当设备连接到新设备时不会再次触发wifi,有时它会打印出我已连接到新的 wifi。
首先,当您调用 enableNetwork(id, true)
时,不需要 wifiManager.reconnect()
,因为它已经尝试连接。
其次,您必须确保您之前没有通过系统设置手动连接到该网络。在这种情况下,您的应用不会连接到它,因为它是不允许的。如果您手动创建了连接,则必须先忘记该网络,以允许该应用程序重新创建该连接。之后,您会在系统设置中看到一个小文本提示是哪个应用创建了该配置。
第三,广播接收器不适合您的尝试。它有太多容易出错的情况。如果您正在处理 Android 5 及更高版本,请使用 ConnectivityManager.NetworkCallback
并监听 onAvailable() 调用。这将确保 wifi 连接已实际设置并可用。
我正在构建一个应用程序,它有两个部分。在第一部分,用户扫描附近的主机点并获取可用网络列表。这部分工作正常。 第二部分,是有问题的部分。在这部分,用户选择要连接的网络,屏幕会相应更新。我实现了一个广播接收器来捕捉用户连接到所选网络的时间。当移动数据关闭时,广播接收器捕捉到正确的情况并且一切正常。但是,如果移动数据打开,广播接收器在连接到 wifi 时不会捕捉到这种情况,尽管我可以看到 phone 已经连接到 wifi。
这是我的广播接收器代码片段:
mConnectivityReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
new Thread(new Runnable() {
@Override
public void run() {
final ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isAvailable()){
Log.e("connectivityReceiver", "networkInfo type " + networkInfo.getTypeName());
switch (networkInfo.getType()){
case ConnectivityManager.TYPE_WIFI://When mobile data is on, I never reach this case
updateUI(networkInfo);
break;
case ConnectivityManager.TYPE_MOBILE:
//do nothing.
break;
}
}
}
public void updateUI(final NetworkInfo networkInfo){
if(networkInfo.isAvailable() && networkInfo.getExtraInfo()!= null){
Log.e("connectivityReceiver","networkInfo extra: " + networkInfo.getExtraInfo());
if(networkInfo.getExtraInfo() != null){
if(networkInfo.getExtraInfo().contains(selectedNetwork)) {
networks.clear();
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
mDiscoverNetworksBtn.setEnabled(true);
mDiscoverNetworksBtn.setVisibility(View.VISIBLE);
mProgressbar.setVisibility(View.GONE);
mWaitMessage.setVisibility(View.GONE);
}
});
unregisterReceiver(mConnectivityReceiver);
}
else if(!networkInfo.getExtraInfo().equals("<unknown ssid>")){
Log.e("connectivityReceiver", "Error occurred while trying to connect to " + selectedNetwork);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(IoTSetupActivity.this, "Error occurred while trying to connect to " + selectedNetwork, Toast.LENGTH_LONG).show();
mProgressbar.setVisibility(View.GONE);
mWaitMessage.setVisibility(View.GONE);
mListview.setVisibility(View.VISIBLE);
}
});
}
}
}
}
}).start();
}
};
这是我用来连接到所选网络的代码片段:
private void connectToNetwork(final Network network){
final WifiConfiguration conf = new WifiConfiguration();
conf.SSID = "\"" + network.getNetworkName() + "\"";
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiManager wifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiManager.addNetwork(conf);
List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
for(WifiConfiguration i : list){
if(i.SSID != null && i.SSID.equals(conf.SSID)){
registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
Log.e("connectToNetwork", "Disconnecting from " + wifiManager.getConnectionInfo().getSSID());
boolean isDisconnected = wifiManager.disconnect();
Log.v("connectToNetwork", "isDisconnected: " + isDisconnected);
boolean isEnabled = wifiManager.enableNetwork(i.networkId, true);
Log.v("connectToNetwork", "isEnabled: " + isEnabled);
Log.e("connectToNetwork", "Trying to reconnect to " + conf.SSID);
boolean isReconnected = wifiManager.reconnect();
Log.v("connectToNetwork", "isReconnected: " + isReconnected);
// Toast.makeText(IoTSetupActivity.this,"Connected to " + conf.SSID, Toast.LENGTH_LONG).show();
break;
}
}
}
根据 Denis 的回答编辑:
public class ConnectivityNetworkCallback extends ConnectivityManager.NetworkCallback{
@Override
public void onAvailable(android.net.Network network) {
super.onAvailable(network);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
mConnectivityManager.bindProcessToNetwork(network);
else
ConnectivityManager.setProcessDefaultNetwork(network);
NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
int connectionType = networkInfo.getType();
Log.e("networkCallback", "connectionType: " + networkInfo.getTypeName());
switch(connectionType){
case ConnectivityManager.TYPE_WIFI:
String networkName = networkInfo.getExtraInfo();
Log.e("networkCallback","network type wifi, extra: " + networkName);
break;
case ConnectivityManager.TYPE_MOBILE:
Log.e("networkCallback","network type mobile, extra: " + networkInfo.getExtraInfo());
break;
}
}
现在我的问题是,当我同时打开移动数据和 Wifi 并在 wifi 网络之间切换时,有时第一个日志会打印我已连接到移动设备,并且当设备连接到新设备时不会再次触发wifi,有时它会打印出我已连接到新的 wifi。
首先,当您调用 enableNetwork(id, true)
时,不需要 wifiManager.reconnect()
,因为它已经尝试连接。
其次,您必须确保您之前没有通过系统设置手动连接到该网络。在这种情况下,您的应用不会连接到它,因为它是不允许的。如果您手动创建了连接,则必须先忘记该网络,以允许该应用程序重新创建该连接。之后,您会在系统设置中看到一个小文本提示是哪个应用创建了该配置。
第三,广播接收器不适合您的尝试。它有太多容易出错的情况。如果您正在处理 Android 5 及更高版本,请使用 ConnectivityManager.NetworkCallback
并监听 onAvailable() 调用。这将确保 wifi 连接已实际设置并可用。