Android 状态栏WiFi图标的显示逻辑

简介: Android 状态栏WiFi图标的显示逻辑

1. 状态栏信号图标

1.1 WIFI信号显示

WIFI信号在状态栏的显示如下图所示

当WiFi状态为关闭时,状态栏不会有任何显示。当WiFi状态打开时,会如上图所示,左侧表示有可用WiFi,右侧表示当前WiFi打开但未连接。

当WiFi状态连接时,会如上图所示,显示信号连接强度和数据连接状态。


1.2 图标更新流程框架


如图所示,WiFi图标的显示流程主要是通过监听系统的WiFi状态,然后通知UI去实时的刷新图标资源。NetworkControllerImpl.java 继承 BroadcastReceiver 监听系统WiFi状态的变化。


2. WIFI图标更新流介绍


2.1 重要类

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\NetworkControllerImpl.java

定义相关函数,继承BroadcastReceiver监听系统广播,动态注册广播接收器。是状态栏WiFi图标更新的核心类。

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\WifiIcons.java

定义了 Wifi 信号更新所需的图标资源。

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java

frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\WifiSignalController.java


2.2 WIFI图标更新流程


(1)WifiNetworkController实例化,在NetworkControllerImpl.java进行实例化


frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\connectivity\NetworkControllerImpl.java

    @VisibleForTesting
    NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
            TelephonyManager telephonyManager,
            TelephonyListenerManager telephonyListenerManager,
            WifiManager wifiManager,
            SubscriptionManager subManager,
            Config config,
            Looper bgLooper,
            Executor bgExecutor,
            CallbackHandler callbackHandler,
            AccessPointControllerImpl accessPointController,
            StatusBarPipelineFlags statusBarPipelineFlags,
            DataUsageController dataUsageController,
            SubscriptionDefaults defaultsHandler,
            DeviceProvisionedController deviceProvisionedController,
            BroadcastDispatcher broadcastDispatcher,
            UserTracker userTracker,
            DemoModeController demoModeController,
            CarrierConfigTracker carrierConfigTracker,
            WifiStatusTrackerFactory trackerFactory,
            MobileSignalControllerFactory mobileFactory,
            @Main Handler handler,
            DumpManager dumpManager,
            LogBuffer logBuffer
    ) {
        mContext = context;
        mTelephonyListenerManager = telephonyListenerManager;
        mConfig = config;
        mMainHandler = handler;
        mReceiverHandler = new Handler(bgLooper);
        mBgLooper = bgLooper;
        mBgExecutor = bgExecutor;
        mCallbackHandler = callbackHandler;
        mStatusBarPipelineFlags = statusBarPipelineFlags;
        mDataSaverController = new DataSaverControllerImpl(context);
        mBroadcastDispatcher = broadcastDispatcher;
        mMobileFactory = mobileFactory;
 
        mSubscriptionManager = subManager;
        mSubDefaults = defaultsHandler;
        mConnectivityManager = connectivityManager;
        mHasMobileDataFeature = telephonyManager.isDataCapable();
        mDemoModeController = demoModeController;
        mCarrierConfigTracker = carrierConfigTracker;
        mDumpManager = dumpManager;
        mLogBuffer = logBuffer;
 
        // telephony
        mPhone = telephonyManager;
 
        // wifi
        mWifiManager = wifiManager;
 
        mLocale = mContext.getResources().getConfiguration().locale;
        mAccessPoints = accessPointController;
        mDataUsageController = dataUsageController;
        mDataUsageController.setNetworkController(this);
        // TODO: Find a way to move this into DataUsageController.
        mDataUsageController.setCallback(new DataUsageController.Callback() {
            @Override
            public void onMobileDataEnabled(boolean enabled) {
                mCallbackHandler.setMobileDataEnabled(enabled);
                notifyControllersMobileDataChanged();
            }
        });
 
        mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
                mCallbackHandler, this, mWifiManager, trackerFactory,
                mReceiverHandler);


注册广播


@VisibleForTesting
    void registerListeners() {
        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
            mobileSignalController.registerListener();
        }
        if (mSubscriptionListener == null) {
            mSubscriptionListener = new SubListener(mBgLooper);
        }
        mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
        mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
 
        // broadcasts
        IntentFilter filter = new IntentFilter();
        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        filter.addAction(Intent.ACTION_SERVICE_STATE);
        filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
        filter.addAction(Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
        filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
        filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
        filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
        filter.addAction(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler);
        mListening = true;
 
        // Initial setup of connectivity. Handled as if we had received a sticky broadcast of
        // ConnectivityManager.CONNECTIVITY_ACTION.
        mReceiverHandler.post(this::updateConnectivity);
 
        // Initial setup of WifiSignalController. Handled as if we had received a sticky broadcast
        // of WifiManager.WIFI_STATE_CHANGED_ACTION or WifiManager.NETWORK_STATE_CHANGED_ACTION
        mReceiverHandler.post(mWifiSignalController::fetchInitialState);
 
        // Initial setup of mLastServiceState. Only run if there is no service state yet.
        // Each MobileSignalController will also get their corresponding
        mReceiverHandler.post(() -> {
            if (mLastServiceState == null) {
                mLastServiceState = mPhone.getServiceState();
                if (mMobileSignalControllers.size() == 0) {
                    recalculateEmergency();
                }
            }
        });
        updateMobileControllers();
 
        // Initial setup of emergency information. Handled as if we had received a sticky broadcast
        // of TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED.
        mReceiverHandler.post(this::recalculateEmergency);
    }


