当前位置: 首页 > 工具软件 > Juice-battery > 使用案例 >

Android Low Battery 低电量处理流程

李甫
2023-12-01

      Android 通过BatteryService对电量进行自动管理。在BatteryService.java中从jni层获得电量mBatteryLevel,  并根据mBatteryLevel判断手机电量是否过低,然后发出警告或声音提醒,并且太低时还会自动关机。下面简单介绍一下其流程。

       在BatteryService.java中判断当前电量是否过低:

    /* The ACTION_BATTERY_LOW broadcast is sent in these situations:
     * - is just un-plugged (previously was plugged) and battery level is
     *   less than or equal to WARNING, or
     * - is not plugged and battery level falls to WARNING boundary
     *   (becomes <= mLowBatteryWarningLevel).
     */
    final boolean sendBatteryLow = !plugged
            && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
            && mBatteryLevel <= mLowBatteryWarningLevel
            && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);

如果当前电量小于警告电量(在config.xml中 <integer name="config_lowBatteryWarningLevel">15</integer>)则弹出电量低提示,或者电量为0(当然这个有误差也可能是5%时就自动关机)时自动关机。如果低电量的话就发送一个广播出去:

    if (sendBatteryLow) {
        mSentLowBatteryBroadcast = true;
        statusIntent.setAction(Intent.ACTION_BATTERY_LOW);
        mContext.sendBroadcast(statusIntent);
    }
        下面 这段代码是电量过低而自动关机:

    private void More ...shutdownIfNoPowerLocked() {
        // shut down gracefully if our battery is critically low and we are not powered.
        // wait until the system has booted before attempting to display the shutdown dialog.
        if (mBatteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {
            mHandler.post(new Runnable() {
                @Override
                public void More ...run() {
                    if (ActivityManagerNative.isSystemReady()) {
                        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
                        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivityAsUser(intent, UserHandle.CURRENT);
                    }
                }
            });
        }
    }
        而在StatusBarPolicy.java中会接收广播, 里面有判断当接受到ACTION_BATTERY_LOW时, 调用onBatteryLow(intent)方法来处理:

private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            .....action.
            //里面会有判断当接受到ACTION_BATTERY_LOW时:
            else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
                onBatteryLow(intent);
            }
        }
    }
    
    private void onBatteryLow(Intent intent) {
        if (SHOW_LOW_BATTERY_WARNING) {
            if (false) {
                Slog.d(TAG, "mPhoneState=" + mPhoneState
                        + " mLowBatteryDialog=" + mLowBatteryDialog
                        + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
            }

            if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
                showLowBatteryWarning();
            } else {
                mBatteryShowLowOnEndCall = true;
            }
        }
    }
         弹出低电量过低Dialog提醒和声音提醒:

    private void showLowBatteryWarning() {
        closeLastBatteryView();

        // Show exact battery level.
        CharSequence levelText = mContext.getString(R.string.battery_low_percent_format, mBatteryLevel);

        if (mBatteryLevelTextView != null) {
            mBatteryLevelTextView.setText(levelText);
        } else {
            View v = View.inflate(mContext, R.layout.battery_low, null);
            mBatteryLevelTextView=(TextView)v.findViewById(R.id.level_percent);
            mBatteryLevelTextView.setText(levelText);
            AlertDialog.Builder b = new AlertDialog.Builder(mContext);
            b.setCancelable(true);
            b.setTitle(R.string.battery_low_title);
            b.setView(v);
            b.setIcon(android.R.drawable.ic_dialog_alert);
            b.setPositiveButton(android.R.string.ok, null);

            final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                    | Intent.FLAG_ACTIVITY_NO_HISTORY);
            if (intent.resolveActivity(mContext.getPackageManager()) != null) {
                b.setNegativeButton(R.string.battery_low_why, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        mContext.startActivity(intent);
                        if (mLowBatteryDialog != null) {
                            mLowBatteryDialog.dismiss();
                        }
                    }
                });
            }

            AlertDialog d = b.create();
            d.setOnDismissListener(mLowBatteryListener);
            d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
            d.show();
            mLowBatteryDialog = d;
        }
        
        //waring voiced
        final ContentResolver cr = mContext.getContentResolver();
        if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {
            final String soundPath = Settings.System.getString(cr, Settings.System.LOW_BATTERY_SOUND);
            if (soundPath != null) {
                final Uri soundUri = Uri.parse("file://" + soundPath);
                if (soundUri != null) {
                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
                    if (sfx != null) {
                        sfx.setStreamType(AudioManager.STREAM_SYSTEM);
                        sfx.play();
                    }
                }
            }
        }
    }

 类似资料: