获取 Android 手机的电池电流值
Posted
技术标签:
【中文标题】获取 Android 手机的电池电流值【英文标题】:Getting the battery current values for the Android Phone 【发布时间】:2010-03-13 19:04:14 【问题描述】:我正在尝试收集 android G1 手机的电量使用统计信息。我有兴趣了解电压和电流的值,然后能够收集PDF 中报告的统计数据。
我可以通过注册意图接收器以接收 ACTION_BATTERY_CHANGED 的广播来获取电池电压的值。但是问题是Android没有通过这个SDK接口暴露current的值。
我尝试的一种方法是通过 sysfs 接口,我可以使用以下命令从 adb shell 查看电池电流值
$cat /sys/class/power_supply/battery/batt_current
449
但这也只有在手机通过 USB 接口连接时才有效。如果我断开电话,我会看到 batt_current 的值为“0”。我不确定为什么当前报告的值为零。它应该大于零,对吧?
获取电池当前值的任何建议/指针?如果我错了也请纠正我。
【问题讨论】:
您可能想在 YouTube 上观看该演示文稿。我在那里,我似乎记得 Sharkey 先生提到过一些关于为这些测量配备特殊硬件的事情。 Here's 一些您可以尝试的示例代码。 感谢您的链接,我正在使用类似的功能来读取电池电压。但 Android 不会通过该接口公开 current 的值。因此,如果您知道内核/底层的一些解决方法,请告诉我。 是的,他在演示文稿的最后提到,测量电流是通过硬件电子设备完成的,软件无济于事。你知道 sysfs 接口是如何工作的吗?如果可能的话,我们可以从中提取数据吗?谢谢你指点我看视频。 嗨@Chintan Parikh,您找到获得当前价值的好方法了吗?有一个应用程序可以获取当前值,但我不知道它是如何工作的。 play.google.com/store/apps/details?id=com.gombosdev.ampere 【参考方案1】:您可以只查看当前小部件的源代码。它具有特定平台存储当前值的硬编码路径。
/*
* Copyright (c) 2010-2011 Ran Manor
*
* This file is part of CurrentWidget.
*
* CurrentWidget is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CurrentWidget is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CurrentWidget. If not, see <http://www.gnu.org/licenses/>.
*/
package com.manor.currentwidget.library;
import java.io.File;
import android.os.Build;
import android.util.Log;
public class CurrentReaderFactory
static public Long getValue()
File f = null;
// htc desire hd / desire z / inspire?
if (Build.MODEL.toLowerCase().contains("desire hd") ||
Build.MODEL.toLowerCase().contains("desire z") ||
Build.MODEL.toLowerCase().contains("inspire"))
f = new File("/sys/class/power_supply/battery/batt_current");
if (f.exists())
return OneLineReader.getValue(f, false);
// nexus one cyangoenmod
f = new File("/sys/devices/platform/ds2784-battery/getcurrent");
if (f.exists())
return OneLineReader.getValue(f, true);
// sony ericsson xperia x1
f = new File("/sys/devices/platform/i2c-adapter/i2c-0/0-0036/power_supply/ds2746-battery/current_now");
if (f.exists())
return OneLineReader.getValue(f, false);
// xdandroid
/*if (Build.MODEL.equalsIgnoreCase("MSM")) */
f = new File("/sys/devices/platform/i2c-adapter/i2c-0/0-0036/power_supply/battery/current_now");
if (f.exists())
return OneLineReader.getValue(f, false);
/**/
// droid eris
f = new File("/sys/class/power_supply/battery/smem_text");
if (f.exists())
Long value = SMemTextReader.getValue();
if (value != null)
return value;
// htc sensation / evo 3d
f = new File("/sys/class/power_supply/battery/batt_attr_text");
if (f.exists())
Long value = BattAttrTextReader.getValue();
if (value != null)
return value;
// some htc devices
f = new File("/sys/class/power_supply/battery/batt_current");
if (f.exists())
return OneLineReader.getValue(f, false);
// nexus one
f = new File("/sys/class/power_supply/battery/current_now");
if (f.exists())
return OneLineReader.getValue(f, true);
// samsung galaxy vibrant
f = new File("/sys/class/power_supply/battery/batt_chg_current");
if (f.exists())
return OneLineReader.getValue(f, false);
// sony ericsson x10
f = new File("/sys/class/power_supply/battery/charger_current");
if (f.exists())
return OneLineReader.getValue(f, false);
// Nook Color
f = new File("/sys/class/power_supply/max17042-0/current_now");
if (f.exists())
return OneLineReader.getValue(f, false);
return null;
【讨论】:
我运行 Slimkat 的 GNex 的功率级别在 /sys/class/power_supply/battery/capacity 中,尽管它可能不会在这里使用,因为它是 % 值,而不是当前值。有趣的是,我的设备上没有您列出的文件。 这是 GNU 许可证。是否有用于类似代码的更好的许可证?另外,有没有覆盖所有设备的方法?【参考方案2】:从 API 21 开始,我们可以得到以微安为单位的瞬时电池电流,作为一个整数。 Developer docs
BatteryManager mBatteryManager = (BatteryManager) getSystemService(Context.BATTERY_SERVICE);
Long avgCurrent = null, currentNow = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
avgCurrent = mBatteryManager.getLongProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE);
currentNow = mBatteryManager.getLongProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW);
Log.d(TAG, "BATTERY_PROPERTY_CURRENT_AVERAGE = " + avgCurrent + "mAh");
Log.d(TAG, "BATTERY_PROPERTY_CURRENT_NOW = " + currentNow + "mAh");
使用 mBatteryManager 可以获得瞬时电流读数。
测量设备功耗和读取功耗以及 NEXUS 设备上的可用属性。 Android open source docs
【讨论】:
-9223372036854775808 mAh。这就是我一直得到的。 此 API 可能会提供当前值,但正如@HiteshDanidhariya 提到的那样,它并不总是保证在所有设备上都是准确的。 如 Android 开源文档中所述,该设备需要具有电量计硬件才能进行精确读取,否则它将在输出中给出任意值。到目前为止,很少有设备拥有这种硬件。【参考方案3】:使用此函数获取所有设备中的电压温度电流。
在 OnCreate 中注册广播接收器
this.registerReceiver(this.BatteryInfo, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
并创建广播接收器
private BroadcastReceiver BatteryInfo = new BroadcastReceiver()
@Override
public void onReceive(Context ctxt, Intent intent)
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
boolean isPresent = intent.getBooleanExtra("present", false);
Bundle bundle = intent.getExtras();
String str = bundle.toString();
Log.i("Battery Info", str);
if (isPresent)
int percent = (level * 100) / scale;
technology.setText("Technology: "+bundle.getString("technology"));
voltage.setText("Voltage: "+bundle.getInt("voltage")+"mV");
temp.setText("Temperature: "+bundle.getInt("temperature"));
curent.setText("Current: "+bundle.getInt("current_avg"));
health.setText("Health: "+getHealthString(health_));
charging.setText("Charging: "+getStatusString(status) + "(" +getPlugTypeString(pluggedType)+")");
battery_percentage.setText("" + percent + "%");
else
battery_percentage.setText("Battery not present!!!");
;
private String getPlugTypeString(int plugged)
String plugType = "Unknown";
switch (plugged)
case BatteryManager.BATTERY_PLUGGED_AC:
plugType = "AC";
break;
case BatteryManager.BATTERY_PLUGGED_USB:
plugType = "USB";
break;
return plugType;
private String getHealthString(int health)
String healthString = "Unknown";
switch (health)
case BatteryManager.BATTERY_HEALTH_DEAD:
healthString = "Dead";
break;
case BatteryManager.BATTERY_HEALTH_GOOD:
healthString = "Good Condition";
break;
case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
healthString = "Over Voltage";
break;
case BatteryManager.BATTERY_HEALTH_OVERHEAT:
healthString = "Over Heat";
break;
case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
healthString = "Failure";
break;
return healthString;
private String getStatusString(int status)
String statusString = "Unknown";
switch (status)
case BatteryManager.BATTERY_STATUS_CHARGING:
statusString = "Charging";
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
statusString = "Discharging";
break;
case BatteryManager.BATTERY_STATUS_FULL:
statusString = "Full";
break;
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
statusString = "Not Charging";
break;
return statusString;
【讨论】:
有没有办法知道“电流”值是否足够好、速度慢,甚至太低而无法充电(因此设备实际上会断电)?如果是这样,怎么做?另外,这种方法适用于所有设备吗?什么是“getHealthString”、“getStatusString”、“getPlugTypeString”方法? 什么是“getHealthString”、“getStatusString”、“getPlugTypeString”方法?我已经编辑了我的答案添加方法 谢谢。你也可以回答其他问题吗?我还注意到,对于我的设备,“当前”值始终为 0。为什么会这样? 检查日志输出以查看电池信息,或在 toast 中打印 str 以检查是否存在 current_avg 以及值是什么 由于您已经将“str”写入日志,我可以看到“current_avg”不存在...... :(【参考方案4】:我在 Intel android 开发者网站上找到了这段代码
public class BatteryActivity extends Activity
private final String TAG = "SDP_BATTERY";
private final String DEGREE_UNICODE = "\u00B0";
private StringBuffer textBuffer = new StringBuffer();
// a text view to show the status of the battery
private TextView mStatusTextView;
// a text view to display the battery status icon
private TextView mBatteryStatusIcon;
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.battery);
mBatteryStatusIcon = (TextView) this.findViewById(R.id.statusBattIcon);
mStatusTextView = (TextView) this.findViewById(R.id.statusEditText);
/**
* Once onResume is called, the activity has become visible (it is now "resumed"). Comes after onCreate
*/
protected void onResume()
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
Log.d(TAG, "Register battery status receiver.");
registerReceiver(mBroadcastReceiver, filter);
/**
* Another activity takes focus, so this activity goes to "paused" state
*/
protected void onPause()
super.onPause();
Log.d(TAG, "Unegister battery status receiver.");
unregisterReceiver(mBroadcastReceiver);
/**
* BroadcastReceiver is used for receiving intents (broadcasted messages) from the BatteryManager
*/
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
private boolean isHealth = false;
public void onReceive(Context context, Intent intent)
DecimalFormat formatter = new DecimalFormat();
String action = intent.getAction();
// store battery information received from BatteryManager
if (action.equals(Intent.ACTION_BATTERY_CHANGED))
Log.d(TAG, "Received battery status information.");
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 0);
int health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, 0);
boolean present = intent.getBooleanExtra(
BatteryManager.EXTRA_PRESENT, false);
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
int icon_small = intent.getIntExtra(
BatteryManager.EXTRA_ICON_SMALL, 0);
int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED,
0);
int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE,
0);
int temperature = intent.getIntExtra(
BatteryManager.EXTRA_TEMPERATURE, 0);
String technology = intent
.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
// display the battery icon that fits the current battery status (charging/discharging)
mBatteryStatusIcon.setCompoundDrawablesWithIntrinsicBounds(icon_small, 0, 0, 0);
// create TextView of the remaining information , to display to screen.
String statusString = "";
switch (status)
case BatteryManager.BATTERY_STATUS_UNKNOWN:
statusString = "unknown";
break;
case BatteryManager.BATTERY_STATUS_CHARGING:
statusString = "charging";
break;
case BatteryManager.BATTERY_STATUS_DISCHARGING:
statusString = "discharging";
break;
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
statusString = "not charging";
break;
case BatteryManager.BATTERY_STATUS_FULL:
statusString = "full";
break;
String healthString = "";
switch (health)
case BatteryManager.BATTERY_HEALTH_UNKNOWN:
healthString = "unknown";
break;
case BatteryManager.BATTERY_HEALTH_GOOD:
healthString = "good";
isHealth = true;
break;
case BatteryManager.BATTERY_HEALTH_OVERHEAT:
healthString = "overheat";
break;
case BatteryManager.BATTERY_HEALTH_DEAD:
healthString = "dead";
break;
case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
healthString = "over voltage";
break;
case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
healthString = "unspecified failure";
break;
String acString = "";
switch (plugged)
case BatteryManager.BATTERY_PLUGGED_AC:
acString = "plugged AC";
break;
case BatteryManager.BATTERY_PLUGGED_USB:
acString = "plugged USB";
break;
default:
acString = "not plugged";
textBuffer = new StringBuffer();
textBuffer.append("status:" + statusString + "\n");
formatter.applyPattern("#");
String levelStr = formatter.format( (float)level/scale * 100 );
textBuffer.append("level:" + levelStr + "% (out of 100)\n");
textBuffer.append("health:" + healthString + "\n");
textBuffer.append("present?:" + String.valueOf(present) + "\n");
textBuffer.append("plugged?:" + acString + "\n");
// voltage is reported in millivolts
formatter.applyPattern(".##");
String voltageStr = formatter.format( (float)voltage/1000 );
textBuffer.append("voltage:" + voltageStr + "V\n");
// temperature is reported in tenths of a degree Centigrade (from BatteryService.java)
formatter.applyPattern(".#");
String temperatureStr = formatter.format( (float)temperature/10 );
textBuffer.append("temperature:" + temperatureStr
+ "C" + DEGREE_UNICODE + "\n");
textBuffer.append("technology:" + String.valueOf(technology)
+ "\n");
mStatusTextView.setText(textBuffer.toString());
if (isHealth)
Log.d(TAG, "Battery health: " + healthString);
Log.d(TAG, "UMSE_BATTERY_SUCCESSFULLY");
else
Log.d(TAG, "UMSE_BATTERY_FAILED");
Log.d(TAG, textBuffer.toString());
//finish();
;
【讨论】:
【参考方案5】:经过多次实验和其他各个小组的帮助,我发现仅通过软件无法获取电池电流值(因为它不支持硬件)。我发现的唯一方法是通过万用表测量流过电池的电流。
【讨论】:
这不起作用吗? developer.android.com/training/monitoring-device-state/… 请参阅@Kevin(和 voss)的答案。 ;) 不是有current_now吗?【参考方案6】:试试这个代码,可能对你有帮助:
private BroadcastReceiver mBatInfoReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context arg0, Intent intent)
// TODO Auto-generated method stub
//this will give you battery current status
int level = intent.getIntExtra("level", 0);
contentTxt.setText(String.valueOf(level) + "%");
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
textView2.setText("status:"+status);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
textView3.setText("is Charging:"+isCharging);
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
textView4.setText("is Charge plug:"+chargePlug);
boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
textView5.setText("USB Charging:"+usbCharge+" AC charging:"+acCharge);
;
在主类中使用:
this.registerReceiver(this.mBatInfoReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
【讨论】:
【参考方案7】:大多数电池使用流出电池的电流来确定百分比,尽管开发人员很少使用它!
需要在这些设备上修改内核。
Galaxy S2 就是这样,它有芯片测量这种电流!但它在股票内核中被“停用”。这意味着它已从 sysfs 接口中移除,仅由电池在内部使用。
尽管如此,您可以尝试使用 Market 的 Battery Monitor Widget 应用程序,它支持许多手机,并且会在不可用时估算 mA 电流。定期添加对新手机和新方法的支持以改善读数。
在 Galaxy Nexus 上,当前芯片已完全移除,因为电池现在使用高级计算来确定 %,这不需要当前数据。结果是该手机没有学习曲线(
【讨论】:
【参考方案8】:对于电池电流百分比充电,您可以使用以下
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = this.registerReceiver(null, ifilter);
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;
TextView tView = (TextView) findViewById(R.id.textView2);
tView.setText("Battery Status " + batteryPct);
【讨论】:
以上是关于获取 Android 手机的电池电流值的主要内容,如果未能解决你的问题,请参考以下文章