当收到广播时,更新图标


@Override
    public void onReceive(Context context, Intent intent) {
        if (true) {
            Log.d(TAG, "onReceive: intent=" + intent);
        }
        final String action = intent.getAction();
        mLogBuffer.log(
                TAG,
                LogLevel.INFO,
                logMessage -> {
                    logMessage.setStr1(action);
                    return Unit.INSTANCE;
                },
                logMessage -> String.format(
                        Locale.US,
                        "Received broadcast with action \"%s\"",
                        logMessage.getStr1()));
        switch (action) {
            case ConnectivityManager.CONNECTIVITY_ACTION:
                updateConnectivity();
                break;
            case Intent.ACTION_AIRPLANE_MODE_CHANGED:
                refreshLocale();
                updateAirplaneMode(false);
                break;
            case TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
                // We are using different subs now, we might be able to make calls.
                recalculateEmergency();
                break;
            case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
                // Notify every MobileSignalController so they can know whether they are the
                // data sim or not.
                for (int i = 0; i < mMobileSignalControllers.size(); i++) {
                    MobileSignalController controller = mMobileSignalControllers.valueAt(i);
                    controller.handleBroadcast(intent);
                }
                mConfig = Config.readConfig(mContext);
                mReceiverHandler.post(this::handleConfigurationChanged);
                break;
 
            case TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED: {
                // Notify the relevant MobileSignalController of the change
                int subId = intent.getIntExtra(
                        TelephonyManager.EXTRA_SUBSCRIPTION_ID,
                        INVALID_SUBSCRIPTION_ID
                );
                if (SubscriptionManager.isValidSubscriptionId(subId)) {
                    if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                        mMobileSignalControllers.get(subId).handleBroadcast(intent);
                    }
                }
            }
            break;
            case Intent.ACTION_SIM_STATE_CHANGED:
                // Avoid rebroadcast because SysUI is direct boot aware.
                if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
                    break;
                }
                // Might have different subscriptions now.
                updateMobileControllers();
                break;
            case Intent.ACTION_SERVICE_STATE:
                mLastServiceState = ServiceState.newFromBundle(intent.getExtras());
                if (mMobileSignalControllers.size() == 0) {
                    // If none of the subscriptions are active, we might need to recalculate
                    // emergency state.
                    recalculateEmergency();
                }
                break;
            case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
                mConfig = Config.readConfig(mContext);
                mReceiverHandler.post(this::handleConfigurationChanged);
                break;
            case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
                mMainHandler.post(() -> mInternetDialogFactory.create(true,
                        mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi(),
                        null /* view */));
                break;
            default:
                int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
                        INVALID_SUBSCRIPTION_ID);
                if (SubscriptionManager.isValidSubscriptionId(subId)) {
                    if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
                        mMobileSignalControllers.get(subId).handleBroadcast(intent);
                    } else {
                        // Can't find this subscription...  We must be out of date.
                        updateMobileControllers();
                    }
                } else {
                    // No sub id, must be for the wifi.
                    mWifiSignalController.handleBroadcast(intent);
                }
                break;
        }
    }


目录
相关文章
|
13天前
|
API Android开发
31. 【Android教程】状态栏通知:Notification
31. 【Android教程】状态栏通知:Notification
11 1
|
1月前
|
Android开发
Android获取当前连接的wifi名称
Android获取当前连接的wifi名称
34 6
|
1月前
|
Java Android开发
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
27 1
|
1月前
|
Android开发
android连接指定wifi
android连接指定wifi
22 0
|
1月前
|
Java Android开发
Android 9在连接以太网情况下 还能连接WiFi
Android 9在连接以太网情况下 还能连接WiFi
19 0
|
1月前
|
Android开发
Android12 ethernet和wifi共存
Android12 ethernet和wifi共存
57 0
|
1月前
|
Java Shell Android开发
Android11 有线网和wifi优先级设置
Android11 有线网和wifi优先级设置
53 0
|
1月前
|
Java Android开发 开发者
rk3399 android以太网和wifi共存
rk3399 android以太网和wifi共存
28 0
|
1月前
|
Android开发 Python
Python封装ADB获取Android设备wifi地址的方法
Python封装ADB获取Android设备wifi地址的方法
71 0
|
1月前
|
XML API Android开发
Android WIFI使用简述(上)
Android WIFI使用简述(上)
104 0