java - android广播接收器OnReceive()延迟导致错误

标签 java android

我的广播接收器监听 WiFi ssid 更改,如果 ssid 更改,它返回 boolean 值 WifiChanged true。我在另一个 Activity 中检查这个 boolean 值,该 Activity 根据返回的值更改列表,无论它是真还是假。默认情况下 boolean 值是 false。

我有意更改应触发广播接收器将 boolean 值返回为 true 并相应地设置列表的 wifi,但实际发生的是我的列表根据 boolean 值 false 更改,因为广播接收器需要一段时间才能返回值(value)。在下面的日志中,您可以看到 boolean 值为 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 值的另一个 Activity

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

这将如何工作:不是让 Activity 请求信息,而是让 ConnectionChangeReceiver 交付它 - 当它可用时ConnectionChangeReceiver 处理完接收到的 intent 后,它会发送一个 local 广播。如果您的 Activity 是活跃的并且正在聆听,它就会对此使用react。

// 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);
    }
}

在 Activity 方面:在您的 Activity 中创建一个 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() 中取消注册。

在您的 Activity 的 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);
}

请注意,您可以在许多 Activity 中声明一个接收器,例如 wifiRelatedChangeListener。广播从 ConnectionChangeReceiver # onReceive(...) 发送一次。无论此时哪个 Activity 在前台/正在收听,都将收到此广播并据此采取行动。

By that time its too late

这个问题不会出现在上面讨论的解决方案中。

关于java - android广播接收器OnReceive()延迟导致错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25215280/

相关文章:

android - Gradle:错误:包 com.nostra13.universalimageloader.core 不存在

java - android - ListView 和适配器不显示任何项目:(

java - 关闭应用程序时如何停止声音

java - 如何在 super 关键字内使用具有多个条件的三元运算符?

Java 应用程序 : Windows Service interacting with the system tray icon

java - Java 中的规范化/取消重音文本

java - 未调用跳过 Activity onActivityResult

JavaFX Scene Builder 在不同的包/ Controller 上处理 OnAction

java - 为什么 javaFX Circle.getCenterX 在这种情况下不起作用?

java - F-Droid.com 上的 R.java 文件