手机信号强度

在android手机上,通过“设置”-“关于手机”-“状态”-“信号强度”可以查看到手机的信号强度,显示出如“-87 dBm 13 asu”这样的数据。ASU与dBm之间的关系是:dBm=-113+(2*ASU)。

  在你手机屏幕上方显示的信号条永远不会是最好的方法来确定你手机的信号,无论你用什么手机都一样。Android也是,用很粗的条来展示很强的信号,但这些条仅仅表示最高的信号。或许你并不熟悉,信号通常是以dBm度量的。dBm是每毫瓦特的电磁波产生的功率。-60dBm的信号接近完美,-112dBm就很容易掉线,如果你在 -87dBm以上,Android会显示一个4格的满信号。

  android界面UI信号显示是通过RIL对通讯模块发送AT命令来实现的,如AT+CSQ,我们查看一般可以通过 logcat -b radio来获取一些RIL的实时信息,可以通过关键字“CSQ”查找radio.log,查看手机信号强度。log如:AT< +CSQ: 14,99  这里的14就是ASU值,在4.0源码中有SignalStrength.java类,其中有ASU值转换为几格信号的方法:

[java]  view plain copy
  1. 403  
  2.     public int getGsmLevel() {  
  3. 404  
  4.         int level;  
  5. 405  
  6.    
  7. 406  
  8.         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5  
  9. 407  
  10.         // asu = 0 (-113dB or less) is very weak  
  11. 408  
  12.         // signal, its better to show 0 bars to the user in such cases.  
  13. 409  
  14.         // asu = 99 is a special case, where the signal strength is unknown.  
  15. 410  
  16.         int asu = getGsmSignalStrength();  
  17. 411  
  18.         if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;  
  19. 412  
  20.         else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;  
  21. 413  
  22.         else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;  
  23. 414  
  24.         else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;  
  25. 415  
  26.         else level = SIGNAL_STRENGTH_POOR;  
  27. 416  
  28.         if (DBG) log("getGsmLevel=" + level);  
  29. 417  
  30.         return level;  
  31. 418  
  32.     }  

-----------------------------------------------------------------------------------------

以下是从网上找到的相关资料。

  在RILConstants.java中找到:
int RIL_UNSOL_SIGNAL_STRENGTH = 1009;

在RIL.java中找到与其相关的代码:
private void
processUnsolicited (Parcel p) {
…….
case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
…..
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));
}

在RIL的父类BaseCommands.java中找到:
public void setOnSignalStrengthUpdate(Handler h, int what, Object obj) {
mSignalStrengthRegistrant = new Registrant (h, what, obj);
}

再找其调用者(GsmServiceStateTracker.java):
public GsmServiceStateTracker(GSMPhone phone) {
super();

……
cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
……

GsmServiceStateTracker自己处理上报上来的信号强度信息:
case EVENT_SIGNAL_STRENGTH_UPDATE:
// This is a notification from
// CommandsInterface.setOnSignalStrengthUpdate

ar = (AsyncResult) msg.obj;

// The radio is telling us about signal strength changes
// we don’t have to ask it
dontPollSignalStrength = true;

onSignalStrengthResult(ar);
break;

函数onSignalStrengthResult负责处理:
private void onSignalStrengthResult(AsyncResult ar) {
SignalStrength oldSignalStrength = mSignalStrength;
int rssi = 99;

if (ar.exception != null) {
// -1 = unknown
// most likely radio is resetting/disconnected
setSignalStrengthDefaultValues();
} else {
int[] ints = (int[])ar.result;

// bug 658816 seems to be a case where the result is 0-length
if (ints.length != 0) {
rssi = ints[0];
} else {
Log.e(LOG_TAG, “Bogus signal strength response”);
rssi = 99;
}
}

mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
-1, -1, -1, true);

if (!mSignalStrength.equals(oldSignalStrength)) {
try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
// POLL_PERIOD_MILLIS) during Radio Technology Change)
phone.notifySignalStrength();
} catch (NullPointerException ex) {
log(“onSignalStrengthResult() Phone already destroyed: ” + ex
+ “SignalStrength not notified”);
}
}
}

若没发生异常,且值产生变化,则调用 phone.notifySignalStrength通知(见GSMPhone.java):
notifySignalStrength() {
mNotifier.notifySignalStrength(this);
}

DefaultPhoneNotifier(DefaultPhoneNotifier.java)通知注册者:
public void notifySignalStrength(Phone sender) {
try {
mRegistry.notifySignalStrength(sender.getSignalStrength());
} catch (RemoteException ex) {
// system process is dead
}
}

这个注册者来自:
DefaultPhoneNotifier() {
mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
“telephony.registry”));
}

