BatteryService 浅析

极力推荐Android 开发大总结文章:欢迎收藏
程序员Android 力荐 ,Android 开发者需要的必备技能

 

BatteryService是电池管理的重要服务,该服务继承SystemService,主要用于管理 电池的充电状态,充电百分比等。

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

  1. BatteryService 简介
  2. BatteryService 继承关系
  3. BatteryService 构造函数
  4. BatteryService 开始引导阶段
  5. processValuesLocked 处理电池属性变化事件
  6. 低电量关机,高温、NTC 关机实现
  7. NTC 电池高低温警示及关机实现
  8. 充电提示音实现

欢迎关注微信公众号:程序员Android
公众号ID:ProgramAndroid
获取更多信息

微信公众号:ProgramAndroid

我们不是牛逼的程序员,我们只是程序开发中的垫脚石。
我们不发送红包,我们只是红包的搬运工。

1. BatteryService 简介

BatteryService是电池管理的重要服务,该服务继承SystemService,主要用于管理 电池的充电状态,充电百分比等。

另外,power manager 会吊起BatteryService,并获取使用锁,因此在Activity Manager中通过Handler post 消息时候,请谨慎使用!

2. BatteryService 继承关系

BatteryService 继承 SystemService,是电池管理中一个重要的服务之一。

BatteryService 继承 SystemService

3. BatteryService 构造函数

BatteryService 主要控制手机充电呼吸灯,低电量提示,高温关机等。

BatteryService 构造函数

电量相关常用配置修改路径如下:
frameworks\base\core\res\res\values\config.xml

电量相关常用配置信息如下:

BatteryService 常用配置信息

4. BatteryService 开始引导阶段

BatteryService 开始引导阶段加载电池属性,注册监听,监视事件。

BatteryService 开始引导阶段加载电池属性,注册监听,监视事件

5.processValuesLocked 处理电池属性变化事件

updateBatteryWarningLevelLocked() 方法中会调用 processValuesLocked() 处理监听电池信息改变事件。

processValuesLocked 处理电池属性变化事件

processValuesLocked 对外广播电池信息变更

6.低电量关机,高温、NTC 关机实现,

高温关机实现代码

低电量关机

NTC 关机模式状态

NTC 常见配置值

7. NTC 电池高低温警示及关机实现

大概实现就是电池在高温或者低温时候给客户一个提示,在低于某个温度后关机。


   AlertDialog mNtcWarnDialog = null;
   AlertDialog mNtcShutdownDialog = null;
   private static final int NTC_LEVEL_NORMAL = 0;
    private static final int NTC_LEVEL_HIGH_WARN = 1;
    private static final int NTC_LEVEL_CRITICAL_HIGH_SHUTDOWN = 2;
    private static final int NTC_LEVEL_LOW_WARN = 3;
    private static final int NTC_LEVEL_CRITICAL_LOW_SHUTDOWN = 4;
    private int getNtcLevel(int temperature) {
        boolean DEBUG_FAKE_TEMP = false;
        if(DEBUG_FAKE_TEMP) {
            int t = android.os.SystemProperties.getInt("persist.debug.battery.high", 200);
            Slog.w(TAG, "DEBUG: ntc change temperature = " + temperature + " to " + t);
            temperature = t;
        }
        if(temperature >= Features.JAVA_VALUE_NTC_HIGH_SHUTDOWN) {
            return NTC_LEVEL_CRITICAL_HIGH_SHUTDOWN;
        }else if(temperature >= Features.JAVA_VALUE_NTC_HIGH_WARN){
            return NTC_LEVEL_HIGH_WARN;
        }else if(temperature <= Features.JAVA_VALUE_NTC_LOW_SHUTDOWN) {
            return NTC_LEVEL_CRITICAL_LOW_SHUTDOWN;
        }else if(temperature <= Features.JAVA_VALUE_NTC_LOW_WARN) {
            return NTC_LEVEL_LOW_WARN;
        }else {
            return NTC_LEVEL_NORMAL;
        }
    }

    private void doShutdown() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mActivityManagerInternal.isSystemReady()) {
                    Slog.w(TAG, "shutdownIfOverTempLockedNtc, batteryTemperature : "
                        + mBatteryProps.batteryTemperature);
                    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);
                }
                mNtcShutdownDialog = null;
                mShutDownTimer = null;
            }
        });
    }

    private AlertDialog getAlertDialog(String msg, boolean cancel, Runnable r) {
        AlertDialog tempDialog = null;
        AlertDialog.Builder b = new AlertDialog.Builder(mContext);
        b.setCancelable(cancel);
        b.setIconAttribute(android.R.attr.alertDialogIcon);
        b.setPositiveButton(android.R.string.ok, null);
        b.setMessage(msg);
        tempDialog = b.create();
        tempDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            public void onDismiss(DialogInterface dialog) {
                if(r != null)
                    r.run();
            }
        });
        tempDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        return tempDialog;
    }
    private CountDownTimer mShutDownTimer;
    private void shutdownIfOverTempLockedNtc() {
        // shut down gracefully if temperature is too high (> 68.0C by default)
        // wait until the system has booted before attempting to display the
        // shutdown dialog.
        final int ntcLevel = getNtcLevel(mBatteryProps.batteryTemperature);
        if ((ntcLevel == NTC_LEVEL_CRITICAL_HIGH_SHUTDOWN || ntcLevel == NTC_LEVEL_CRITICAL_LOW_SHUTDOWN)
            && mActivityManagerInternal.isSystemReady()) {
            if(ntcLevel == NTC_LEVEL_CRITICAL_HIGH_SHUTDOWN && Features.JAVA_VALUE_NTC_HIGH_SHUTDOWN_INTERVAL > 0) {
                android.util.Log.d(TAG, "mNtcShutdownDialog=" + mNtcShutdownDialog);
                if(mNtcShutdownDialog == null && mShutDownTimer == null) {
                    mHandler.post(new Runnable(){
                        @Override
                        public void run() {
                            mNtcShutdownDialog = getAlertDialog(mContext.getString(com.android.internal.R.string.battery_temperature_shutdown, 
                                Features.JAVA_VALUE_NTC_HIGH_SHUTDOWN_INTERVAL), false, 
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        mNtcShutdownDialog = null;
                                    }
                                });
                            mShutDownTimer = new CountDownTimer(Features.JAVA_VALUE_NTC_HIGH_SHUTDOWN_INTERVAL * 1000, 1000) {
                                @Override  
                                public void onTick(long millisUntilFinished) {  
                                    if(mNtcShutdownDialog != null) 
                                        mNtcShutdownDialog.setMessage(mContext.getString(com.android.internal.R.string.battery_temperature_shutdown, 
                                            millisUntilFinished/1000));
                                }
                                @Override  
                                public void onFinish() {
                                    doShutdown();
                                }
                            };
                            android.util.Log.d(TAG, "show=" + mNtcShutdownDialog);
                            mNtcShutdownDialog.show();
                            mShutDownTimer.start();
                        }
                    });
                }
            }else{
                doShutdown();
            }
        }

        if((ntcLevel == NTC_LEVEL_HIGH_WARN || ntcLevel == NTC_LEVEL_LOW_WARN)
            && isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)
            && mNtcWarnDialog == null
            && mActivityManagerInternal.isSystemReady()){
            mHandler.post(new Runnable(){
                @Override
                public void run() {
                    if(mNtcWarnDialog == null){
                        if(ntcLevel == NTC_LEVEL_HIGH_WARN) {
                            mNtcWarnDialog = getAlertDialog(mContext.getString(com.android.internal.R.string.battery_temperature_warning_charger), false, 
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        mNtcWarnDialog = null;
                                    }
                                });
                            mNtcWarnDialog.show();
                        }else {
                            mNtcWarnDialog = getAlertDialog(mContext.getString(com.android.internal.R.string.battery_temperature_low_warning_charger), false,
                                new Runnable() {
                                    @Override
                                    public void run() {
                                        mNtcWarnDialog = null;
                                    }
                                });
                            mNtcWarnDialog.show();
                        }
                    }
                }
            });
         }

        if(ntcLevel == NTC_LEVEL_NORMAL){
            if(mNtcWarnDialog != null) {
                mNtcWarnDialog.dismiss();
                mNtcWarnDialog = null;
            }
        }
    }

