当我断开 wifi 时,用于检查互联网连接的广播接收器被调用两次

Broadcast receiver to check internet connection is called twice when i disconnect wifi

这是检查网络连接的BroadcastReceiver,当我断开wifi时它显示"No Internet" toast两次。

InternetDetector.java

package com.hfad.evenit;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;

/**
 * Created by Vicky on 26-Sep-15.
 */

public class InternetDetector extends BroadcastReceiver {
    public InternetDetector() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {


        boolean isVisible = MyApplication.isActivityVisible();

        try {
            if (isVisible == true) {
                ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

                // Check internet connection and accrding to state change the
                // text of activity by calling method
                if (networkInfo != null && networkInfo.isConnected())
                {
                    Toast.makeText(context, "Internet Available", Toast.LENGTH_SHORT).show();
                } else
                {
                    Toast.makeText(context, "No Internet", Toast.LENGTH_SHORT).show();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.hfad.evenit" >

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".EnterPhoneNumber"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateVisible" />
        <activity
            android:name=".EnterVerificationCode"
            android:label="@string/title_activity_enter_verification_code"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateVisible" />
        <activity
            android:name=".GetNameAndEmail"
            android:label="@string/title_activity_get_name_and_email"
            android:screenOrientation="portrait"
            android:windowSoftInputMode="stateVisible" />
        <activity
            android:name=".Launcher"
            android:label="@string/title_activity_launcher"
            android:screenOrientation="portrait" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Home"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
             >
        </activity>
        <activity
            android:name=".SettingsActivity"
            android:label="@string/title_activity_settings"
            android:screenOrientation="portrait">
        </activity>
        <receiver
            android:name=".InternetDetector"
            android:enabled="true" >
            <intent-filter>
                <!-- Intent filters for broadcast receiver -->
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>
    </application>

</manifest>

我尝试了几种解决方案,但其中 none 似乎有效。

ConnectivityManager 发送各种 intent 来通知不同的状态,所以这很正常,你不是只捕获互联网 on/off 变化,这个功能有更多的选项,见 here了解更多详情。

UPD,解决方法如下:

public class InternetDetector extends BroadcastReceiver {
    public InternetDetector() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {     
        boolean isVisible = MyApplication.isActivityVisible();

        try {
            if (isVisible == true) {
                ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

                // Check internet connection and accrding to state change the
                // text of activity by calling method
                if ((networkInfo != null) && (networkInfo.getState() == NetworkInfo.State.CONNECTED)) {
                   Toast.makeText(context, "Internet Available", Toast.LENGTH_SHORT).show();
                } else {
                   Toast.makeText(context, "No Internet", Toast.LENGTH_SHORT).show();
                }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

我想这能帮上忙。我已经更新了你的接收器。试试这个肯定对你有帮助。

package com.hfad.evenit;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;

/**
 * Created by Vicky on 26-Sep-15.
 */

public class InternetDetector extends BroadcastReceiver {

    private boolean isConnected = false;

    public InternetDetector() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        boolean isVisible = MyApplication.isActivityVisible();

        try {
            if (isVisible == true) {
                isNetworkAvailable(context);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null) {
                for (int i = 0; i < info.length; i++) {
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        if (!isConnected) {
                            Log.v(LOG_TAG, "Now you are connected to Internet!");
                            Toast.makeText(context, "Internet availablle via Broadcast receiver", Toast.LENGTH_SHORT).show();
                            isConnected = true;
                            // do your processing here ---
                            // if you need to post any data to the server or get
                            // status
                            // update from the server
                        }
                        return true;
                    }
                }
            }
        }
        Log.v(LOG_TAG, "You are not connected to Internet!");
        Toast.makeText(context, "Internet NOT availablle via Broadcast receiver", Toast.LENGTH_SHORT).show();
        isConnected = false;
        return false;
    }

}

正如在 Android 文档中提到的,只要连接状态发生变化,也可以在设备从移动数据移动到 WIFI 等时发送此广播。

Changes to a device's connectivity can be very frequent—this broadcast is triggered every time you move between mobile data and Wi-Fi.

source

连接的状态很多,都可以找到in docs

要检查网络连接的当前状态,您应该使用 getActiveNetworkInfo()

因此您检查状态的方法可能如下所示:

 private void checkNetworkState(){
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();

    if(activeNetworkInfo == null){
        //no network
    } else {
        NetworkInfo.State state = activeNetworkInfo.getState();

        switch (state){
            case CONNECTED:
                break;
            case CONNECTING:
                break;
            case DISCONNECTED:
                break;
            case DISCONNECTING:
                break;
            case SUSPENDED:
                break;
            case UNKNOWN:
                break;
        }
    }
}

记住权限:android.Manifest.permission.ACCESS_NETWORK_STATE

您需要声明一个变量 b 以删除重复的操作。

boolean b = true;
if(b){
   // do something, in the first trigger
}else{
   //do nothing, cancel trigger
}
b = !b;

BroadcastReceiver connectivityReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();

        boolean isConnectedToData;

        final int currentType = activeNetwork != null
                ? activeNetwork.getType() : NO_CONNECTION_TYPE;

        if (sLastType != currentType) {
            if (activeNetwork != null) {
                boolean isWiFi = ConnectivityManager.TYPE_WIFI == currentType;
                boolean isMobile = ConnectivityManager.TYPE_MOBILE == currentType;

                if (isWiFi || isMobile) {
                    boolean isConnected = activeNetwork.isConnectedOrConnecting();
                    if (isConnected) {
                        isConnectedToData = isConnected;
                    } else {
                        isConnectedToData = false;
                    }
                } else {
                    isConnectedToData = false;
                }
                // TODO Connected. Do your stuff!
            } else {
                // TODO Disconnected. Do your stuff!
                isConnectedToData = false;
            }
            sLastType = currentType;

            if (connectivityReceiverListener != null) {
                connectivityReceiverListener.onNetworkConnectionChanged(isConnectedToData);
            }
        }

    }
};