TelephonyRegistry.java,TelephonyRegistry是ITelephonyRegistry.Stub的子类,作为service运行在system_server进程中,它会通知注册者。上面的DefaultPhoneNotifier运行在com.android.phone进程中,当信号强度值变化时,通过Service进行通知(service被感兴趣的注册者调用了listen,添加了回调函数。
public void notifySignalStrength(SignalStrength signalStrength) {
if (!checkNotifyPermission(“notifySignalStrength()”)) {
return;
}
synchronized (mRecords) {
mSignalStrength = signalStrength;
for (int i = mRecords.size() – 1; i >= 0; i–) {
Record r = mRecords.get(i);
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
sendSignalStrength(r, signalStrength);
}
if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
try {
int gsmSignalStrength = signalStrength.getGsmSignalStrength();
r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
: gsmSignalStrength));
} catch (RemoteException ex) {
remove(r.binder);
}
}
}
}
broadcastSignalStrengthChanged(signalStrength);
}

在TelephonyManager.java中提供了API,应用程序可以监听各种事件,实际上它将感兴趣的监听者作为一条记录添加到service一侧的列表(跨进程)中,当有变化时,调用它们提供的回调函数,通知(跨进程)这些注册者。
TelephonyManager.java中的listen函数如下:
public void listen(PhoneStateListener listener, int events) {
String pkgForDebug = mContext != null ? mContext.getPackageName() : “<unknown>”;
try {
Boolean notifyNow = (getITelephony() != null);
mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
} catch (RemoteException ex) {
// system process dead
} catch (NullPointerException ex) {
// system process dead
}
}
其中回调对象实例listener.callback来自于PhoneStateListener.java嵌套定义及其实例,这样,当TelephonyRegistry.java调用回调函数时,就调用到listener.callback,进而发送消息给PhoneStateListener.java中的mHandler,由其处理,进而由其子类去处理。

在StatusBarPolicy.java中,注册了下面要监听处理的事件。第二个为信号强度:
((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
.listen(mPhoneStateListener,
PhoneStateListener.LISTEN_SERVICE_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_CALL_STATE
| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_DATA_ACTIVITY);

处理者为:
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
mSignalStrength = signalStrength;
updateSignalStrength();
}

在StatusBarPolicy的updateSignalStrength函数中,将根据得到的信息,设置适当的图标id,显示合适的图标。

主动请求:

GsmServiceStateTracker.java
case EVENT_POLL_SIGNAL_STRENGTH:
// Just poll signal strength…not part of pollState()

cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
break;

在RIL.java中,发送请求:
public void
getSignalStrength (Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);

/*if (RILJ_LOGD)*/ riljLog(rr.serialString() + “> ” + requestToString(rr.mRequest));

send(rr);
}

请求号在RIL.java中,定义了请求号:
RIL_REQUEST_SIGNAL_STRENGTH

返回结果: processSolicited中得到结果后sendToTarget
private void
processSolicited (Parcel p) {
…..

case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;

在GsmServiceStateTracker.java中,msg的handler指定为this,所以GsmServiceStateTracker负责回送的消息的处理:
case EVENT_GET_SIGNAL_STRENGTH:
// This callback is called when signal strength is polled
// all by itself

if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isCdma())) {
// Polling will continue when radio turns back on and not CDMA
return;
}
ar = (AsyncResult) msg.obj;
onSignalStrengthResult(ar);
queueNextSignalStrengthPoll();

break;

private void onSignalStrengthResult(AsyncResult ar) {
SignalStrength oldSignalStrength = mSignalStrength;
int rssi = 99;
Log.d(“YCG”, “query done! onSignalStrengthResult”);
if (ar.exception != null) {
// -1 = unknown
// most likely radio is resetting/disconnected
setSignalStrengthDefaultValues();
} else {
int[] ints = (int[])ar.result;

// bug 658816 seems to be a case where the result is 0-length
if (ints.length != 0) {
rssi = ints[0];
Log.d(“YCG”, “query done! rssi=”+rssi);
} else {
Log.e(LOG_TAG, “Bogus signal strength response”);
rssi = 99;
}
}

mSignalStrength = new SignalStrength(rssi, -1, -1, -1,
-1, -1, -1, true);

if (!mSignalStrength.equals(oldSignalStrength)) {
try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
// POLL_PERIOD_MILLIS) during Radio Technology Change)
phone.notifySignalStrength();
} catch (NullPointerException ex) {
log(“onSignalStrengthResult() Phone already destroyed: ” + ex
+ “SignalStrength not notified”);
}
}
}

phone.notifySignalStrength();通知上层,走上相同流程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值