Android Low Battery 低电量处理流程

2019-04-14 15:32发布

点击打开链接Android 通过BatteryService对电量进行自动管理。在BatteryService.java中从jni层获得电量mBatteryLevel,  并根据mBatteryLevel判断手机电量是否过低,然后发出警告或声音提醒,并且太低时还会自动关机。下面简单介绍一下其流程。       在BatteryService.java中判断当前电量是否过低:[java] view plain copy
  1. /* The ACTION_BATTERY_LOW broadcast is sent in these situations: 
  2.  * - is just un-plugged (previously was plugged) and battery level is 
  3.  *   less than or equal to WARNING, or 
  4.  * - is not plugged and battery level falls to WARNING boundary 
  5.  *   (becomes <= mLowBatteryWarningLevel). 
  6.  */  
  7. final boolean sendBatteryLow = !plugged  
  8.         && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN  
  9.         && mBatteryLevel <= mLowBatteryWarningLevel  
  10.         && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel);  
如果当前电量小于警告电量(在config.xml中 15)则弹出电量低提示,或者电量为0(当然这个有误差也可能是5%时就自动关机)时自动关机。如果低电量的话就发送一个广播出去:[java] view plain copy
  1. if (sendBatteryLow) {  
  2.     mSentLowBatteryBroadcast = true;  
  3.     statusIntent.setAction(Intent.ACTION_BATTERY_LOW);  
  4.     mContext.sendBroadcast(statusIntent);  
  5. }  
        下面这段代码是电量过低而自动关机:
[java] view plain copy
  1. private void More ...shutdownIfNoPowerLocked() {  
  2.     // shut down gracefully if our battery is critically low and we are not powered.  
  3.     // wait until the system has booted before attempting to display the shutdown dialog.  
  4.     if (mBatteryLevel == 0 && !isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY)) {  
  5.         mHandler.post(new Runnable() {  
  6.             @Override  
  7.             public void More ...run() {  
  8.                 if (ActivityManagerNative.isSystemReady()) {  
  9.                     Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);  
  10.                     intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);  
  11.                     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  12.                     mContext.startActivityAsUser(intent, UserHandle.CURRENT);  
  13.                 }  
  14.             }  
  15.         });  
  16.     }  
  17. }  
        而在StatusBarPolicy.java中会接收广播, 里面有判断当接受到ACTION_BATTERY_LOW时, 调用onBatteryLow(intent)方法来处理:[java] view plain copy
  1. private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {  
  2.         @Override  
  3.         public void onReceive(Context context, Intent intent) {  
  4.             String action = intent.getAction();  
  5.             .....action.  
  6.             //里面会有判断当接受到ACTION_BATTERY_LOW时:  
  7.             else if (action.equals(Intent.ACTION_BATTERY_LOW)) {  
  8.                 onBatteryLow(intent);  
  9.             }  
  10.         }  
  11.     }  
  12.       
  13.     private void onBatteryLow(Intent intent) {  
  14.         if (SHOW_LOW_BATTERY_WARNING) {  
  15.             if (false) {  
  16.                 Slog.d(TAG, "mPhoneState=" + mPhoneState  
  17.                         + " mLowBatteryDialog=" + mLowBatteryDialog  
  18.                         + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);  
  19.             }  
  20.   
  21.             if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {  
  22.                 showLowBatteryWarning();  
  23.             } else {  
  24.                 mBatteryShowLowOnEndCall = true;  
  25.             }  
  26.         }  
  27.     }  
         弹出低电量过低Dialog提醒和声音提醒:
[java] view plain copy
  1. private void showLowBatteryWarning() {  
  2.     closeLastBatteryView();  
  3.   
  4.     // Show exact battery level.  
  5.     CharSequence levelText = mContext.getString(R.string.battery_low_percent_format, mBatteryLevel);  
  6.   
  7.     if (mBatteryLevelTextView != null) {  
  8.         mBatteryLevelTextView.setText(levelText);  
  9.     } else {  
  10.         View v = View.inflate(mContext, R.layout.battery_low, null);  
  11.         mBatteryLevelTextView=(TextView)v.findViewById(R.id.level_percent);  
  12.         mBatteryLevelTextView.setText(levelText);  
  13.         AlertDialog.Builder b = new AlertDialog.Builder(mContext);  
  14.         b.setCancelable(true);  
  15.         b.setTitle(R.string.battery_low_title);  
  16.         b.setView(v);  
  17.         b.setIcon(android.R.drawable.ic_dialog_alert);  
  18.         b.setPositiveButton(android.R.string.ok, null);  
  19.   
  20.         final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);  
  21.         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK  
  22.                 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK  
  23.                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS  
  24.                 | Intent.FLAG_ACTIVITY_NO_HISTORY);  
  25.         if (intent.resolveActivity(mContext.getPackageManager()) != null) {  
  26.             b.setNegativeButton(R.string.battery_low_why, new DialogInterface.OnClickListener() {  
  27.                 @Override  
  28.                 public void onClick(DialogInterface dialog, int which) {  
  29.                     mContext.startActivity(intent);  
  30.                     if (mLowBatteryDialog != null) {  
  31.                         mLowBatteryDialog.dismiss();  
  32.                     }  
  33.                 }  
  34.             });  
  35.         }  
  36.   
  37.         AlertDialog d = b.create();  
  38.         d.setOnDismissListener(mLowBatteryListener);  
  39.         d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);  
  40.         d.show();  
  41.         mLowBatteryDialog = d;  
  42.     }  
  43.       
  44.     //waring voiced  
  45.     final ContentResolver cr = mContext.getContentResolver();  
  46.     if (Settings.System.getInt(cr, Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) {  
  47.         final String soundPath = Settings.System.getString(cr, Settings.System.LOW_BATTERY_SOUND);  
  48.         if (soundPath != null) {  
  49.             final Uri soundUri = Uri.parse("file://" + soundPath);  
  50.             if (soundUri != null) {  
  51.                 final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);  
  52.                 if (sfx != null) {  
  53.                     sfx.setStreamType(AudioManager.STREAM_SYSTEM);  
  54.                     sfx.play();  
  55.                 }  
  56.             }  
  57.         }  
  58.     }  
  59. }