<string name="battery_temperature_low_warning_charger">Battery Under Temperature, Remove the charger!</string>
<string name="battery_temperature_warning_charger">Battery Over Temperature, Remove the charger!</string>
<string name="battery_temperature_shutdown">Battery Over Temperature, Phone will shutdown in <xliff:g id="secs">%d</xliff:g>s!</string>
<java-symbol type="string" name="battery_temperature_warning_charger" />
<java-symbol type="string" name="battery_temperature_low_warning_charger" />
<java-symbol type="string" name="battery_temperature_shutdown" />

8. 充电提示音实现

无论插入座充,还是 USB充电,当连接充电器的时候,发个提示音给客户,表示正在充电,也是一个满友好的设计,具体实现代码如下:


private MediaPlayer mMediaPlayer;
    private void StartUSBAlarm() {
        try {
            if (mMediaPlayer == null) {
                mMediaPlayer = new MediaPlayer();
            }
            if (mMediaPlayer.isPlaying()) {
                mMediaPlayer.stop();
            }
            mMediaPlayer.reset();
            mMediaPlayer.setDataSource(this, RingtoneManager
                    .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
            mMediaPlayer.prepare();
            mMediaPlayer.start();
            mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    StopUSBAlarm();
                }
            });
            mMediaPlayer.setOnErrorListener(new OnErrorListener() {

                @Override
                public boolean onError(MediaPlayer mp, int what, int extra) {
                    StopUSBAlarm();
                    return false;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void StopUSBAlarm() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

这里要注意 MediaPlayer 资源使用释放不当,会导致播放声音无效,使用前请注意使用mMediaPlayer.reset();

在 Power Connect 以及disconnect 时候添加声音的播放与停止,实现代码如下:

在 Power Connect 以及disconnect 时候添加声音的播放与停止

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

如有侵权,请联系小编,小编对此深感抱歉,届时小编会删除文章,立即停止侵权行为,请您多多包涵。

既然都看到这里,领两个红包在走吧!
以下两个红包每天都可以领取

1.支付宝搜索 522398497,或扫码支付宝红包海报。

支付宝扫一扫,每天领取大红包

2.微信红包,微信扫一扫即可领取红包

 

微信扫一扫,每天领取微信红包

小礼物走一走,来简书关注我

posted @ 2018-03-15 11:19  程序员Android的博客  阅读(218)  评论(0编辑  收藏  举报