如何获得在Android的LTE信号强度dbm的强度

源码版本:4.4
跳过InCallActivity等UI实现。先看service以及底层。
1, 在frameworks/opt下面会发现如下文件列表:
./telephony/src/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
./telephony/src/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
./telephony/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
./telephony/src/java/com/android/internal/telephony/gsm/GsmLteServiceStateTracker.java
./telephony/src/java/com/android/internal/telephony/ServiceStateTracker.java
2, 可以直接进入./telephony/src/java/com/android/internal/telephony/ServiceStateTracker.java 分析,很容易发现类似于如下的代码:
* send signal-strength-changed notification if changed Called both for
* solicited and unsolicited signal strength updates
* @return true if the signal strength changed and a notification was sent.
protected boolean onSignalStrengthResult(AsyncResult ar, boolean isGsm) {
SignalStrength oldSignalStrength = mSignalS
// This signal is used for both voice and data radio signal so parse
// all fields
if ((ar.exception == null) && (ar.result != null)) {
mSignalStrength = (SignalStrength) ar.
mSignalStrength.validateInput();
mSignalStrength.setGsm(isGsm);
log("onSignalStrengthResult() Exception from RIL : " + ar.exception);
mSignalStrength = new SignalStrength(isGsm);
return notifySignalStrength();
  这里主要是结构体的初始化以及上下文环境的简单判断。我们继续追踪notifySignalStrength()
private SignalStrength mLastSignalStrength = null;
protected boolean notifySignalStrength() {
boolean notified = false;
synchronized(mCellInfo) {
if (!mSignalStrength.equals(mLastSignalStrength)) {
mPhoneBase.notifySignalStrength();
notified = true;
} catch (NullPointerException ex) {
loge("updateSignalStrength() Phone already destroyed: " + ex
+ "SignalStrength not notified");
这里有mSignalStrength 和&mLastSignalStrength 两个和信号强度相关的量。算是找到切入点了,信号强度更新的中间点就是这里了。
3,我们先向下分析看有什么可以学习的。&onSignalStrengthResult 是被  frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java中handleMessage在Message Type是    EVENT_GET_SIGNAL_STRENGTH的时候调用的:
case EVENT_GET_SIGNAL_STRENGTH:
// This callback is called when signal strength is polled
// all by itself
if (!(mCi.getRadioState().isOn())) {
// Polling will continue when radio turns back on
ar = (AsyncResult) msg.
onSignalStrengthResult(ar, true);
queueNextSignalStrengthPoll();
4, 到这里就需要对RIL有一定的了解才好继续追下去。RIL的event传到上层之后主要通过一个叫做Registrant的机制分发的。
  我们跳到frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java中去。
  这里有主动去得到signalstrength的方法:
getSignalStrength (Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result, mIs2ndRil);
if (RILJ_LOGD) riljLog(rr.serialString() + "& " + requestToString(rr.mRequest));
  继续往下看,接受到底层发来的数据后通过Registrant Notification:
case RIL_UNSOL_SIGNAL_STRENGTH:
// Note this is set to "verbose" because it happens
// frequently
if (RILJ_LOGV) unsljLogvRet(response, ret);
if (mSignalStrengthRegistrant != null) {
mSignalStrengthRegistrant.notifyRegistrant(
new AsyncResult (null, ret, null));
5, 继续追下去,我们看到有主动通过RIL_REQUEST_SIGNAL_STRENGTH去request signal strength的。
  所以直接在hardware/ril下搜关键字:RIL_REQUEST_SIGNAL_STRENGTH得到结果如下:
./include/telephony/ril.h:1388: * RIL_REQUEST_SIGNAL_STRENGTH
./include/telephony/ril.h:1402:#define RIL_REQUEST_SIGNAL_STRENGTH 19
./libril/ril.cpp:3758:
case RIL_REQUEST_SIGNAL_STRENGTH: return "SIGNAL_STRENGTH";
./libril/ril_commands.h:36:
{RIL_REQUEST_SIGNAL_STRENGTH, dispatchVoid, responseRilSignalStrength},
./reference-ril/reference-ril.c:2093:
case RIL_REQUEST_SIGNAL_STRENGTH:
./reference-ril/ril.h:1388: * RIL_REQUEST_SIGNAL_STRENGTH
./reference-ril/ril.h:1402:#define RIL_REQUEST_SIGNAL_STRENGTH 19
  很明显是hardware/ril/reference-ril/reference-ril.c里面如下函数被调用去查询信号强度了,调用AT command等一看便知:
839 static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
ATResponse *p_response = NULL;
int count =0;
int numofElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
int response[numofElements];
err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
if (err & 0 || p_response-&success == 0) {
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
line = p_response-&p_intermediates-&
err = at_tok_start(&line);
if (err & 0) goto
for (count =0; count & numofE count ++) {
err = at_tok_nextint(&line, &(response[count]));
if (err & 0) goto
RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
at_response_free(p_response);
从上层追到下层基本告一段落,Telephony的其他功能的实现结构都一样,也可以同样通过上述思路去追踪。
涉及到的源码路径基本有:
frameworks/av
frameworks/base
frameworks/opt
packages/apps
hardware/ril
阅读(...) 评论()1518人阅读
Android(17)
android手机信号强度检测
最近在面试的时候被问到一个问题,当手机处于弱网状态下,如何处理,如何监听网络信号强度变化。
这里先了解关于手机信号强度的相关几个概念
文章出处:
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则是表示功率绝对大小的值。
关于对数运算,不记得的自行复习一下了。
下面再来了解一下网络类型吧,还是很多的,不过在国内只要了解国内三大运营商的网络类型大概就可以了。
3G CDMA2000
4G TD-LTE,FDD-LTE
3G TD-SCDMA
4G TD-LTE,FDD-LTE
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 mTextV
public TelephonyManager mTelephonyM
public PhoneStatListener mL
* 网络信号强度监听
* @param savedInstanceState
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);
protected void onResume() {
super.onResume();
mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);
protected void onPause() {
super.onPause();
//用户不在当前页面时,停止监听
mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_NONE);
private class PhoneStatListener extends PhoneStateListener {
//获取信号强度
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);
case NETWORKTYPE_2G:
mTextView.setText(&当前网络为2G移动网络,信号强度为:& + gsmSignalStrength);
case NETWORKTYPE_4G:
mTextView.setText(&当前网络为4G移动网络,信号强度为:& + gsmSignalStrength);
case NETWORKTYPE_NONE:
mTextView.setText(&当前没有网络,信号强度为:& + gsmSignalStrength);
mTextView.setText(&当前网络错误,信号强度为:& + gsmSignalStrength);
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;
mNetWorkType = NETWORKTYPE_NONE;//没有网络
return mNetWorkT
/**判断网络类型*/
private static boolean isFastMobileNetwork(Context context) {
TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
//这里只简单区分两种类型网络,认为4G网络为快速,但最终还需要参考信号值
改进后的方式,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
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);
protected void onResume() {
super.onResume();
mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_SIGNAL_STRENGTHS);
protected void onPause() {
super.onPause();
//用户不在当前页面时,停止监听
mTelephonyManager.listen(mListener, PhoneStatListener.LISTEN_NONE);
private class PhoneStatListener extends PhoneStateListener {
//获取信号强度
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;
mNetWorkType = NETWORKTYPE_NONE;//没有网络
return mNetWorkType;
* 判断网络速度
private boolean isFastMobileNetwork() {
if (mTelephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
//这里只简单区分两种类型网络,认为4G网络为快速,但最终还需要参考信号值
//接收网络状态改变的广播
class NetWorkBroadCastReciver extends BroadcastReceiver {
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:
WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo connectionInfo = manager.getConnectionInfo();
int rssi = connectionInfo.getRssi();
mTextView.setText(&当前为wifi网络,信号强度=& + rssi);
case ConnectivityManager.TYPE_MOBILE:
//移动网络,可以通过TelephonyManager来获取具体细化的网络类型
String netWorkStatus = isFastMobileNetwork() ? &4G网络& : &2G网络&;
mTextView.setText(&当前为& + netWorkStatus + &,信号强度=& + mGsmSignalStrength);
mTextView.setText(&没有可用网络&);
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mNetWorkBroadCastReciver);
关于信号获取流程,这个还需深入研究,目前只在应用层简单获取了网络信号。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11738次
排名:千里之外
原创:29篇
(2)(5)(4)(9)(9)

我要回帖

更多关于 手机信号强度dbm与asu 的文章

 

随机推荐