android手机信号强度检测

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011394071/article/details/53198672

android手机信号强度检测

  • 最近在面试的时候被问到一个问题,当手机处于弱网状态下,如何处理,如何监听网络信号强度变化。
  • 这里先了解关于手机信号强度的相关几个概念

文章出处:http://blog.csdn.net/fuchengbo000/article/details/42740357

Android手机信号强度介绍

  • android定义了2种信号单位:dBm和asu。它们之间的关系是:dBm =-113+2asu,这是google给android手机定义的特有信号单位。例如,我的信号强度为-53dBm,则对应30asu,因为-53 = -113 + (230) 。

详细介绍两者:

  • asu:alone signal unit 独立信号单元,是一种模拟信号。ASU仅仅代表手机将它的位置传递给附近的信号塔的速率。它和dBm测量的是一样的东西,但是是以一种更加线性的方式来表示。
  • dBm:是一个表示功率绝对值的值(也可以认为是以1mW功率为基准的一个比值),计算公式为:10log(功率值/1mw)。

     [例] 如果功率P为1mw,折算为dBm后为0dBm。
     [例] 对于0.01mW的功率,按dBm单位进行折算后的值应为: 10log(0.01/1)=-20dBm。
    
     这个数值越大,表明信号越好。由于手机信号强度一般较小,折算成为dBm一般都是负数。
     中国移动的规范规定,手机接收电平>=(城市取-90dBm;乡村取-94dBm) 时,则满足覆盖要求,
    
    
     也就是说此处无线信号强度满足覆盖要求.-67dBm要比-90dBm信号要强20多个dB,
    
     那么它在打电话接通成功率和通话过程中的话音质量都会好的多。再引入一个相关概念dB。
    
  • dB:是一个表征相对值的值,纯粹的比值,只表示两个量的相对大小关系,没有单位,当考虑甲的功率相比于乙功率大或小多少个dB时,按下面的计算公式:10log(甲功率/乙功率),如果采用两者的电压 比计算,要用20log(甲电压/乙电压)。

[例] 甲功率比乙功率大一倍,那么10lg(甲功率/乙功率)=10lg2=3dB,即甲的功率比乙的功率大3 dB。反之,如果甲的功率是乙的功率的一半,则甲的功率比乙的功率小3 dB。

总结:dBm是负数,越接近0信号强度越高,信号越好,但不可能为0。asu为正数,值越大信号越好。dB是两个量之间的比值,表示两个量间的相对大小,而dBm则是表示功率绝对大小的值。

  • 关于对数运算,不记得的自行复习一下了。
  • 下面再来了解一下网络类型吧,还是很多的,不过在国内只要了解国内三大运营商的网络类型大概就可以了。

    电信
    2G CDMA
    3G CDMA2000
    4G TD-LTE,FDD-LTE
    
    移动
    2G GSM
    3G TD-SCDMA
    4G TD-LTE,FDD-LTE
    
    联通
    2G GSM
    3G WCDMA
    4G TD-LTE,FDD-LTE
    
  • 而谷歌API给我们提供的有19种类型,在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;
        /** 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;
    

下面通过一些实例来测试一下吧

  • 首先记得加权限

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

  • 实例代码

  • 原来的方式,只通过监听信号改变来区分网络类型

public class MainActivity extends AppCompatActivity {

    private static final int NETWORKTYPE_WIFI = 0;
    private static final int NETWORKTYPE_4G = 1;
    private static final int NETWORKTYPE_2G = 2;
    private static final int NETWORKTYPE_NONE = 3;
    public TextView mTextView;
    public TelephonyManager mTelephonyManager;
    public PhoneStatListener mListener;

    /**
     * 网络信号强度监听
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.textview);
        //获取telephonyManager
        mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        //开始监听
        mListener = new PhoneStatListener();
        //监听信号强度
        mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);
    }

    @Override
    protected void onPause() {
        super.onPause();
        //用户不在当前页面时,停止监听
        mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_NONE);
    }

    private class PhoneStatListener extends PhoneStateListener {
        //获取信号强度

        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            super.onSignalStrengthsChanged(signalStrength);
            //获取网络信号强度
            //获取0-4的5种信号级别,越大信号越好,但是api23开始才能用
//            int level = signalStrength.getLevel();
            int gsmSignalStrength = signalStrength.getGsmSignalStrength();
//获取网络类型
            int netWorkType = getNetWorkType(MainActivity.this);
            switch (netWorkType) {
                case NETWORKTYPE_WIFI:
                    mTextView.setText("当前网络为wifi,信号强度为:" + gsmSignalStrength);
                    break;
                case NETWORKTYPE_2G:
                    mTextView.setText("当前网络为2G移动网络,信号强度为:" + gsmSignalStrength);
                    break;
                case NETWORKTYPE_4G:
                    mTextView.setText("当前网络为4G移动网络,信号强度为:" + gsmSignalStrength);
                    break;
                case NETWORKTYPE_NONE:
                    mTextView.setText("当前没有网络,信号强度为:" + gsmSignalStrength);
                    break;
                case -1:
                    mTextView.setText("当前网络错误,信号强度为:" + gsmSignalStrength);
                    break;
            }
        }
    }


    public static int getNetWorkType(Context context) {
        int mNetWorkType = -1;
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            String type = networkInfo.getTypeName();
            if (type.equalsIgnoreCase("WIFI")) {
                mNetWorkType = NETWORKTYPE_WIFI;
            } else if (type.equalsIgnoreCase("MOBILE")) {
                return isFastMobileNetwork(context) ? NETWORKTYPE_4G : NETWORKTYPE_2G;
            }
        } else {
            mNetWorkType = NETWORKTYPE_NONE;//没有网络
        }
        return mNetWorkType;
    }

    /**判断网络类型*/
    private static boolean isFastMobileNetwork(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
            //这里只简单区分两种类型网络,认为4G网络为快速,但最终还需要参考信号值
            return true;
        }
        return false;
    }
}

  • 改进后的方式,wifi的信号通过wifimanager来监听,更精确,并且通过广播的方式更灵敏

    
