[英]android broadcast receiver OnReceive() delay causing errors
我的廣播接收器偵聽WiFi的ssid更改,如果ssid更改,則返回布爾值WifiChanged true。我在另一個活動中檢查此布爾值,該活動根據返回的值是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。
有很多方法可以完成這項工作。
我更喜歡使用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"
。 此String值必須與從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(...)
發送一次。 無論哪個活動在該前景/收聽中,將接收該廣播並對其進行操作。
到那時為時已晚
在上面討論的解決方案中將不存在此問題。
你的方法不正確。 您的廣播接收器應向您的活動發送消息,然后您的活動應使用“onNewIntent”方法檢查WiFi狀態。 然后,如果你在接收器中設置一個靜態變量(你可能不應該這樣做),你可以檢查它,但最好只是發送你的Activity一個帶有WiFi狀態的布爾“額外”。
問題是你的UI線程比后台線程快得多。 因此,如果活動正在響應接收者也在響應的事件,那么Android很可能會優先考慮活動在后台線程上的處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.