Customization of battery icon in Android 11 status bar

1. Display process of battery icon in status bar

//packages/SystemUI/src/com/android/systemui/BatteryMeterView.java

public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {

    mBatteryIconView = new ImageView(context);

    mBatteryIconView.setImageDrawable(mDrawable);

    final MarginLayoutParams mlp = new MarginLayoutParams(

                getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_width),

                getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_height));

    mlp.setMargins(0, 0, 0,

                getResources().getDimensionPixelOffset(R.dimen.battery_margin_bottom));

    addView(mBatteryIconView, mlp);

}

In the construction method of batteryMeterView, new creates an ImageView, which is the view of the battery icon

Set the picture to mDrawable through setImageDrawable. mDrawable is drawn through code. Our scene is to add radio wave icons on both sides of the battery icon during wireless charging

Keep the original battery icon unchanged and add the radio wave icon during wireless charging

public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {

    mDrawable.setCharging(pluggedIn);

    mDrawable.setBatteryLevel(level);

    mCharging = pluggedIn;

    mLevel = level;

    updatePercentText();

}

When receiving the battery change broadcast, this method will be called. In this method, you can see whether the attribute of charging is set for mDrawable and the attribute of battery power

mDrawable draws the current battery icon through these two attributes

2. Demand realization

If we want to realize wireless charging, we need to know under what circumstances is the wireless charging state and what methods we can judge

//packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java

protected String computePowerIndication() {

    if (mPowerCharged) {

        return mContext.getResources().getString(R.string.keyguard_charged);

    }

    int chargingId;

    String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);

    if (mBatteryOverheated) {

        chargingId = R.string.keyguard_plugged_in_charging_limited;

        return mContext.getResources().getString(chargingId, percentage);

    }

    final boolean hasChargingTime = mChargingTimeRemaining > 0;

    //mPowerPluggedInWired  ==  false   Wireless charging

    if (mPowerPluggedInWired) {

        switch (mChargingSpeed) {

            case BatteryStatus.CHARGING_FAST:

                chargingId = hasChargingTime

                        ? R.string.keyguard_indication_charging_time_fast

                        : R.string.keyguard_plugged_in_charging_fast;

                break;

            case BatteryStatus.CHARGING_SLOWLY:

                chargingId = hasChargingTime

                        ? R.string.keyguard_indication_charging_time_slowly

                        : R.string.keyguard_plugged_in_charging_slowly;

                break;

            default:

                chargingId = hasChargingTime

                        ? R.string.keyguard_indication_charging_time

                        : R.string.keyguard_plugged_in;

                break;

        }

    } else {

        chargingId = hasChargingTime

                ? R.string.keyguard_indication_charging_time_wireless

                : R.string.keyguard_plugged_in_wireless;

    }

}

The charging prompt text on the lock screen is judged in this way, so we can use the same method, and we need the cooperation of bottom colleagues to adapt this method

Wireless charging if not limited charging

Take a closer look at how MPOWER pluggedinwired gets this value

public void onRefreshBatteryInfo(BatteryStatus status) {

    boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING

            || status.status == BatteryManager.BATTERY_STATUS_FULL;

    boolean wasPluggedIn = mPowerPluggedIn;

    mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;

    mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;

    mPowerCharged = status.isCharged();

    mChargingWattage = status.maxChargingWattage;

    mChargingSpeed = status.getChargingSpeed(mContext);

    mBatteryLevel = status.level;

    mBatteryOverheated = status.isOverheated();

    mEnableBatteryDefender = mBatteryOverheated && status.isPluggedIn();

    mBatteryPresent = status.present;

}

Check whether the status of BatteryStatus is charged or fully charged, and if BatteryStatus.ispluggeinwired returns true, it means limited charging. Through this logic, we can obtain whether it is currently in wireless charging status

Check that the onBatteryLevelChanged in the above code BatteryMeterView does not carry the relevant parameters that we need to judge whether to charge wirelessly. Therefore, we need to find the source of calling this method and add the parameters of charging wirelessly

//packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java

public void onReceive(final Context context, Intent intent) {

    final String action = intent.getAction();

    if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {

        if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;

        mHasReceivedBattery = true;

        mLevel = (int)(100f

                * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)

                / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));

        mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;

        final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,

                BatteryManager.BATTERY_STATUS_UNKNOWN);

        mCharged = status == BatteryManager.BATTERY_STATUS_FULL;

        mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;

        mWirelessCharging = mCharging && intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)

                == BatteryManager.BATTERY_PLUGGED_WIRELESS;

        boolean present = intent.getBooleanExtra(EXTRA_PRESENT, true);

        boolean unknown = !present;

        if (unknown != mStateUnknown) {

            mStateUnknown = unknown;

            fireBatteryUnknownStateChanged();

        }

        fireBatteryLevelChanged();

    }

}

protected void fireBatteryLevelChanged() {

    synchronized (mChangeCallbacks) {

        final int N = mChangeCallbacks.size();

        for (int i = 0; i < N; i++) {

            mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);

        }

    }

}

After receiving the battery change broadcast, whether relevant parameters are obtained and passed to BatteryMeterView

In onReceive, we need to obtain relevant attributes by locking the screen to obtain wireless charging, and pass them on

After passing the attributes of wireless charging, we need to add relevant pictures to the View in the batteryMeterView

In the construction method of batteryMeterView, new has two imageviews, one for the radio wave picture on the left and one for the radio wave picture on the right

In the onBatteryLevelChanged method, it is judged that if it is wireless charging, two radio wave pictures are added to the parent View through addView. Thus, wireless charging is realized

Demand for battery icons when powered

However, the color of the icon on the status bar needs to be changed according to different situations, which requires us to consider the color problem

The interface has been given in BatteryMeterView

Tags: Android

Posted on Wed, 29 Sep 2021 22:44:30 -0400 by elabuwa