Android 网络改变状态监听

简介: 1. 网络状态改变使用静态注册还是动态注册回答: 动态注册。因为当App关闭后,我们的应用将不再关心网络状态的改变了。2. 添加必须的权限 3.

1. 网络状态改变使用静态注册还是动态注册

回答: 动态注册。因为当App关闭后,我们的应用将不再关心网络状态的改变了。

2. 添加必须的权限

    <uses-permission android:name="android.permission.INTERNET"/>
    <!--允许读取网络状态-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <!--允许读取wifi网络状态-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

3. 静态注册

        <!--静态注册-->
        <receiver
            android:name=".NetReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
                <action android:name="android.net.wifi.STATE_CHANGE"/>
            </intent-filter>
        </receiver>

4. 动态注册

public class MainActivity extends AppCompatActivity {

    private NetReceiver mReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mReceiver = new NetReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(mReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
    }
}

5. NetReceiver代码

/**
 * 网络状态监听广播
 * 监听网络的改变状态,只有在用户操作网络连接开关(wifi, mobile)的时候接收广播,
 * 然后再对应的界面进行相应的操作,并将状态保存在我们的app里面
 * @author mazaiting
 */
public class NetReceiver extends BroadcastReceiver {
    private static final String TAG = "NetReceiver";
    public NetReceiver() {
    }

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

        /**
         * 这个监听wifi的打开与关闭,与wifi的连接无关
         */
        if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            // 获取Wifi状态
            int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 0);
            Log.e(TAG, "onReceive: " + wifiState);

            switch (wifiState) {
                case WifiManager.WIFI_STATE_ENABLING:
                    // Wifi开启中
                    Log.e(TAG, "onReceive: Wifi开启中");
                    break;
                case WifiManager.WIFI_STATE_ENABLED:
                    // Wifi可用
                    Log.e(TAG, "onReceive: Wifi可用");
                    break;
                case WifiManager.WIFI_STATE_DISABLING:
                    // Wifi关闭中
                    Log.e(TAG, "onReceive: Wifi关闭中");
                    break;
                case WifiManager.WIFI_STATE_DISABLED:
                    // Wifi已关闭
                    Log.e(TAG, "onReceive: Wifi已关闭");
                    break;
                case WifiManager.WIFI_STATE_UNKNOWN:
                    // Wifi状态未知
                    Log.e(TAG, "onReceive: Wifi未知");
                    break;
                default:
                    break;
            }
        }

        /**
         * 监听Wifi的连接状态,即是否连上了一个有效无线路由,当上变广播的状态时WifiManager.WIFI_STATE_DISABLING,
         * 和WIFI_STATE_DISABLED的时候,根本不会解到这个广播在上边广播接到是WifiManager.WIFI_STATE_ENABLED状态
         * 的同时也会接到这个广播,当然刚打开wifi肯定还没有连接到有效的无线
         */
        if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(intent.getAction())) {
            // 获取网络信息
            Parcelable parcelableExtra = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
            if (null != parcelableExtra) {
                // 强转为NetworkInfo对象
                NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
                // 获取网络状态
                NetworkInfo.State state = networkInfo.getState();
                // 判断状态
                boolean isConnection = state == NetworkInfo.State.CONNECTED;
                Log.e(TAG, "onReceive: " + isConnection);
                Toast.makeText(context, "当前状态: " + isConnection , Toast.LENGTH_SHORT).show();
            }
        }

        /**
         * 这个监听网络连接的设置,包括Wifi和移动数据的打开和关闭
         * 最好还是用这个监听,Wifi如果打开,关闭以及链接上可用的连接都会接到监听
         * 这个广播的最大的弊端势必上边两个广播的反应都要慢
         */
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            // 获取连接管理者
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            // 获取网络状态信息
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            // 判断网络信息是否为空并且已连接
            if (null != networkInfo && networkInfo.isConnected()) {
                if (ConnectivityManager.TYPE_WIFI == networkInfo.getType()) {
                    // 判断是否为Wifi
                    Log.e(TAG, "onReceive: 当前Wifi可用");
                    Toast.makeText(context, "当前Wifi可用", Toast.LENGTH_SHORT).show();
                } else if (ConnectivityManager.TYPE_MOBILE == networkInfo.getType()) {
                    // 判断是否为移动网络
                    Log.e(TAG, "onReceive: 当前移动网络可用");
                    Toast.makeText(context, "当前移动网络可用", Toast.LENGTH_SHORT).show();
                }

                Log.e(TAG, "onReceive: info.getTypeName--" + networkInfo.getTypeName());
                Log.e(TAG, "onReceive: getSubtypeName--" + networkInfo.getSubtypeName());
                Log.e(TAG, "onReceive: getState--" + networkInfo.getState());
                Log.e(TAG, "onReceive: getDetailedState().name--" + networkInfo.getDetailedState().name());
                Log.e(TAG, "onReceive: getExtraInfo--" + networkInfo.getExtraInfo());
                Log.e(TAG, "onReceive: getType--" + networkInfo.getType());

            } else {
                Log.e(TAG, "onReceive: 当前没有网络连接,请确保你已经打开网络!");
                Toast.makeText(context, "当前没有网络连接,请确保你已经打开网络!", Toast.LENGTH_SHORT).show();
            }
        }

    }
}
img_e76e9d02360ddc9f93ea5c7c2a2dc6f3.png
执行效果.png

