不啰嗦直接分析:
推荐一篇SystemUI的分析文章,帮这位不认识的老铁打个广告 ^_^
https://blog.csdn.net/azhengye/article/details/50419409
1:Android 4.1 MTK平台
2:Android 5.1 (6.1) QCOM平台
(主要不同点,第一个数组是在代码里,第二个数读取资源文件里面的数组 . apply 里设置信号图片的代码略为不同,5.1以后是在updateMobile() 这个方法去设置 , 二4.1 直接在 apply() 这个函数里设置)
(源码下载链接在最后^_^)
定位源码:/XXX/frameworks/base/packages/SystemUI/
com.android.systemui.statusbar 包下的 SignalClusterView.java
这个类主要用来管理SystemUI的网络信号有关的UI, 记住只是UI。系统的架构很好,处理的地方在另外一个类,这个就是
com.android.systemui.statusbar.policy 包下的 NetworkController
这里主要做一些逻辑操作,比如说信号刷新,以及信号的UI如何获取 并传递到 SignalClusterView 这个类本身就是集成一个广播,这里不做深入分析。
public void setMobileDataIndicators(boolean visible, IconIdWrapper strengthIcon, IconIdWrapper activityIcon,
int typeIcon, String contentDescription, String typeContentDescription) {
mMobileVisible = visible;
mMobileStrengthId = strengthIcon.clone();
mMobileActivityId = activityIcon.clone();
mMobileTypeId = typeIcon;
mMobileDescription = contentDescription;
mMobileTypeDescription = typeContentDescription;
Xlog.d(TAG, "setMobileDataIndicators"
+ " mMobileVisible=" + mMobileVisible
+ " mMobileStrengthId=" + mMobileStrengthId.getIconId()
+ " mMobileActivityId=" + mMobileActivityId.getIconId()
+ " mMobileTypeId=" + mMobileTypeId
+ " mWifiGroup" + ((mWifiGroup == null) ? "=null" : "!=null"));
apply();
}
public void setMobileDataIndicators 这个函数就是 回调 NetworkController 的接口, 表示数据更新。
我们后面回过头来看这个函数,
最后面执行了apply();
4.1代码:
// Run after each indicator change.
private void apply() {
// *******省略部分代码******
if (mMobileVisible && !mIsAirplaneMode) {
/// M: Support Roam Data Icon both show. @{
if (mRoaming) {
mMobileRoam.setImageResource(mRoamingId);
mMobileRoam.setVisibility(View.VISIBLE);
} else {
mMobileRoam.setImageResource(0);
mMobileRoam.setVisibility(View.GONE);
}
/// M: Support Roam Data Icon both show. }@
mMobileGroup.setVisibility(View.VISIBLE);
if (mMobileStrengthId.getResources() != null) {
mMobile.setImageDrawable(mMobileStrengthId.getDrawable());
} else {
if (mMobileStrengthId.getIconId() == 0) {
mMobile.setImageDrawable(null);
} else {
mMobile.setImageResource(mMobileStrengthId.getIconId());
}
}
if (mMobileActivityId.getResources() != null) {
mMobileActivity.setImageDrawable(mMobileActivityId.getDrawable());
} else {
if (mMobileActivityId.getIconId() == 0) {
mMobileActivity.setImageDrawable(null);
} else {
mMobileActivity.setImageResource(mMobileActivityId.getIconId());
}
}
mMobileType.setImageResource(mMobileTypeId);
Xlog.d(TAG, "apply() setImageResource(mMobileTypeId) mShowSimIndicator = " + mShowSimIndicator);
mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription);
/// M: Airplane mode: Shouldn't show data type icon (L1)
/// OP01 project: Not in airplane mode, the data type icon should be always displayed (L2)
/// WifiVisible: Not in airplane mode, not OP01 project, the data type icon should follow the wifi visible status (L3)
if (PluginFactory.getStatusBarPlugin(mContext).supportDataTypeAlwaysDisplayWhileOn()) {
mMobileType.setVisibility(View.VISIBLE);
} else {
mMobileType.setVisibility(!mWifiVisible ? View.VISIBLE : View.GONE);
}
/// M: When the signal strength icon id is null should hide the data type icon, this including several status
if (mMobileStrengthId.getIconId() == R.drawable.stat_sys_signal_null) {
mMobileType.setVisibility(View.GONE);
}
/// M: Support SIM Indicator. @{
if (mShowSimIndicator) {
mSignalClusterCombo.setBackgroundResource(mSimIndicatorResource);
} else {
mSignalClusterCombo.setPadding(0, 0, 0, 0);
mSignalClusterCombo.setBackgroundDrawable(null);
}
/// M: Support SIM Indicator. }@
} else {
mMobileGroup.setVisibility(View.GONE);
}
// *******省略部分代码******
}
5.1 以上:
// Run after each indicator change.
private void apply(int phoneId) {
if (mWifiGroup == null) return;
if (mWifiVisible) {
mWifiGroup.setVisibility(View.VISIBLE);
mWifi.setImageResource(mWifiStrengthId);
mWifiActivity.setImageResource(mWifiActivityId);
mWifiGroup.setContentDescription(mWifiDescription);
} else {
mWifiGroup.setVisibility(View.GONE);
}
if (DEBUG) Slog.d(TAG,
String.format("wifi: %s sig=%d act=%d",
(mWifiVisible ? "VISIBLE" : "GONE"), mWifiStrengthId, mWifiActivityId));
if (mMobileVisible && !mIsAirplaneMode) {
updateMobile(phoneId);
updateCdma();
updateData(phoneId);
updateDataVoice(phoneId);
mMobileGroup[phoneId].setVisibility(View.VISIBLE);
} else {
mMobileGroup[phoneId].setVisibility(View.GONE);
mMobileCdmaGroup.setVisibility(View.GONE);
mMobileCdma1xOnly.setVisibility(View.GONE);
mDataGroup[phoneId].setVisibility(View.GONE);
}
// *******省略部分代码******
}
到这里只是设置完了UI。我们再回过头来看 图片源到底是怎么设置的?
这边就要回到
NetworkControllerImpl.java 这边了
这边只是做个简单分析,这个类会接受一些广播信息,然后通过接口刷新数据给上面那个类。
看下代码:
public void refreshSignalCluster(SignalCluster cluster) {
cluster.setWifiIndicators(
// only show wifi in the cluster if connected or if wifi-only
mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
mWifiIconId,
mWifiActivityIconId,
mContentDescriptionWifi);
if (mIsWimaxEnabled && mWimaxConnected) {
// wimax is special
cluster.setMobileDataIndicators(
true,
mAlwaysShowCdmaRssi ? mPhoneSignalIconId : new IconIdWrapper(mWimaxIconId),
mMobileActivityIconId,
mDataTypeIconId,
mContentDescriptionWimax,
mContentDescriptionDataType);
} else {
// normal mobile data
cluster.setMobileDataIndicators(
mHasMobileDataFeature,
mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
mMobileActivityIconId,
mDataTypeIconId,
mContentDescriptionPhoneSignal,
mContentDescriptionDataType);
}
cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
}
其中 cluster.setMobileDataIndicators(**) 就是将SIM的信息回调给 SignalClusterView
第二个参数标识的是信号强度。其余的参数想了解 可以找百度。
然后通过这个mPhoneSignalIconId 继续查找 会发现到底是谁给他赋值,接下来我们在MTK4.0 已经iQCOM 5.1 6.1 代码分别来看(MTK5.1和这个一样)。
有一点,对这个 图标 赋值的函数是同一个 那就是
private final void updateTelephonySignalStrength() 信号强度
private final void updateDataNetType() 信号类型
switch (mDataNetType) {
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
if (!mShowAtLeastThreeGees) {
if (!mIsRoaming) { /// M: Support Roam Data Icon both show.
mDataIconList = TelephonyIcons.DATA_G[simColor];
} else {
mDataIconList = TelephonyIcons.DATA_G_ROAM[simColor];
}
mDataTypeIconId = 0;
mContentDescriptionDataType = mContext.getString(
R.string.accessibility_data_connection_gprs);
break;
} else {
// fall through
}
case TelephonyManager.NETWORK_TYPE_EDGE:
if (!mShowAtLeastThreeGees) {
if (!mIsRoaming) { /// M: Support Roam Data Icon both show.
mDataIconList = TelephonyIcons.DATA_E[simColor];
} else {
mDataIconList = TelephonyIcons.DATA_E_ROAM[simColor];
}
mDataTypeIconId = mDataIconList[0];
mContentDescriptionDataType = mContext.getString(
R.string.accessibility_data_connection_edge);
break;
} else {
// fall through
}
case TelephonyManager.NETWORK_TYPE_UMTS:
if (!mIsRoaming) { /// M: Support Roam Data Icon both show.
mDataIconList = TelephonyIcons.DATA_3G[simColor];
} else {
mDataIconList = TelephonyIcons.DATA_3G_ROAM[simColor];
}
mDataTypeIconId = mDataIconList[0];
mContentDescriptionDataType = mContext.getString(
R.string.accessibility_data_connection_3g);
break;
从代码中可以看出,所有图标数组 都是定义在 TelephonyIcons.java 这个类中, 不管是类型还是强度。具体的部分源码我会给个下载地址。
那么信号强度:
private final void updateTelephonySignalStrength(int phoneId) {
/****省略部分代码***/
mMSimPhoneSignalIconId[phoneId] =
TelephonyIcons.getSignalNullIcon(phoneId);
mMSimDataSignalIconId[phoneId] =
mMSimPhoneSignalIconId[phoneId];
if (phoneId == dataSub) {
mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
}
} else {
if (mMSimSignalStrength[phoneId] == null || (mMSimServiceState == null)) {
if (DEBUG) {
Slog.d(TAG, " Null object, mMSimSignalStrength= "
+ mMSimSignalStrength[phoneId]
+ " mMSimServiceState " + mMSimServiceState[phoneId]);
}
mMSimPhoneSignalIconId[phoneId] =
TelephonyIcons.getSignalNullIcon(phoneId);
mMSimDataSignalIconId[phoneId] =mMSimPhoneSignalIconId[phoneId];
mMSimContentDescriptionPhoneSignal[phoneId] =
TelephonyIcons.getSignalStrengthDes(phoneId, 0);
/****省略部分代码***/
}
}
}
mMSimContentDescriptionPhoneSignal[phoneId] =TelephonyIcons.getSignalStrengthDes(phoneId, iconLevel);
所以在追踪到 TelephonyIcons 会发现有很多
static void initAll(Context context) {
if (isInitiated) {
log(TAG, "initAll, already initiated!");
return;
}
mRes = context.getResources();
try {
mDataTypeArray = mRes.getStringArray(
R.array.multi_data_type);
mDataTypeDescriptionArray = mRes.getStringArray(
R.array.telephony_data_type_description);
mDataTypeGenerationArray = mRes.getStringArray(
R.array.telephony_data_type_generation);
mDataTypeGenerationDescArray = mRes.getStringArray(
R.array.telephony_data_type_generation_description);
mDataActivityArray = mRes.getStringArray(
R.array.multi_data_activity);
mSignalStrengthArray = mRes.getStringArray(
R.array.multi_signal_strength);
mSignalStrengthRoamingArray = mRes.getStringArray(
R.array.multi_signal_strength_roaming);
mSignalNullArray = mRes.getStringArray(
R.array.multi_signal_null);
mNoSimArray = mRes.getStringArray(
R.array.multi_no_sim);
mSignalStrengthDesc = mRes.getStringArray(
R.array.signal_strength_description);
} catch (android.content.res.Resources.NotFoundException e) {
isInitiated = false;
log(TAG, "initAll, exception happened: " + e);
return;
}
可以发现 ,读取的是资源文件的array。 那么就可以对应的去查找这个array资源文件 可以在里面替换自己想要的一些信号强度图片。
贴个部分代码吧:
- array/signal_strength_cdma_normal_roaming_sim1
- array/signal_strength_cdma_fully_roaming_sim1
- array/signal_strength_umts_normal_sim1
- array/signal_strength_umts_fully_sim1
- array/signal_strength_umts_normal_roaming_sim1
- array/signal_strength_umts_fully_roaming_sim1
- drawable/stat_sys_signal_0_fully
- drawable/stat_sys_signal_1_fully
- drawable/stat_sys_signal_2_fully
- drawable/stat_sys_signal_3_fully
- drawable/stat_sys_signal_4_fully
这样就OK了!
SystemUI源码:
点击下载