編輯:關於Android編程
Android6.0 SystemUI之網絡信號欄顯示刷新。Android的網絡信號欄的顯示刷新也是SystemUI的一部分,主要業務邏輯也是在SystemUI這模塊內的,整個流程的開始是在PhoneStatusBar.java內的,
frameworks/base/packages/SystemUI/src/com/Android/systemui/statusbar/phone/PhoneStatusBar.Java;
先從布局方面入手:
由PhoneStatusBar.java的makeStatusBarView()統一加載super_status_bar.xml的。而在Android中,SystemUI上顯示信號狀態欄的地方主要由三處,分別是狀態欄、鎖屏界面下的狀態欄以及下拉通知欄的快捷設置區域。這三個引用處分別是status_bar.xml、keyguard_status_bar.xml、status_bar_expanded_header.xml;而這三個布局文件都會去include一個system_icons.xml布局,
這個布局就是所要尋找的網絡信號欄顯示和電池圖標顯示view的地方。
android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center_vertical"> android:layout_height="match_parent" android:gravity="center_vertical" android:orientation="horizontal"/> android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="2.5dp"/> android:layout_width="9.5dp" android:layout_marginBottom="@dimen/battery_margin_bottom"/>
這個布局又會去include一個signal_cluster_view.xml布局,即這個布局才是具體的信號欄的布局文件
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="wrap_content" android:gravity="center_vertical" android:orientation="horizontal" android:paddingEnd="@dimen/signal_cluster_battery_padding" > android:id="@+id/vpn" android:layout_height="wrap_content" android:layout_width="wrap_content" android:paddingEnd="6dp" android:src="@drawable/stat_sys_vpn_ic" /> android:id="@+id/wifi_combo" android:layout_height="wrap_content" android:layout_width="wrap_content" > android:id="@+id/wifi_signal" android:layout_height="wrap_content" android:layout_width="wrap_content" /> android:id="@+id/wifi_signal_spacer" android:layout_width="4dp" android:layout_height="4dp" android:visibility="gone" /> android:id="@+id/mobile_signal_group" android:layout_height="wrap_content" android:layout_width="wrap_content" > android:id="@+id/no_sims" android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="@drawable/stat_sys_no_sims" /> android:id="@+id/wifi_airplane_spacer" android:layout_width="4dp" android:layout_height="4dp" android:visibility="gone" /> android:id="@+id/airplane" android:layout_height="wrap_content" android:layout_width="wrap_content" />
代碼邏輯方面:
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
makeStatusBarView()方法:
在這個方法內先去創建兩個控制器mNetworkController、mSecurityController;
mNetworkController=newNetworkControllerImpl(mContext,mHandlerThread.getLooper());
mSecurityController=newSecurityControllerImpl(mContext); NetworkControllerImpl.java繼承於BroadcastReceiver,再看下NetworkControllerImpl的構造方法:
publicNetworkControllerImpl(Contextcontext,LooperbgLooper){ this(context,(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE), (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE), (WifiManager)context.getSystemService(Context.WIFI_SERVICE), SubscriptionManager.from(context),Config.readConfig(context),bgLooper, newCallbackHandler(), newAccessPointControllerImpl(context,bgLooper), newMobileDataControllerImpl(context), newSubscriptionDefaults()); mReceiverHandler.post(mRegisterListeners);
} 這個構造方法內部會先去調用一個另外的構造方法;
@VisibleForTesting NetworkControllerImpl(Contextcontext,ConnectivityManagerconnectivityManager, TelephonyManagertelephonyManager,WifiManagerwifiManager, SubscriptionManagersubManager,Configconfig,LooperbgLooper, CallbackHandlercallbackHandler, AccessPointControllerImplaccessPointController, MobileDataControllerImplmobileDataController, SubscriptionDefaultsdefaultsHandler){ mContext=context; mConfig=config; mReceiverHandler=newHandler(bgLooper); mCallbackHandler=callbackHandler; mSubscriptionManager=subManager; mSubDefaults=defaultsHandler; mConnectivityManager=connectivityManager; mHasMobileDataFeature= mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); //telephony mPhone=telephonyManager; //wifi mWifiManager=wifiManager; mLocale=mContext.getResources().getConfiguration().locale; mAccessPoints=accessPointController; mMobileDataController=mobileDataController; mMobileDataController.setNetworkController(this); //TODO:FindawaytomovethisintoMobileDataController. mMobileDataController.setCallback(newMobileDataControllerImpl.Callback(){ @Override publicvoidonMobileDataEnabled(booleanenabled){ mCallbackHandler.setMobileDataEnabled(enabled); } }); mWifiSignalController=newWifiSignalController(mContext,mHasMobileDataFeature, mCallbackHandler,this); mEthernetSignalController=newEthernetSignalController(mContext,mCallbackHandler,this); //AIRPLANE_MODE_CHANGEDissentatboot;we'veprobablyalreadymissedit updateAirplaneMode(true/*forcecallback*/);
} 1、給相應的成員變量賦值;
2、創建handler,mReceiverHandler、mCallbackHandler;
3、創建mMobileDataController控制器,並為其設置回調;
4、創建mWifiSignalController,mEthernetSignalController控制器;
5、檢查更新飛行模式;
然後執行完這個內部的構造方法後,接下來會去使用mReceiverHandler去執行一個注冊廣播的操作,負責監控 wifi, SIM卡狀態, service state ,飛行模式等等,最後調用updateMobileControllers()方法初始化一下信號欄顯示:
mReceiverHandler.post(mRegisterListeners); /** *UsedtoregisterlistenersfromtheBGLooper,thiswaythePhoneStateListenersthat *getcreatedwillalsorunontheBGLooper. */ privatefinalRunnablemRegisterListeners=newRunnable(){ @Override publicvoidrun(){ registerListeners(); } }; privatevoidregisterListeners(){ for(MobileSignalControllermobileSignalController:mMobileSignalControllers.values()){ mobileSignalController.registerListener(); } if(mSubscriptionListener==null){ mSubscriptionListener=newSubListener(); } mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener); //broadcasts IntentFilterfilter=newIntentFilter(); 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.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_LOCALE_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); if(carrier!=null&&(CarrierAppUtils.CARRIER.TELEPHONY_CARRIER_ONE ==carrier)){ filter.addAction(ACTION_EMBMS_STATUS); } mContext.registerReceiver(this,filter,null,mReceiverHandler); mListening=true; updateMobileControllers(); } 分析完NetworkControllerImpl.java的構造方法之後,基本上我們可以知道NetworkControllerImpl.java是作為信號欄數據控制類,負責監控 wifi, service state ,飛行模式等。 再來看SecurityControllerImpl.java的構造方法,主要先獲取一些系統服務的實例,然後再去注冊一個用戶切換時候的網絡回調接口; publicSecurityControllerImpl(Contextcontext){ mContext=context; mDevicePolicyManager=(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); mConnectivityManager=(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); mConnectivityManagerService=IConnectivityManager.Stub.asInterface( ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); mUserManager=(UserManager) context.getSystemService(Context.USER_SERVICE); //TODO:re-registernetworkcallbackonuserchange. mConnectivityManager.registerNetworkCallback(REQUEST,mNetworkCallback); onUserSwitched(ActivityManager.getCurrentUser()); }
回到PhoneStatusBar.java的makeStatusBarView()方法,接下來實例化自定義的view對象SignalClusterView,上面說過在android SystemUI的三個地方都需要使用網絡信號狀態欄,所以分別實例化了三次,並為其添加相應的接口。
finalSignalClusterViewsignalCluster= (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster); finalSignalClusterViewsignalClusterKeyguard= (SignalClusterView)mKeyguardStatusBar.findViewById(R.id.signal_cluster); finalSignalClusterViewsignalClusterQs= (SignalClusterView)mHeader.findViewById(R.id.signal_cluster); mNetworkController.addSignalCallback(signalCluster); mNetworkController.addSignalCallback(signalClusterKeyguard); mNetworkController.addSignalCallback(signalClusterQs); signalCluster.setSecurityController(mSecurityController); signalCluster.setNetworkController(mNetworkController); signalClusterKeyguard.setSecurityController(mSecurityController); signalClusterKeyguard.setNetworkController(mNetworkController); signalClusterQs.setSecurityController(mSecurityController); signalClusterQs.setNetworkController(mNetworkController);
先來看下addSignalCallback()方法,傳入的參數為SignalClusterView.java的對象,也就是可以大膽推測這個方法的作用應該就是將SignalClusterView.java和NetworkControllerImpl.java建立callback調用。可以具體來分析下,這個方法的主要實現是在NetworkControllerImpl.java中
publicvoidaddSignalCallback(SignalCallbackcb){ mCallbackHandler.setListening(cb,true); mCallbackHandler.setSubs(mCurrentSubscriptions); mCallbackHandler.setIsAirplaneMode(newIconState(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON,R.string.accessibility_airplane_mode,mContext)); mCallbackHandler.setNoSims(mHasNoSims); mWifiSignalController.notifyListeners(); mEthernetSignalController.notifyListeners(); for(MobileSignalControllermobileSignalController:mMobileSignalControllers.values()){ mobileSignalController.notifyListeners(); } }
最近一直在調用微信的API,卻發現一直調用不成功,糾結了好久,各方面找教程,找官方,官方裡的文檔也只是寫得很模糊,說是按三步走。1、申請App_ID 2、填寫包
本文實例講述了Android開發中include控件用法。分享給大家供大家參考,具體如下:我們知道,基於Android系統的應用程序的開發,界面設計是非常重要的,它關系著
本文實例講述了Android中Spinner控件之鍵值對用法。分享給大家供大家參考。具體如下:一、字典表,用來存放鍵值對信息package com.ljq.activit
問題分析 相信大家對於ImageView圖片組件並不陌生吧,見名知意,就是用來顯示圖片的咯! 而顯示圖片的話可以通過src屬性,又或者blac