6. 网络工具类NetUtil


/**
 * 网络工具类
 * @author mazaiting
 * @date 2018/3/29
 */

public class NetUtil {
    /**
     * 判断当前网络是否是移动网络
     *
     * @param context 上下文
     * @return boolean 3G
     */
    public static boolean is3G(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetInfo != null
                && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE;
    }

    /**
     * 判断当前网络是否是wifi网络
     *
     * @param context 上下文
     * @return true: wifi; false: 非wifi
     */
    public static boolean isWifi(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetInfo != null
                && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI;
    }

    /**
     * 判断当前网络是否是2G网络
     *
     * @param context 上下文
     * @return true: 2G; false: 不是2G
     */
    public static boolean is2G(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
        if (null != activeNetInfo && (activeNetInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_EDGE
                || activeNetInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_GPRS || activeNetInfo
                .getSubtype() == TelephonyManager.NETWORK_TYPE_CDMA)) {
            return true;
        }
        return false;
    }

    /**
     * wifi是否打开
     * @param context 上下文
     * @return true: 打开; false: 未打开
     */
    public static boolean isWifiEnabled(Context context) {
        ConnectivityManager mgrConn = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        TelephonyManager mgrTel = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        return ((mgrConn.getActiveNetworkInfo() != null && mgrConn
                .getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel
                .getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS);
    }

    /**
     * 判断是否有网络连接
     *
     * @param context 上下文
     * @return 网络连接
     */
    public static boolean isNetworkConnected(Context context) {
        if (null != context) {
            // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
                    .CONNECTIVITY_SERVICE);
            // 获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            //判断NetworkInfo对象是否为空
            if (null != networkInfo) {
                return networkInfo.isAvailable();
            }
        }
        return false;
    }

