Android4.4 Systemui状态栏之信号逻辑流程分析
来源:互联网 发布:java中log 编辑:程序博客网 时间:2024/05/16 10:58
该篇博文需要一定的Systemui的状态栏基础才能看懂,所以如果各位看官是第一次学习Systemui的状态栏的话建议您点击以下传送门
http://blog.csdn.net/yihongyuelan?viewmode=contents
以下是正文:状态栏的信号包括:手机网络信号,无线WIFI网络信号,代理服务器网络信号,飞行模式4种
以上的4种信号由SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java实现具体的流程逻辑,该类继承BroadcastReceiver,所以大胆猜测底层信号如果发生改变,该广播会接受到相应的广播.
然后在SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java创建一个NetworkController对象,具体代码如下:
protected PhoneStatusBarView makeStatusBarView() { …….. mNetworkController = new NetworkController(mContext); final SignalClusterView signalCluster = (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster); mNetworkController.addSignalCluster(signalCluster); signalCluster.setNetworkController(mNetworkController); ….. }
然后在状态栏上的UI界面更新,在类SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java中实现.
下面我们开始具体的流程分析吧
先从类SignalClusterView.java开始,因为该类比较简单,易于以后的对复杂的类NetworkController.java分析
public class SignalClusterView extends LinearLayout implements NetworkController.SignalCluster
这是该类的继承关系,我们很明显的看到该类实例化了类NetworkController中的内部接口SignalCluster
以下SignalCluserView的全部展示
package com.android.systemui.statusbar;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.view.accessibility.AccessibilityEvent;import android.widget.ImageView;import android.widget.LinearLayout;import com.android.systemui.R;import com.android.systemui.statusbar.policy.NetworkController;// Intimately tied to the design of res/layout/signal_cluster_view.xml/** * @author tony * 信号集中类,包含wifi,以太网,手机信号,飞行模式 */public class SignalClusterView extends LinearLayout implements NetworkController.SignalCluster { static final boolean DEBUG = false; static final String TAG = "SignalClusterView"; NetworkController mNC; private boolean mWifiVisible = false; private int mWifiStrengthId = 0; private boolean mEthernetVisible = false; private int mEthernetStateId = 0, mEthernetActivityId = 0; private boolean mMobileVisible = false; private int mMobileStrengthId = 0, mMobileTypeId = 0; private boolean mIsAirplaneMode = false; private int mAirplaneIconId = 0; private String mWifiDescription, mMobileDescription, mMobileTypeDescription, mEthernetDescription; ViewGroup mWifiGroup, mMobileGroup, mEthernetGroup; //Ethernet是代理服务器的意思 ImageView mWifi, mMobile, mMobileType, mAirplane, mEthernet; View mSpacer; public SignalClusterView(Context context) { this(context, null); } public SignalClusterView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SignalClusterView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setNetworkController(NetworkController nc) { if (DEBUG) Log.d(TAG, "NetworkController=" + nc); mNC = nc; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo); mWifi = (ImageView) findViewById(R.id.wifi_signal); mMobileGroup = (ViewGroup) findViewById(R.id.mobile_combo); mMobile = (ImageView) findViewById(R.id.mobile_signal); mMobileType = (ImageView) findViewById(R.id.mobile_type); mSpacer = findViewById(R.id.spacer); mAirplane = (ImageView) findViewById(R.id.airplane); mEthernetGroup = (ViewGroup) findViewById(R.id.ethernet_combo); mEthernet = (ImageView) findViewById(R.id.ethernet_state); apply(); } @Override protected void onDetachedFromWindow() { mWifiGroup = null; mWifi = null; mMobileGroup = null; mMobile = null; mMobileType = null; mSpacer = null; mAirplane = null; super.onDetachedFromWindow(); } /** * change by tony * 当wifi信号改变时所调用的方法 * @param visible * @param strengthIcon * @param contentDescription */ @Override public void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription) { mWifiVisible = visible; mWifiStrengthId = strengthIcon; mWifiDescription = contentDescription; apply(); } /** * change by tony * 当手机信号改变时所调用的方法 * @param visible * @param strengthIcon * @param typeIcon * @param contentDescription * @param typeContentDescription */ @Override public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, String contentDescription, String typeContentDescription) { mMobileVisible = visible; mMobileStrengthId = strengthIcon; mMobileTypeId = typeIcon; mMobileDescription = contentDescription; mMobileTypeDescription = typeContentDescription; apply(); } /** * change by tony * 当以太网信号改变时所调用的方法 * @param visible * @param strengthIcon * @param activityIcon * @param contentDescription */ public void setEthernetIndicators(boolean visible,int strengthIcon,int activityIcon, String contentDescription){ mEthernetVisible = visible; mEthernetStateId = strengthIcon; mEthernetActivityId = activityIcon; mEthernetDescription = contentDescription; apply(); } @Override public void setIsAirplaneMode(boolean is, int airplaneIconId) { mIsAirplaneMode = is; mAirplaneIconId = airplaneIconId; apply(); } @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { // Standard group layout onPopulateAccessibilityEvent() implementations // ignore content description, so populate manually if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null) event.getText().add(mWifiGroup.getContentDescription()); if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null) event.getText().add(mMobileGroup.getContentDescription()); return super.dispatchPopulateAccessibilityEvent(event); } @Override public void onRtlPropertiesChanged(int layoutDirection) { super.onRtlPropertiesChanged(layoutDirection); if (mWifi != null) { mWifi.setImageDrawable(null); } if (mMobile != null) { mMobile.setImageDrawable(null); } if (mMobileType != null) { mMobileType.setImageDrawable(null); } if(mAirplane != null) { mAirplane.setImageDrawable(null); } apply(); } // Run after each indicator change. private void apply() { if (mWifiGroup == null) return; if (mWifiVisible) { mWifi.setImageResource(mWifiStrengthId); mWifiGroup.setContentDescription(mWifiDescription); mWifiGroup.setVisibility(View.VISIBLE); } else { mWifiGroup.setVisibility(View.GONE); } if(mEthernetVisible){ mEthernetGroup.setVisibility(View.VISIBLE); mEthernet.setImageResource(mEthernetStateId); mEthernetGroup.setContentDescription(mEthernetDescription); } else { mEthernetGroup.setVisibility(View.GONE); } if (DEBUG) Log.d(TAG, String.format("wifi: %s sig=%d", (mWifiVisible ? "VISIBLE" : "GONE"), mWifiStrengthId)); if (mMobileVisible && !mIsAirplaneMode) { mMobile.setImageResource(mMobileStrengthId); mMobileType.setImageResource(mMobileTypeId); mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription); mMobileGroup.setVisibility(View.VISIBLE); } else { mMobileGroup.setVisibility(View.GONE); } if (mIsAirplaneMode) { mAirplane.setImageResource(mAirplaneIconId); mAirplane.setVisibility(View.VISIBLE); } else { mAirplane.setVisibility(View.GONE); } if (mMobileVisible && (mWifiVisible || mEthernetVisible) && mIsAirplaneMode) { mSpacer.setVisibility(View.INVISIBLE); } else { mSpacer.setVisibility(View.GONE); } if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d", (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); mMobileType.setVisibility( !(mWifiVisible || mEthernetVisible) ? View.VISIBLE : View.GONE); }}
从上诉代码我们可以很容易的分析得到SignalCluster类上实现界面更新的时机是类NetworkController的内部接口调用实现的.具体的UI界面在类SignalCluster中的方法apply(){}中,具体的ui更新分析就不在详细展开了,大家自己看下代码就懂了.
下面是对重中之重的类NetworkController分析,
虽然该类是一个广播,但是没有在AndroidMainfest.XML上注册,所以不是一个静态广播,而是一个动态广播
首先对该类的构造方法分析:
public NetworkController(Context context) { ....... mContext = context; // set up the default wifi icon, used when no radios have ever appeared updateWifiIcons(); updateWimaxIcons(); // telephony mPhone = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); //手机信号监听器,如果手机信号有更新的话就在监听器mPhoneStateListener有回调 mPhone.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_CALL_STATE | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | PhoneStateListener.LISTEN_DATA_ACTIVITY); // wifi //AsyncChannel通讯主要是两个handler的通讯,不了解的同学可以先了解一下,所以通讯在 //WifiHandler() mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); Handler handler = new WifiHandler(); mWifiChannel = new AsyncChannel(); Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); if (wifiMessenger != null) { mWifiChannel.connect(mContext, handler, wifiMessenger); } // broadcasts //动态广播,刚好是我们刚刚猜想的 IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.RSSI_CHANGED_ACTION); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(EthernetManager.ETHERNET_STATE_CHANGED_ACTION); filter.addAction(EthernetManager.NETWORK_STATE_CHANGED_ACTION); // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it updateAirplaneMode(); mLastLocale = mContext.getResources().getConfiguration().locale; }
从上面的构造方法中我们可以看出,手机信号的更新是通过getSystemService(Context.TELEPHONY_SERVICE)获取实例,然后再通过注册监听来监听手机信号的变化.wifi信号getSystemService(Context.WIFI_SERVICE)获取实例,然后通过AsyncChannel实现自己的WifiHandler跟wifiManager中的handler实现通讯.并且注册一个动态广播,监听手机信号跟wifi信号来更新UI
手机信号监听器的代码:
// ===== Telephony ============================================================== PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { //手机信号强度改变,在这里实现具体的业务逻辑 } @Override public void onServiceStateChanged(ServiceState state) { //手机信号状态改变,在这里实现具体的业务逻辑,比如强度,信号类型 } @Override public void onCallStateChanged(int state, String incomingNumber) { } @Override public void onDataConnectionStateChanged(int state, int networkType) { //手机信号状态改变,在这里实现具体的业务逻辑,比如强度,信号类型 } @Override public void onDataActivity(int direction) { };
WIFI信号跟新
// ===== Wifi =================================================================== class WifiHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { mWifiChannel.sendMessage(Message.obtain(this, AsyncChannel.CMD_CHANNEL_FULL_CONNECTION)); } else { Log.e(TAG, "Failed to connect to wifi"); } break; case WifiManager.DATA_ACTIVITY_NOTIFICATION: if (msg.arg1 != mWifiActivity) { mWifiActivity = msg.arg1; refreshViews(); } break; default: //Ignore break; } } }
由于NetworkController是个广播,所以必须得分析public void onReceive(Context context, Intent intent)
下面是onReceive的具体代码了
@Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (action.equals(WifiManager.RSSI_CHANGED_ACTION) || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { updateWifiState(intent); refreshViews(); } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { updateSimState(intent); updateDataIcon(); refreshViews(); } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), intent.getStringExtra(TelephonyIntents.EXTRA_SPN), intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); refreshViews(); } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { updateConnectivity(intent); refreshViews(); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { refreshLocale(); refreshViews(); } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { refreshLocale(); updateAirplaneMode(); refreshViews(); } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) || action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) || action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { updateWimaxState(intent); refreshViews(); } else if (action.equals(EthernetManager.NETWORK_STATE_CHANGED_ACTION) || action.equals(EthernetManager.ETHERNET_STATE_CHANGED_ACTION)) { updateEthernetState(intent); refreshViews(); } }
以上的代码也很清晰了,就是根据不同的广播Action来实现具体的业务逻辑
由于最近在实习工作事情很多,并且毕业之际,诸事于一身,以上的分析由于时间比较匆促,所以分析得挺粗的,如果抽得空出来,我会继续分析具体业务流程.如有错漏,欢迎大家指出,毕竟小菜鸟一个.
- Android4.4 Systemui状态栏之信号逻辑流程分析
- Android4.4 Systemui状态栏状态图标更新流程分析
- android4 SystemUI 流程分析
- Android4.4 SystemUI分析之PowerUI
- Android4.4 SystemUI分析之DessertCase
- Android4.4 systemui 启动流程
- Android4.4 SystemUI分析之Clock时钟显示
- android4.0 SystemUi系统状态栏
- Android4.1Systemui分析
- Android 5.0 状态栏(SystemUI)系统图标加载流程简单分析
- android4.0 systemui启动流程
- android4.4 systemUI设置
- android SystemUI 流程分析
- android SystemUI 流程分析
- android SystemUI 流程分析
- SystemUI的下拉状态栏分析
- SystemUI之呈现流程
- Android4.4 状态栏信号和数据业务图片说明
- Android屏幕适配全攻略(最权威的官方适配指导)
- JavaScript事件委托的技术原理
- IP地址类
- JAVA对象JSON数据互相转换的四种常见情况
- GDataXMLNode:xml解析库
- Android4.4 Systemui状态栏之信号逻辑流程分析
- 函数调用之详细分析
- 解决在低版本的xcode上使用高版本iOS系统手机进行真机测试
- Android app设置全屏模式
- solaris下清除log文件命令
- idea maven jetty 配置
- AndroidStudioSDK下tools下各个文件(夹)的用处
- 笔记,TCP协议socket网络编程
- 尝试用顺序表实现排序算法(持续更新..)