我的广播接收器监听WiFi ssid更改,如果ssid发生更改,则返回布尔值WifiChanged true。我在另一个活动中检查此布尔值,该活动根据返回的值更改列表,无论是真还是假。默认情况下布尔值为false。
我故意改变wifi,它应该触发广播接收器将布尔值返回到true并相应地设置列表,但实际发生的是我的列表基于布尔值更改为false,因为广播接收器需要一段时间才能返回价值。在下面的日志中,您可以看到布尔值为false,并且在0.58秒后大约ssid发生变化。到那时为时已晚
08-08 16:43:54.487: D/PlayerManager(20733): Did Wi-Fi Changed: false
|
|
|
08-08 16:43:55.047: V/ConnectionChangeReceiver(20733): onReceive(Context context, Intent intent)
08-08 16:43:55.077: D/ConnectionChangeReceiver(20733): ssid changed from s_ssid="Walter_Meth_Lab" to newSsid="Kings_Landing"
这是我的OnReceive()
public class ConnectionChangeReceiver extends BroadcastReceiver {
private static final String TAG = "ConnectionChangeReceiver";
private static String s_ssid = null;
private static String s_ipAddress = null;
private static String mNetworkType;
private static ConnectionChangeReceiver sInstance;
private ConnectionChangeListener mConnectionChangeListener;
private boolean mHasWifiChanged;
public static ConnectionChangeReceiver getInstance() {
Log.v(TAG, "getInstance()");
synchronized (ConnectionChangeReceiver.class) {
if (sInstance == null) {
sInstance = new ConnectionChangeReceiver();
}
}
return sInstance;
}
public boolean WifiChanged() {
return mHasWifiChanged;
}
public void setConnectionChangeListener(final ConnectionChangeListener listener) {
this.mConnectionChangeListener = listener;
}
@Override
public void onReceive(final Context context, final Intent intent) {
Log.v(TAG, "onReceive(Context context, Intent intent)");
mHasWifiChanged = false;
String newSsid = null;
String action = intent.getAction();
if ((action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) || (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION))
|| (action.equals("android.net.conn.CONNECTIVITY_CHANGE"))) {
NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (networkInfo != null) {
if (networkInfo.getTypeName().equals("WIFI")) {
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
if (wm != null) {
WifiInfo connectionInfo = wm.getConnectionInfo();
if (connectionInfo != null) {
newSsid = connectionInfo.getSSID();
if ((newSsid != null) && (s_ssid != null) && (newSsid.compareTo(s_ssid) != 0)) {
Log.d(TAG, "ssid changed from s_ssid=" + s_ssid + " to newSsid=" + newSsid);
mHasWifiChanged = true;
}
}
}
}
}
}
s_ssid = newSsid;
这是我使用布尔值
的另一个活动boolean WifiChanged = ConnectionChangeReceiver.getInstance().WifiChanged();
Log.d(TAG, "Did Wi-Fi Changed:" + WifiChanged);
if (WifiChanged) {
//Do Something
}
如果更改了Wi-Fi ssid,则列表应根据WifiChanged更改为true,但WifiChanged将始终更改为false,因为ChangeReceiver()未按时返回true并且使用默认false。
答案 0 :(得分:5)
有很多方法可以完成这项工作。
我更喜欢使用LocalBroadcastManager
。
这是如何工作的:让ConnectionChangeReceiver
传递 - ,当它可用时,而不是让活动要求提供信息。完成ConnectionChangeReceiver
处理收到的intent
后,会发出local
广播。如果你的活动是活着的并且正在倾听,它会对此作出反应。
// Snippet from your `ConnectionChangeReceiver # onReceive(...)` method
if (connectionInfo != null) {
newSsid = connectionInfo.getSSID();
if ((newSsid != null) && (s_ssid != null) && (newSsid.compareTo(s_ssid) != 0)) {
Log.d(TAG, "ssid changed from s_ssid=" + s_ssid + " to newSsid=" + newSsid);
mHasWifiChanged = true;
// We can send a local broadcast now
// Note that the String `"com.my.app.wifi.WIFI_RELATED_CHANGE"` can be
// customized to your preference
Intent localIntent = new Intent("com.my.app.wifi.WIFI_RELATED_CHANGE");
// Including this extra is redundant here since `mHasWifiChanged` will
// always be true at this point. I am including it for example sake.
// Again, notice that the key `"com.my.app.wifi.WIFI_HAS_CHANGED"` can
// be customized
localIntent.putExtra("com.my.app.wifi.WIFI_HAS_CHANGED", mHasWifiChanged);
// Broadcasts the Intent to receivers in this app
LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
}
}
在活动方面:在您的活动中创建BroadcastReceiver
并将其设置为侦听操作"com.my.app.wifi.WIFI_RELATED_CHANGE"
。此字符串值必须与从ConnectionChangeReceiver # onReceive(...)
发送广播时使用的值相同:
// Declared as a class member in your Activity
BroadcastReceiver wifiRelatedChangeListener = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("com.my.app.wifi.WIFI_RELATED_CHANGE")) {
// In your current setup, `mHasWifiChanged` will always be true
// Act on it
}
}
};
您应该将BroadcastReceiver
声明为类成员。这将允许您适当地注册和取消注册BroadcastReceiver
:在onResume()
中注册并在onPause()
中取消注册。
在onResume()
您的活动中,注册此接收器以倾听行动com.my.app.wifi.WIFI_RELATED_CHANGE
:
@Override
public void onResume() {
super.onResume();
// Activity has come to foreground. Register to listen for changes to wifi state.
// Create an IntentFilter with action `com.my.app.wifi.WIFI_RELATED_CHANGE`
IntentFilter intentFilter = new IntentFilter("com.my.app.wifi.WIFI_RELATED_CHANGE");
// Register your broadcastreceiver to receive broadcasts
// with action `com.my.app.wifi.WIFI_RELATED_CHANGE`
LocalBroadcastManager.getInstance(this)
.registerReceiver(wifiRelatedChangeListener, intentFilter);
}
取消注册onPause()
中的接收者:
@Override
public void onPause() {
super.onPause();
// Activity is going to background. No need to listen anymore
LocalBroadcastManager.getInstance(this).unregisterReceiver(wifiRelatedChangeListener);
}
请注意,您可以在许多活动中声明wifiRelatedChangeListener
之类的接收器。广播从ConnectionChangeReceiver # onReceive(...)
发送一次。无论那个前景/收听的活动是什么,都会收到这个广播并对其采取行动。
到那时为时已晚
此问题不会出现在上面讨论的解决方案中。
答案 1 :(得分:2)
你的方法不正确。您的广播接收器应向您的活动发送消息,然后您的活动应使用“onNewIntent”方法检查WiFi状态。然后,如果你在你的接收器中设置一个静态变量(你可能不应该这样做),你可以检查它,但最好只是发送你的Activity一个带有WiFi状态的布尔“额外”。
问题是您的UI线程比后台线程快得多。因此,如果活动正在响应接收者也在响应的事件,那么Android很可能会优先考虑活动在后台线程上的处理。