package org.skxy.www.networksingstrange;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private static final int NETWORKTYPE_WIFI = 0;
    private static final int NETWORKTYPE_4G = 1;
    private static final int NETWORKTYPE_2G = 2;
    private static final int NETWORKTYPE_NONE = 3;
    public TextView mTextView;
    public TelephonyManager mTelephonyManager;
    public PhoneStatListener mListener;
    public int mGsmSignalStrength;
    private NetWorkBroadCastReciver mNetWorkBroadCastReciver;

    /**
     * 网络信号强度监听
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextView = (TextView) findViewById(R.id.textview);
        //获取telephonyManager
        mTelephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        //开始监听
        mListener = new PhoneStatListener();
        /**由于信号值变化不大时,监听反应不灵敏,所以通过广播的方式同时监听wifi和信号改变更灵敏*/
        mNetWorkBroadCastReciver = new NetWorkBroadCastReciver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
        registerReceiver(mNetWorkBroadCastReciver, intentFilter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);
    }

    @Override
    protected void onPause() {
        super.onPause();
        //用户不在当前页面时,停止监听
        mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_NONE);
    }

    private class PhoneStatListener extends PhoneStateListener {
        //获取信号强度

        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            super.onSignalStrengthsChanged(signalStrength);
            //获取网络信号强度
            //获取0-4的5种信号级别,越大信号越好,但是api23开始才能用
//            int level = signalStrength.getLevel();
            mGsmSignalStrength = signalStrength.getGsmSignalStrength();
            //网络信号改变时,获取网络信息
            getNetWorkInfo();
        }
    }

    /**暂时不用这个方法*/
    public int getNetWorkType(Context context) {
        int mNetWorkType = -1;
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            String type = networkInfo.getTypeName();
            if (type.equalsIgnoreCase("WIFI")) {
                mNetWorkType = NETWORKTYPE_WIFI;
            } else if (type.equalsIgnoreCase("MOBILE")) {
                return isFastMobileNetwork() ? NETWORKTYPE_4G : NETWORKTYPE_2G;
            }
        } else {
            mNetWorkType = NETWORKTYPE_NONE;//没有网络
        }
        return mNetWorkType;
    }

    /**
     * 判断网络速度
     */
    private boolean isFastMobileNetwork() {
        if (mTelephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
            //这里只简单区分两种类型网络,认为4G网络为快速,但最终还需要参考信号值
            return true;
        }
        return false;
    }

    //接收网络状态改变的广播
    class NetWorkBroadCastReciver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            getNetWorkInfo();
        }
    }

    /**
     * 获取网络的信息
     */
    private void getNetWorkInfo() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable()) {
            switch (info.getType()) {
                case ConnectivityManager.TYPE_WIFI:
                    //wifi
                    WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
                    WifiInfo connectionInfo = manager.getConnectionInfo();
                    int rssi = connectionInfo.getRssi();
                    mTextView.setText("当前为wifi网络,信号强度=" + rssi);
                    break;
                case ConnectivityManager.TYPE_MOBILE:
                    //移动网络,可以通过TelephonyManager来获取具体细化的网络类型
                    String netWorkStatus = isFastMobileNetwork() ? "4G网络" : "2G网络";
                    mTextView.setText("当前为" + netWorkStatus + ",信号强度=" + mGsmSignalStrength);
                    break;
            }
        } else {
            mTextView.setText("没有可用网络");
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mNetWorkBroadCastReciver);
    }
}
  • 关于信号获取流程,这个还需深入研究,目前只在应用层简单获取了网络信号。

猜你喜欢

转载自blog.csdn.net/u011394071/article/details/53198672