Подтвердить что ты не робот

BroadcastReceiver получает несколько идентичных сообщений для одного события

Я зарегистрировал приемник, который прослушивает сетевые события:

<receiver 
    android:label="NetworkConnection"
    android:name=".ConnectionChangeReceiver" >
    <intent-filter >
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>
Приемник

также очень прост:

public class ConnectionChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
                Log.v("@@@","Receiver : " + activeNetInfo);
        } else {
            Log.v("@@@","Receiver : " + "No network");
        }
    }
}

Проблема в том, что когда Wifi подключен, я получаю 3 одинаковых сообщения подряд, например:

Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true
Receiver : NetworkInfo: type: WIFI[], state: CONNECTED/CONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true

Все они "ПОДКЛЮЧЕНЫ/ПОДКЛЮЧЕНЫ" (не должны ли они быть чем-то вроде CONNECTING/OBTAINING_IPADDR и т.д.), поэтому проблема в том, как я могу сказать, когда она действительно подключена? У меня есть некоторые подпрограммы, которые я хочу сделать, когда wifi действительно подключен, и я не хочу, чтобы их вызывали три раза подряд.

PS: 3G отправляет только одно сообщение, поэтому здесь нет проблем.

Обновление:

Похоже на проблему с устройством.

Для теста я взял 2 Desire HD и 4 случайных телефона Android (различные модели Aquos и некоторые китайские вещи без названия). Как на DHD, так и на одном случайном телефоне на wifi connect я получил 3 сообщения, на оставшихся телефонах я получил только одно сообщение. WTF.

4b9b3361

Ответ 1

Получение нескольких широковещательных сообщений - это проблема устройства. Некоторые телефоны просто отправляют одну трансляцию, а другие отправляют 2 или 3. Но есть работа вокруг:

Предполагая, что вы получите сообщение об отключении, когда Wi-Fi отключен, я бы предположил, что первый из них правильный, а другой 2 - просто эхо по какой-либо причине.

Чтобы узнать, что сообщение было вызвано, вы можете иметь статическое логическое значение, которое переключается между подключением и отключением и вызывает вызовы подпрограмм при получении соединения, а логическое значение - true. Что-то вроде:

public class ConnectionChangeReceiver extends BroadcastReceiver {
    private static boolean firstConnect = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
            if(firstConnect) { 
                // do subroutines here
                firstConnect = false;
            }
        }
        else {
            firstConnect= true;
        }
    }
}

Ответ 2

Вы также можете кэшировать в статическом поле последний обработанный тип соединения и проверять на наличие встроенных трансляций. Таким образом, вы получите только один канал для каждого типа подключения.

Когда тип подключения будет изменен, он, очевидно, будет работать. Когда устройство выходит из соединения, activeNetworkInfo будет иметь значение null, а currentType будет NO_CONNECTION_TYPE, как в случае по умолчанию.

public class ConnectivityReceiver extends BroadcastReceiver {

    /** The absence of a connection type. */
    private static final int NO_CONNECTION_TYPE = -1;

    /** The last processed network type. */
    private static int sLastType = NO_CONNECTION_TYPE;

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        final int currentType = activeNetworkInfo != null
                ? activeNetworkInfo.getType() : NO_CONNECTION_TYPE;

        // Avoid handling multiple broadcasts for the same connection type
        if (sLastType != currentType) {
            if (activeNetworkInfo != null) {
                boolean isConnectedOrConnecting = activeNetworkInfo.isConnectedOrConnecting();
                boolean isWiFi = ConnectivityManager.TYPE_WIFI == currentType;
                boolean isMobile = ConnectivityManager.TYPE_MOBILE == currentType;

                // TODO Connected. Do your stuff!
            } else {
                // TODO Disconnected. Do your stuff!
            }

            sLastType = currentType;
        }
}

Ответ 3

В моем случае я регистрировал свои BroadcastReceivers в onResume и только отменял их в onDestroy.

Это заставило каждую трансляцию трансляции регистрироваться 3 или 4 раза в зависимости от того, сколько раз активность возобновляется.

Настройка вашего трансляционного транслятора в нужном месте с точки зрения жизненного цикла активности позволит вам прекратить несколько путающих вызовов.

Ответ 4

Зарегистрируйте свой LocalBroadcastreceiver в oncreate() сам не в onResume(). незарегистрированный в onDestroy

Ответ 5

У меня есть приложение, которое загружает данные, когда пользователь возвращается в онлайн. Поскольку мой широковещательный приемник может получать намерение несколько раз, это может привести к загрузке данных более одного раза. Чтобы справиться с этим, я использую службу, которая ничего не сделает, если она уже запущена.

Широковещательный приемник:

public class ConnectionChangeReceiver extends BroadcastReceiver {
    private static boolean firstConnect = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (activeNetInfo != null) {
            startService();
        }   
    }
}

Услуги:

public class MyService extends Service {
    private boolean mRunning;

    @Override
    public void onCreate() {
        super.onCreate();
        mRunning = false;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (!mRunning) {
            mRunning = true;
            uploadTheData();
        }
        return super.onStartCommand(intent, flags, startId);
    }
}