Andorid网络编程获得移动LTE 4G的dbm信号强度

Introduction

Android官方api中SignalStrength类无法获取移动4G LTE的dbm信号强度,这里fork了weilinhu的获取手机电量,网络链接,信号强度的项目,并添加了对移动4G LTE信号强度的解析。

运行app

git clone下来项目以后,直接在anroid studio中打开即可编译运行。由于只是个测试项目,基本没有界面,可以直接阅读源码:


int currentSignalStrength = PhoneStateUtils.getCurrentSignalStrength();
Log.e(TAG, "currentSignalStrength: "+currentSignalStrength);

可以看到当前信号强度变量,顺着getCurrentSignalStrength()函数定义过去:


public static int getCurrentSignalStrength(){
  return MyPhoneStateListener.sPosition;
}

MyPhoneStateListener


package com.zhanshow.mylibrary.phonestate;

import android.app.Activity;
import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.zhanshow.mylibrary.log.LogToFile;

import java.util.ArrayList;
import java.util.List;

/**
 * @author weilinhu
 */

public class MyPhoneStateListener extends PhoneStateListener {

    protected List<MyPhoneStateListener.MyPhoneStateListenerListener> listeners = new ArrayList<>();
    private Object lock = new Object();
    public static int sMark = -1;
    private TelephonyManager tel;
//    中国移动的是 46000
//    中国联通的是 46001
//    中国电信的是 46003
    private String STRNetworkOperator[] = { "46000", "46001", "46003" };
    private boolean is3Ghave = false;
    public static int sPosition;
    int signal;
    public MyPhoneStateListener(Activity activity) {
        tel = (TelephonyManager)activity.getSystemService(Context.TELEPHONY_SERVICE);
    }

    private SignalStrength signalStrength;
    @Override
    public void onSignalStrengthsChanged(SignalStrength signalStrength) {
        super.onSignalStrengthsChanged(signalStrength);

        String signalInfo = signalStrength.toString();
        String[] params = signalInfo.split(" ");

        if(sMark <0)
        {
            getmark();
        }
        if (sMark == 0) {
            if(tel.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE){
                //4G网络 最佳范围   >-90dBm 越大越好
                LogToFile.e("PhoneState","4G");
                signal = Integer.parseInt(params[11]);
            }else{
                LogToFile.e("PhoneState", "2G");
                signal = signalStrength.getGsmSignalStrength();
            }
            getLevel();
        } else if (sMark == 1) {
            signal = signalStrength.getCdmaDbm();
            getLevel();
        } else if (sMark == 2) {
            signal = signalStrength.getEvdoDbm();
            getLevel();
        }else {
            sPosition = 0;
        }
        LogToFile.e("PhoneState", String.format("signalStrength.getGsmSignalStrength(); %d \t signalStrength.getCdmaDbm();%d\tsignalStrength.getEvdoDbm();%d",signalStrength.getGsmSignalStrength(),signalStrength.getCdmaDbm(), signalStrength.getEvdoDbm()));
        notifyStateToAll();
    }


    public void addListener(MyPhoneStateListener.MyPhoneStateListenerListener l) {
        synchronized(lock) {
            listeners.add(l);
        }
    }

    public void removeListeners() {
        synchronized(lock) {
            listeners.clear();
        }
    }

    private void notifyStateToAll() {
        synchronized(lock) {
            for (MyPhoneStateListener.MyPhoneStateListenerListener listener : listeners) {
                notifyState(listener);
            }

        }
    }
    private void notifyState(MyPhoneStateListener.MyPhoneStateListenerListener listener) {
        if (listener!=null){
            listener.onSignalStrengthsChanged(sPosition);
        }

    }

    public interface MyPhoneStateListenerListener {
        public void onSignalStrengthsChanged(int singnaStrength);
    }

    private void getmark()//得到当前电话卡的归属运营商
    {
        String strNetworkOperator = tel.getNetworkOperator();
        LogToFile.e("MainActivity", strNetworkOperator);
        if (strNetworkOperator != null) {
            for (int i = 0; i < 3; i++) {
                if (strNetworkOperator.equals(STRNetworkOperator[i])) {
                    sMark = i;
                    break;
                }
            }
        } else {
            sMark = -1;
        }
    }





