之前写的文章都是关于软件设置方面的,用来为安装软件和系统来做一些记录,让其他人少绕弯道,今天正式开始更新技术博客。
先简后难吧,我选择了安卓7.0的systemUI中的状态栏开始入手,由于systenUI中的代码涉及的还是比较广的,这里就拆分开来写,以后慢慢持续更新!
一般的分析systenUI都会从它的启动来分析,但是类似于这样的文章网上有很多,我就不再赘述了,这里提供网址,想要了解启动流程的可以自行去看
http://blog.csdn.net/qq_31530015/article/details/53507968
这篇文章不仅介绍了启动流程,还对布局进行了讲解,是从大局观上来讲的。可以了解整个systemUI的视图流程。
闲话少叙,开始具体分析更新流程,这里我还是从视图入手。
个人 习惯,喜欢从布局入手。这里我用了sdk中的 hierarchy 找到了这个视图的布局。这里大致介绍一下systemUI整个布局的联系。
(请原谅我拙劣的画工)
这里主要以最后查询到的 用于放置信号图标的直接父容器,LinearLayout的id着手,在systemUI全局中找寻到下面:
在类SignalClusterView中有如下代码:
mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
然后追寻mMobileSignalGroup 找到了
mMobileSignalGroup.addView(state.mMobileGroup);
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
for (PhoneState state : mPhoneStates) {
mMobileSignalGroup.addView(state.mMobileGroup);
}
int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0;
mMobileSignalGroup.setPaddingRelative(0, 0, endPadding, 0);
TunerService.get(mContext).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
apply();
applyIconTint();
mNC.addSignalCallback(this);
}
这里需要注意mPhoneStates是一个集合,这个集合里面有几个对象就代表目前手机插着几张sim卡。
然后再跳到phonestate:
public PhoneState(int subId, Context context) {
ViewGroup root = (ViewGroup) LayoutInflater.from(context)
.inflate(R.layout.mobile_signal_group, null);
setViews(root);
mSubId = subId;
}
接着 setViews(root);
public void setViews(ViewGroup root) {
mMobileGroup = root;
…………………………
}
可以看到真正的布局其实就是mobile_signal_group.xml
这里将这个布局文件代码贴出来
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/mobile_combo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/embms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginEnd="4dp"
android:visibility="gone"
/>
<ImageView
android:id="@+id/dataNetwork_type"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="2dp"
android:visibility="gone"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:id="@+id/data_inout"
android:visibility="gone"
/>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ImageView
android:id="@+id/mobile_roaming"
android:layout_width="wrap_content"
android:layout_height="17dp"
android:paddingStart="22dp"
android:paddingTop="1.5dp"
android:paddingBottom="3dp"
android:scaleType="fitCenter"
android:src="@drawable/stat_sys_roaming"
android:contentDescription="@string/accessibility_data_connection_roaming"
android:visibility="gone"
/>
<FrameLayout
android:id="@+id/mobile_signal_single"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<com.android.systemui.statusbar.AnimatedImageView
android:theme="@style/DualToneLightTheme"
android:id="@+id/mobile_signal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
systemui:hasOverlappingRendering="false"
/>
<com.android.systemui.statusbar.AnimatedImageView
android:theme="@style/DualToneDarkTheme"
android:id="@+id/mobile_signal_dark"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:alpha="0.0"
systemui:hasOverlappingRendering="false"
/>
<ImageView
android:id="@+id/mobile_type"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
/>
<ImageView
android:id="@+id/mobile_inout"
android:layout_height="17dp"
android:layout_width="17dp"
android:layout_gravity="end|center_vertical"
android:layout_marginBottom="0.8dp"
android:layout_marginRight="1.5dp"
/>
</FrameLayout>
<LinearLayout
android:id="@+id/mobile_signal_stacked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
>
<ImageView
android:id="@+id/mobile_signal_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/mobile_signal_voice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
这里分的很细致,但是分析方法大致都一样,我们主要来分析状态栏的信号强度(表现在信号的格数)和信号type(4g,3g等)。
<com.android.systemui.statusbar.AnimatedImageView
android:theme="@style/DualToneLightTheme"
android:id="@+id/mobile_signal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
systemui:hasOverlappingRendering="false"
/>
遵循这个布局找到id为mobile_signal的AnimatedImageView。
最终发现他的动态改变是在phoneState中的apply()中发生的
public boolean apply(boolean isSecondaryIcon) {
if (mMobileVisible && !mIsAirplaneMode) {
if (mLastMobileStrengthId != mMobileStrengthId) {
updateAnimatableIcon(mMobile, mMobileStrengthId);
updateAnimatableIcon(mMobileDark, mMobileStrengthId);
mLastMobileStrengthId = mMobileStrengthId;
}
if (mLastMobileTypeId != mMobileTypeId) {
mMobileType.setImageResource(mMobileTypeId);
mLastMobileTypeId = mMobileTypeId;
}
。。。。。。。。。。。。。。。。。。。。。。。。。
}
以这个方法为分界点!
向上追(调用它的地方)可以找到信号改变的源码!
向下追(它调用的地方)可以找到,信号改变过程中需要的各种资源的位置。
我们首先向上追,发现SignalClusterView中的apply()调用了它,而SignalClusterView继承了SignalCallback,在实现该接口的所有方法中都调用到了自己的apply()方法,看来是回调了。<未完待续>