    /**
     * 判断MOBILE网络是否可用
     *
     * @param context 上下文
     * @return true, 可用; false,不可用
     */
    public static boolean isMobileConnected(Context context) {
        if (context != null) {
            //获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
                    .CONNECTIVITY_SERVICE);
            //获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            //判断NetworkInfo对象是否为空 并且类型是否为MOBILE
            if (null != networkInfo && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                return networkInfo.isAvailable();
            }
        }
        return false;
    }

    /**
     * 获取当前网络连接的类型信息
     * 原生
     *
     * @param context 上下文
     * @return 网络类型
     */
    public static int getConnectedType(Context context) {
        if (null != context) {
            //获取手机所有连接管理对象
            ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
                    .CONNECTIVITY_SERVICE);
            //获取NetworkInfo对象
            NetworkInfo networkInfo = manager.getActiveNetworkInfo();
            if (null != networkInfo && networkInfo.isAvailable()) {
                //返回NetworkInfo的类型
                return networkInfo.getType();
            }
        }
        return -1;
    }

    /**
     * 获取当前的网络状态 :没有网络-0:WIFI网络1:4G网络-4:3G网络-3:2G网络-2
     * 自定义
     *
     * @param context 上下文
     * @return 网络类型
     */
    public static int getApnType(Context context) {
        //结果返回值
        int netType = 0;
        //获取手机所有连接管理对象
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context
                .CONNECTIVITY_SERVICE);
        //获取NetworkInfo对象
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        //NetworkInfo对象为空 则代表没有网络
        if (networkInfo == null) {
            return netType;
        }
        //否则 NetworkInfo对象不为空 则获取该networkInfo的类型
        int nType = networkInfo.getType();
        if (nType == ConnectivityManager.TYPE_WIFI) {
            //WIFI
            netType = 1;
        } else if (nType == ConnectivityManager.TYPE_MOBILE) {
            // 获取子类型
            int nSubType = networkInfo.getSubtype();
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService
                    (Context.TELEPHONY_SERVICE);
            if (nSubType == TelephonyManager.NETWORK_TYPE_LTE
                    && !telephonyManager.isNetworkRoaming()) {
                // 4G
                netType = 4;
            } else if (nSubType == TelephonyManager.NETWORK_TYPE_UMTS
                    || nSubType == TelephonyManager.NETWORK_TYPE_HSDPA
                    || nSubType == TelephonyManager.NETWORK_TYPE_EVDO_0
                    && !telephonyManager.isNetworkRoaming()) {
                //3G   联通的3G为UMTS或HSDPA 电信的3G为EVDO
                netType = 3;
            } else if (nSubType == TelephonyManager.NETWORK_TYPE_GPRS
                    || nSubType == TelephonyManager.NETWORK_TYPE_EDGE
                    || nSubType == TelephonyManager.NETWORK_TYPE_CDMA
                    && !telephonyManager.isNetworkRoaming()) {
                //2G 移动和联通的2G为GPRS或EGDE,电信的2G为CDMA
                netType = 2;
            } else {
                netType = 2;
            }
        }
        return netType;
    }

    /**
     * 获得本机ip地址
     *
     * @return ip地址
     */
    public static String getHostIp() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface
                    .getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface networkInterface = en.nextElement();
                for (Enumeration<InetAddress> ipAdd = networkInterface.getInetAddresses(); ipAdd
                        .hasMoreElements(); ) {
                    InetAddress inetAddress = ipAdd.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        return inetAddress.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

目录
相关文章
|
20天前
|
API Android开发
Android 监听Notification 被清除实例代码
Android 监听Notification 被清除实例代码
|
28天前
|
缓存 网络协议 安全
Android网络面试题之Http基础和Http1.0的特点
**HTTP基础:GET和POST关键差异在于参数传递方式(GET在URL,POST在请求体),安全性(POST更安全),数据大小限制(POST无限制,GET有限制),速度(GET较快)及用途(GET用于获取,POST用于提交)。面试中常强调POST的安全性、数据量、数据类型支持及速度。HTTP 1.0引入了POST和HEAD方法,支持多种数据格式和缓存,但每个请求需新建TCP连接。**
28 5
|
26天前
|
安全 网络协议 算法
Android网络基础面试题之HTTPS的工作流程和原理
HTTPS简述 HTTPS基于TCP 443端口,通过CA证书确保服务器身份,使用DH算法协商对称密钥进行加密通信。流程包括TCP握手、证书验证(公钥解密,哈希对比)和数据加密传输(随机数加密,预主密钥,对称加密)。特点是安全但慢,易受特定攻击,且依赖可信的CA。每次请求可能复用Session ID以减少握手。
27 2
|
1月前
|
缓存 JSON 网络协议
Android面试题:App性能优化之电量优化和网络优化
这篇文章讨论了Android应用的电量和网络优化。电量优化涉及Doze和Standby模式,其中应用可能需要通过用户白名单或电池广播来适应限制。Battery Historian和Android Studio的Energy Profile是电量分析工具。建议减少不必要的操作,延迟非关键任务,合并网络请求。网络优化包括HTTPDNS减少DNS解析延迟,Keep-Alive复用连接,HTTP/2实现多路复用,以及使用protobuf和gzip压缩数据。其他策略如使用WebP图像格式,按网络质量提供不同分辨率的图片,以及启用HTTP缓存也是有效手段。
45 9
|
27天前
|
Android开发
技术经验分享:Android前后台切换的监听
技术经验分享:Android前后台切换的监听
19 2
|
27天前
|
缓存 网络协议 Android开发
Android网络面试题之Http1.1和Http2.0
HTTP/1.1 引入持久连接和管道机制提升效率,支持分块传输编码和更多请求方式如PUT、PATCH。Host字段指定服务器域名,RANGE用于断点续传。HTTP/2变为二进制协议,实现多工处理,头信息压缩和服务器推送,减少延迟并优化资源加载。HTTP不断发展,从早期的简单传输到后来的高效交互。
26 0
Android网络面试题之Http1.1和Http2.0
|
1月前
|
JSON Java API
【Android】使用 Retrofit2 发送异步网络请求的简单案例
**摘要:** Retrofit是Android和Java的HTTP客户端库,简化了RESTful API交互。它通过Java接口定义HTTP请求,并提供注解管理参数、HTTP方法等。要使用Retrofit,首先在AndroidManifest.xml中添加`INTERNET`权限,然后在`build.gradle`中引入Retrofit和Gson依赖。创建服务器响应数据类和描述接口的接口,如`Result`和`Api`。通过Retrofit.Builder配置基础URL并构建实例,之后调用接口方法创建Call对象并发送异步请求。
59 1
|
13天前
|
测试技术 API Android开发
autox.js如何监听异常情况,比如网络中断、内存慢、应用死机或者页面无响应
autox.js如何监听异常情况,比如网络中断、内存慢、应用死机或者页面无响应
|
28天前
|
安全 Java API
Android获取Wi-Fi网络列表
【6月更文挑战第21天】
|
6天前
|
Shell Linux C语言