zoukankan      html  css  js  c++  java
  • 转:Android 判断用户2G/3G/4G移动数据网络

    Android 判断用户2G/3G/4G移动数据网络

    在做 Android App 的时候,为了给用户省流量,为了不激起用户的愤怒,为了更好的用户体验,是需要根据用户当前网络情况来做一些调整的,也可以在 App 的设置模块里,让用户自己选择,在 2G / 3G / 4G 网络条件下,是否允许请求一些流量比较大的数据。

    通过 Android 提供的 TelephonyManager 和 ConnectivityManager 都可以获取到 NetworksInfo 对象,可以通过 getType() 获取类型,判断是 wifi 还是 mobile ,如果是 mobile ,可以通过 NetworksInfo 对象的 getSubType() 和 getSubTypeName() 可以获取到对于的网络类型和名字。

    网络类型和名字定义在 TelephonyManager 类里。

    /** Network type is unknown */
    public static final int NETWORK_TYPE_UNKNOWN = 0;
    /** Current network is GPRS */
    public static final int NETWORK_TYPE_GPRS = 1;
    /** Current network is EDGE */
    public static final int NETWORK_TYPE_EDGE = 2;
    /** Current network is UMTS */
    public static final int NETWORK_TYPE_UMTS = 3;
    /** Current network is CDMA: Either IS95A or IS95B*/
    public static final int NETWORK_TYPE_CDMA = 4;
    /** Current network is EVDO revision 0*/
    public static final int NETWORK_TYPE_EVDO_0 = 5;
    /** Current network is EVDO revision A*/
    public static final int NETWORK_TYPE_EVDO_A = 6;
    /** Current network is 1xRTT*/
    public static final int NETWORK_TYPE_1xRTT = 7;
    /** Current network is HSDPA */
    public static final int NETWORK_TYPE_HSDPA = 8;
    /** Current network is HSUPA */
    public static final int NETWORK_TYPE_HSUPA = 9;
    /** Current network is HSPA */
    public static final int NETWORK_TYPE_HSPA = 10;
    /** Current network is iDen */
    public static final int NETWORK_TYPE_IDEN = 11;
    /** Current network is EVDO revision B*/
    public static final int NETWORK_TYPE_EVDO_B = 12;
    /** Current network is LTE */
    public static final int NETWORK_TYPE_LTE = 13;
    /** Current network is eHRPD */
    public static final int NETWORK_TYPE_EHRPD = 14;
    /** Current network is HSPA+ */
    public static final int NETWORK_TYPE_HSPAP = 15;
    

    看到这个代码和注释,相信没有这方面知识的人很难看懂,都啥玩意?这注释跟没注释有啥区别?!就是让人看着更加闹心而已。所以说,注释对阅读代码的人很重要。当然这些东西可能太专业了,写这些代码的人估计是想写也不知道该怎么了,得写多大一坨啊?!我在最后会贴上一些我整理的资料,可以供大家参考一下,不是很详细,也不专业,就是大概有个印象。

    TelephonyManager 还提供了 getNetworkTypeName(int type) 的方法,这个方法可以返回一个字符串,但是信息量不大。

    那怎么判断是 2G , 3G 还是 4G 网络呢?TelephonyManager 还提供了另外一个方法,getNetworkClass(int networkType) ,但这个方法被隐藏掉了,我把代码贴一下。

    public static int getNetworkClass(int networkType) {
        switch (networkType) {
            case NETWORK_TYPE_GPRS:
            case NETWORK_TYPE_EDGE:
            case NETWORK_TYPE_CDMA:
            case NETWORK_TYPE_1xRTT:
            case NETWORK_TYPE_IDEN:
        return NETWORK_CLASS_2_G;
            case NETWORK_TYPE_UMTS:
            case NETWORK_TYPE_EVDO_0:
            case NETWORK_TYPE_EVDO_A:
            case NETWORK_TYPE_HSDPA:
            case NETWORK_TYPE_HSUPA:
            case NETWORK_TYPE_HSPA:
            case NETWORK_TYPE_EVDO_B:
            case NETWORK_TYPE_EHRPD:
            case NETWORK_TYPE_HSPAP:
        return NETWORK_CLASS_3_G;
            case NETWORK_TYPE_LTE:
        return NETWORK_CLASS_4_G;
            default:
        return NETWORK_CLASS_UNKNOWN;
        }
    }
    

      然后下面是这几个常量的值。

    /** Unknown network class. {@hide} */
    public static final int NETWORK_CLASS_UNKNOWN = 0;
    /** Class of broadly defined "2G" networks. {@hide} */
    public static final int NETWORK_CLASS_2_G = 1;
    /** Class of broadly defined "3G" networks. {@hide} */
    public static final int NETWORK_CLASS_3_G = 2;
    /** Class of broadly defined "4G" networks. {@hide} */
    public static final int NETWORK_CLASS_4_G = 3;
    

      

    不知道为啥要把这些东西给隐藏起来,然道是不靠谱?!还是其他的更好的方式?!不知道,先这样吧,现在通过上面的手段,是可以知道用户用的是什么网络,当然也可以区分出来用户使用的是 2G , 3G 还是 4G 了。当然,你获取到这些数据后,你也可以推算出用户用的是哪家公司的网络,移动的,联通的,还是电信的,当然,只在中国。而且虚拟运营商开始真正上市后,这个就区分不出来是京东的,还是国美,苏宁的了,但是你可以知道你的手机号用的是联通的网还是移动的网。

    最后贴上我收集整理的一些资料,可以参考一下。

    • GPRS : 2G(2.5) General Packet Radia Service 114kbps
    • EDGE : 2G(2.75G) Enhanced Data Rate for GSM Evolution 384kbps
    • UMTS : 3G WCDMA 联通3G Universal Mobile Telecommunication System 完整的3G移动通信技术标准
    • CDMA : 2G 电信 Code Division Multiple Access 码分多址
    • EVDO_0 : 3G (EVDO 全程 CDMA2000 1xEV-DO) Evolution - Data Only (Data Optimized) 153.6kps - 2.4mbps 属于3G
    • EVDO_A : 3G 1.8mbps - 3.1mbps 属于3G过渡,3.5G
    • 1xRTT : 2G CDMA2000 1xRTT (RTT - 无线电传输技术) 144kbps 2G的过渡,
    • HSDPA : 3.5G 高速下行分组接入 3.5G WCDMA High Speed Downlink Packet Access 14.4mbps
    • HSUPA : 3.5G High Speed Uplink Packet Access 高速上行链路分组接入 1.4 - 5.8 mbps
    • HSPA : 3G (分HSDPA,HSUPA) High Speed Packet Access
    • IDEN : 2G Integrated Dispatch Enhanced Networks 集成数字增强型网络 (属于2G,来自维基百科)
    • EVDO_B : 3G EV-DO Rev.B 14.7Mbps 下行 3.5G
    • LTE : 4G Long Term Evolution FDD-LTE 和 TDD-LTE , 3G过渡,升级版 LTE Advanced 才是4G
    • EHRPD : 3G CDMA2000向LTE 4G的中间产物 Evolved High Rate Packet Data HRPD的升级
    • HSPAP : 3G HSPAP 比 HSDPA 快些

    有朋友说他是移动 4G 的网络,获取到的是 17。于是我又去翻了一下源码,找到了如下的代码。也就是说当有新的类型被支持的时候,Android 会增加对于的类型代码。确实 17 是 NETWORKTYPETD_SCDMA 也就是移动的那一坨。其他的代码就不贴了,大概就是这个意思。下面的代码是5.1的代码。

    /** Network type is unknown */
    public static final int NETWORK_TYPE_UNKNOWN = 0;
    /** Current network is GPRS */
    public static final int NETWORK_TYPE_GPRS = 1;
    /** Current network is EDGE */
    public static final int NETWORK_TYPE_EDGE = 2;
    /** Current network is UMTS */
    public static final int NETWORK_TYPE_UMTS = 3;
    /** Current network is CDMA: Either IS95A or IS95B*/
    public static final int NETWORK_TYPE_CDMA = 4;
    /** Current network is EVDO revision 0*/
    public static final int NETWORK_TYPE_EVDO_0 = 5;
    /** Current network is EVDO revision A*/
    public static final int NETWORK_TYPE_EVDO_A = 6;
    /** Current network is 1xRTT*/
    public static final int NETWORK_TYPE_1xRTT = 7;
    /** Current network is HSDPA */
    public static final int NETWORK_TYPE_HSDPA = 8;
    /** Current network is HSUPA */
    public static final int NETWORK_TYPE_HSUPA = 9;
    /** Current network is HSPA */
    public static final int NETWORK_TYPE_HSPA = 10;
    /** Current network is iDen */
    public static final int NETWORK_TYPE_IDEN = 11;
    /** Current network is EVDO revision B*/
    public static final int NETWORK_TYPE_EVDO_B = 12;
    /** Current network is LTE */
    public static final int NETWORK_TYPE_LTE = 13;
    /** Current network is eHRPD */
    public static final int NETWORK_TYPE_EHRPD = 14;
    /** Current network is HSPA+ */
    public static final int NETWORK_TYPE_HSPAP = 15;
    /** Current network is GSM {@hide} */
    public static final int NETWORK_TYPE_GSM = 16;
     /** Current network is TD_SCDMA {@hide} */
    public static final int NETWORK_TYPE_TD_SCDMA = 17;
    /** Current network is IWLAN {@hide} */
    public static final int NETWORK_TYPE_IWLAN = 18;
    

      示例:

    ////////
    	/*
    	 * 前边注释和后边注释是后来加的判断网络类型
    	 */
    	//WIFI("wifi", 1), G2("2G", 2), G3("3G", 3), WAP("wap", 4), NO("invalid", 5), ALL(
    	//"all", 6), G4("4G",7);
    	private static final int NETWORK_TYPE_UNAVAILABLE = 5;  
    	    // private static final int NETWORK_TYPE_MOBILE = -100;  
    	private static final int NETWORK_TYPE_WIFI = 1;  
    	  
    	private static final int NETWORK_CLASS_WIFI = 1;  
    	private static final int NETWORK_CLASS_UNAVAILABLE = 5;  
    	    /** Unknown network class. */  
    	private static final int NETWORK_CLASS_UNKNOWN = 6;  
    	    /** Class of broadly defined "2G" networks. */  
    	    private static final int NETWORK_CLASS_2_G = 2;  
    	    /** Class of broadly defined "3G" networks. */  
    	    private static final int NETWORK_CLASS_3_G = 3;  
    	    /** Class of broadly defined "4G" networks. */  
    	    private static final int NETWORK_CLASS_4_G = 7;  
    	/** 
         * 获取网络类型 
         *  
         * @return 
         */  
        public String getCurrentNetworkType() {  
            int networkClass = getNetworkClass();  
            String type = "未知";  
            switch (networkClass) {  
            case NETWORK_CLASS_UNAVAILABLE:  
                type = "无";  
                break;  
            case NETWORK_CLASS_WIFI:  
                type = "Wi-Fi";  
                break;  
            case NETWORK_CLASS_2_G:  
                type = "2G";
                break;  
            case NETWORK_CLASS_3_G:  
                type = "3G";  
                break;  
            case NETWORK_CLASS_4_G:  
                type = "4G";  
                break;  
            case NETWORK_CLASS_UNKNOWN:  
                type = "未知";  
                break;  
            }  
            return type;  
        }  
      
        private int getNetworkClassByType(int networkType) {  
            switch (networkType) {  
            case TelephonyManager.NETWORK_TYPE_GPRS:  
            case TelephonyManager.NETWORK_TYPE_EDGE:  
            case TelephonyManager.NETWORK_TYPE_CDMA:  
            case TelephonyManager.NETWORK_TYPE_1xRTT:  
            case TelephonyManager.NETWORK_TYPE_IDEN:  
                return NETWORK_CLASS_2_G;  
            case TelephonyManager.NETWORK_TYPE_UMTS:  
            case TelephonyManager.NETWORK_TYPE_EVDO_0:  
            case TelephonyManager.NETWORK_TYPE_EVDO_A:  
            case TelephonyManager.NETWORK_TYPE_HSDPA:  
            case TelephonyManager.NETWORK_TYPE_HSUPA:  
            case TelephonyManager.NETWORK_TYPE_HSPA:  
            case TelephonyManager.NETWORK_TYPE_EVDO_B:  
            case TelephonyManager.NETWORK_TYPE_EHRPD:  
            case TelephonyManager.NETWORK_TYPE_HSPAP:  
                return NETWORK_CLASS_3_G;  
            case TelephonyManager.NETWORK_TYPE_LTE:  
                return NETWORK_CLASS_4_G;  
            default:  
                return NETWORK_CLASS_UNKNOWN;  
            }  
        }  
        private int getNetworkClass() {  
        	
            connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); 
    	    networkInfo = connectivityManager.getActiveNetworkInfo(); 
               
                if (networkInfo != null&& networkInfo.isConnected()) {  
                    int type = networkInfo.getType();  
                    if (type == ConnectivityManager.TYPE_WIFI) {  
                    	mNetWorkType =  NetEnum.WIFI.getID();
                    } else if (type == ConnectivityManager.TYPE_MOBILE) {  
                        TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(  
                                        Context.TELEPHONY_SERVICE);  
                        mNetWorkType = getNetworkClassByType(telephonyManager.getNetworkType());
                    }  
                } else {  
                	mNetWorkType = NETWORK_TYPE_UNAVAILABLE;  
                }  
             return mNetWorkType;
            } 
    
        ////
    

      参考博客:http://blog.binkery.com/android/networks_type.html

    http://www.eoeandroid.com/thread-540327-1-1.html?_dsign=77a59737

    最近在项目中用到啦,总结了下。。。。大部分都是别人总结好的,就直接拿过来啦,哈哈。。

  • 相关阅读:
    [HNOI2019]JOJO
    [TJOI2019]唱、跳、rap和篮球
    [ZJOI2019]开关
    jzoj5746
    [JSOI2019]神经网络(指数生成函数)
    [TJOI2019]甲苯先生的线段树
    [JSOI2019]节日庆典
    XSY1519
    XSY1528
    springboot actuator监控笔记
  • 原文地址:https://www.cnblogs.com/jycboy/p/5152686.html
Copyright © 2011-2022 走看看