    private void getLevel() {
        LogToFile.e("MainActivity",  "signal " + signal);
        // TODO Auto-generated method stub
        if (sMark == 2) {//电信3g信号强度的分类,可以按照ui自行划分等级
            if (signal >= -65)
                sPosition = 5;
            else if (signal >= -75)
                sPosition = 4;
            else if (signal >= -85)
                sPosition = 3;
            else if (signal >= -95)
                sPosition = 2;
            else if (signal >= -105)
                sPosition = 1;
            else
                sPosition = 0;
        }
        if (sMark == 1) {//联通3g信号划分
            if (signal >= -75)
                sPosition = 5;
            else if (signal >= -80)
                sPosition = 4;
            else if (signal >= -85)
                sPosition = 3;
            else if (signal >= -95)
                sPosition = 2;
            else if (signal >= -100)
                sPosition = 1;
            else
                sPosition = 0;
        }
        if (sMark == 0) {//移动信号的划分,这个不是很确定是2g还是3g
            if (signal <= 2 || signal == 99)
                sPosition = 0;
            else if (signal >= 12)
                sPosition = 5;
            else if (signal >= 10)
                sPosition = 4;
            else if (signal >= 8)
                sPosition = 3;
            else if (signal >= 5)
                sPosition = 2;
            else
                sPosition = 1;
        }
    }


}

找到在包mylibrarypackage com.zhanshow.mylibrary.phonestateMyPhoneStateListener.java类,即是signalstrength获取的主类。

可以看到原作者重载了onSignalStrengthsChanged函数,当信号发生变化时,判断是哪一家运营商,然后获得对应的signal强度,而在getLevel函数里,则将相应的信号强度进行了等级划分,不再是简单的输出dbm值。

移动4G无法获取dbm值

经过测试,发现官网的signalstrength api中,int getGsmSignalStrength ()函数不能获得移动4G的信号强度值,[Android——获取手机当前信号强度(dbm/asu值)](http://blog.csdn.net/cdzz11/article/details/52197732)文章给出了另一种方法,获取LTE网络和3G/2G网络的信号强度的方式有一点不同, LTE网络强度是通过解析字符串获取的, 3G/2G网络信号强度是通过API接口函数完成的。


@Override  
public void onSignalStrengthsChanged(SignalStrength signalStrength) {  
  super.onSignalStrengthsChanged(signalStrength);  
  String signalInfo = signalStrength.toString();  
  String[] params = signalInfo.split(" ");  
  if(tm.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE){  
    //4G网络 最佳范围   >-90dBm 越大越好  
    int Itedbm = Integer.parseInt(params[9]);  
    setDBM(Itedbm+"");  

  }else

对原项目进行修改的部分:


 +  /*@author: FindHao
 +        * 添加对移动4G的信号解析支持
 +        * */
 +        String signalInfo = signalStrength.toString();
 +        String[] params = signalInfo.split(" ");
          if(sMark <0)
          {
              getmark();
          }
          if (sMark == 0) {
 -            signal = signalStrength.getGsmSignalStrength();
 +            if(tel.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE){
 +                Log.e("SignalState","4G");
 +                /*@author: FindHao
 +                * 这里不同手机,dbm信号有不同的index*/
 +                signal = Integer.parseInt(params[11]);
 +            }else{
 +                Log.e("SignalState", "2G");
 +                signal = signalStrength.getGsmSignalStrength();
 +            }
              getLevel();
          } else if (sMark == 1) {

下面的信号强度分级getLevel函数当然也需要相应的完善。

dbm信号强弱

诺基亚手机和iPhone 4信号强度与格数对比

诺基亚手机和iPhone 4信号强度与格数对比

dBm 和 asu 都用来表示手机信号强度,其中 dBm 是通用单位,asu 是安卓手机特有单位。

dBm 是一个表示功率绝对值的值(也可以认为是以 1mW 功率为基准的一个比值),计算公式为:10log(功率值/1mw)。

[例] 如果功率 P 为 1mw,折算为 dBm 后为 0dBm。

[例] 对于 0.01mW 的功率,按 dBm 单位进行折算后的值应为:10log(0.01/1) = -20dBm。

这个数值越大,表明信号越好。由于手机信号强度一般较小,折算成为 dBm 一般都是负数。asu 是英文 alone signal unit 的简写,是 google 为 android 设备定义的信号强度单位。

Reference

Android——获取手机当前信号强度(dbm/asu值)

Android将Log写入文件

andorid 官网signalstrength api

信号多少才算强?dbm和asu信号单位解析

文章版权归 FindHao 所有丨本站默认采用CC-BY-NC-SA 4.0协议进行授权|
转载必须包含本声明,并以超链接形式注明作者 FindHao 和本文原始地址:
https://www.findhao.net/easycoding/2105

你可能喜欢:(相似内容推荐和广告都使用了谷歌的推荐系统,需要对本站取消广告屏蔽才能显示。感谢点击↓广告支持博主~)

Find

新浪微博(FindSpace博客)QQ群:不安分的Coder(375670127) 不安分的Coder

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*