簡體   English   中英

android廣播接收器OnReceive()延遲導致錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM