Can someone answer this question for me?
On watches that use wireless charging, does the extra BatteryManager.EXTRA_PLUGGED only every yield BatteryManager.BATTERY_PLUGGED_WIRELESS? (as opposed to BATTERY_PLUGGED_AC and BATTERY_PLUGGED_USB).
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = registerReceiver(null, ifilter);
// How are we charging?
int extraPlugged = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
I don't think so, you may be getting that because (BatteryManager.EXTRA_PLUGGED, -1); is set to -1. There are other number codes with corresponding equivalents like 0 is for "Battery".
More info from this BatterManager docs
EXTRA_PLUGGED
added in API level 5 String EXTRA_PLUGGED Extra for
ACTION_BATTERY_CHANGED: integer indicating whether the device is
plugged in to a power source; 0 means it is on battery, other
constants are different types of power sources.
For all practical purposes, yes, but watches that are plugged in via a debug board (i.e not the ones in the general public) can return BATTERY_PLUGGED_USB.
Related
Is it possible to get the battery level of connected smartwatches as part of the Wear API? (Preferably without having to deploy an actual wear-component onto the smartwatch and then communicating back-and-forth between the watch and the device). I've seen some wear-apps that show the battery level of the watch on the watch itself, but I'd simply like to find out the current battery level of the watch using the phone.
You're more than likely going to need a wear app, but it should be very easy.
On the wearable, make a WearableListenerService. Have the phone app send a message (using the Message APi). This will start the WearableListenerService on the watch. Have the watch get it's battery information and send it back to the phone using another message.
Start by determining the current charge status. The BatteryManager broadcasts all battery and charging details in a sticky Intent that includes the charging status.
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, ifilter);
You can extract the current charging status this way
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
you can use this one
public static final String EXTRA_LEVEL
Added in API level 5
Extra for ACTION_BATTERY_CHANGED: integer field containing the current battery level, from 0 to EXTRA_SCALE.
Constant Value: "level"
You can find the current battery charge by extracting the current
battery level and scale from the battery status intent as shown here:
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale; // your %
so batteryPct is your Battery % Percentage
//you can show your Percentage then
For more info about BatteryManager from here
I am currently trying to make a reliable way to determine a specific charger type, in my case a music dock like this. The problem is that this dock unfortunately does not send a dock event when docked.
Since I am making an app relying on being able to determine when the device has been docked or undocked. I therefore need a way to filter out and separate these events:
Device is charging through the USB connector(no separate charger)
Device is not connected to a computer
Some sort of way to separate the slow charging dock from a standard charger
I have noticed that my device (LG optimus 4x HD) manages to react differently for every one of these actions. When it is connected to a standard charger it gives no notification message, when it is connected to a computer it tells me USB mode has been activated, and when it is connected to the dock it gives me a slow charger warning.
I need to make a system with the same ability to separate these actions and react to them. Until now I have only made a simple BroadcastReceiver that reacts if the device is connected or unconnected to a charger. I have also managed to monitor the charging state using the code found in the documentation.
Is there any way of determine this specific charger input?
Whenever the device is docked or undocked, the ACTION_DOCK_EVENT action is broadcast. To monitor changes in the device's dock-state, simply register a broadcast receiver in your application manifest as shown in the snippet below:
<action android:name="android.intent.action.ACTION_DOCK_EVENT"/>
If a device is docked, it can be docked in any one of four different type of dock:
Car
Desk
Low-End (Analog) Desk
High-End (Digital) Desk
The dock-state details are included as an extra in a sticky broadcast of the ACTION_DOCK_EVENT action. Because it's sticky, you don't need to register a BroadcastReceiver. You can simply call registerReceiver() passing in null as the broadcast receiver as shown in the next snippet.
IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
Intent dockStatus = context.registerReceiver(null, ifilter);
You can extract the current docking status from the EXTRA_DOCK_STATE extra:
int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
You can find the dock state by
boolean isCar = dockState == EXTRA_DOCK_STATE_CAR;
boolean isDesk = dockState == EXTRA_DOCK_STATE_DESK ||
dockState == EXTRA_DOCK_STATE_LE_DESK ||
dockState == EXTRA_DOCK_STATE_HE_DESK;
EDIT :
If your app still not receiving the broadcast try this code to sent manual broadcast and check the code :
adb shell am broadcast -a android.intent.action.POWER_CONNECTED -n com.jm.monitoringbatterydemo/.PowerConnectionReceiver
Change the name of the broadcast and your receiver.
What you can do to solve this problem is look at the % of battery left on your phone. You can then determine that the value is going up, which means it is docked. Only problem with this could be that if you sometimes charge it on a regular charger rather than a dock, you'd still have it respond as if it were one.
More info on reading battery level etc: http://developer.android.com/training/monitoring-device-state/battery-monitoring.html
Would it be helpful to identify the power source using
int BATTERY_PLUGGED_AC Power source is an AC charger.
int BATTERY_PLUGGED_USB Power source is a USB port.
int BATTERY_PLUGGED_WIRELESS Power source is wireless.
from BatteryManager?
Hope this code helps:
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = mContext.registerReceiver(null, ifilter);
// Are we charging / charged?
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
// How are we charging?
int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharge = chargePlug == 2;
boolean acCharge = chargePlug == 1;
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;
My goal is : when I call some function, I want to get the exact current battery status(level,voltage and etc..).
First I tried to do it in my application as shown on the website. Then I have found actually the ACTION_BATTERY_CHANGED broadcast is sticky which means what I got is from last broadcast, not the exact current value.
Actually, I have looked into the android source code. For the battery interface, the driver has functions to read the registers inside the battery which contain the current soc(state of charge), voltage and etc..
So I am just wondering how and when the system sends the sticky broadcast ACTION_BATTERY_CHANGED? Does it send it periodically(e.g.,every 10 seconds it will read the registers in battery and send the broadcast)? Or does it send based on other criteria(e.g, change of soc, voltage? But voltage will change so frequently in terms of mV)?
To realize my goal, one troublesome way is to implement a system call to call the driver functions and then recompile the NDK to make it usable in my application code. But I just want to know whether I can do this directly through the ACTION_BATTERY_CHANGED broadcast considering what I have mentioned above? Does registering the broadcast again have any effect?
Simply register the Broadcast receiver for the battery level. You will get the result of battery level in onReceive.
private void batteryLevel() {
BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this);
int rawlevel = intent.getIntExtra("level", -1);
int scale = intent.getIntExtra("scale", -1);
int level = -1;
if (rawlevel >= 0 && scale > 0) {
level = (rawlevel * 100) / scale;
}
batterLevel.setText("Battery Level Remaining: " + level + "%");
}
};
IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(batteryLevelReceiver, batteryLevelFilter);
}
Hope this will help you.
To elaborate on the answer from Arpit, ACTION_BATTERY_CHANGED is a "sticky" event - which means it doesn't need a receiver to be able to read its values. That way you may call registerReceiver() with receiver equal to null, and read all the battery stats synchronously right away, and there's no need to unregister.
Here's the code:
private void batteryLevel() {
IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent intent = registerReceiver(null, batteryLevelFilter);
if (intent != null) {
int rawlevel = intent.getIntExtra("level", -1);
int scale = intent.getIntExtra("scale", -1);
int level = -1;
if (rawlevel >= 0 && scale > 0) {
level = (rawlevel * 100) / scale;
}
batteryLevel.setText("Battery Level Remaining: " + level + "%");
}
}
Also, in some rare cases, registerReceiver() may throw an IllegalArgumentException: regist too many Broadcast Receivers exception, so you may want to catch it to avoid crashing.
In response to the of the question:
Does it send it periodically(e.g.,every 10 seconds it will read the
registers in battery and send the broadcast)? Or does it send based on
other criteria(e.g, change of soc, voltage? But voltage will change so
frequently in terms of mV)?
There is no single correct answer, Android makes no guarantees and it varies by device.
Based on my experience working with different board bring-ups it is highly dependant on the linux kernel drivers managing power. I've seen it firing uevents off once per second or once every 30 seconds. Even the same device will fire it differently based on whether it is attached to a power source or not. I tend to see that usually there is some fixed timer that triggers it and additionally major events such as attaching/detaching a charger will trigger it as well.
Also see: ACTION_BATTERY_CHANGED firing like crazy
In my application, I want to do something when the battery is low. When battery is low android fires ACTION_BATTERY_LOW and when the battery again reaches to its good health it fires intent ACTION_BATTERY_OKAY. So, I have three questions regarding this:
1.At what battery percentage android actually fires ACTION_BATTERY_LOW?
2.Does it fire that same event repeatedly if the battery gets even lower?
3.Can we configure the battery percentage at which android will fire ACTION_BATTERY_LOW intent?
I am more concerned about the third point.
No, you cannot set when the ACTION_BATTERY_LOW threshold will be sent. That is a system level intent that is specified by the Android ROM. Here is the code where it sets the value in the Battery Service:
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
See the code below which is cut from the Android system code in the update method of the Battery Service:
/* 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);
sendIntent();
// Separate broadcast is sent for power connected / not connected
// since the standard intent will not wake any applications and some
// applications may want to have smart behavior based on this.
Intent statusIntent = new Intent();
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (mPlugType != 0 && mLastPlugType == 0) {
statusIntent.setAction(Intent.ACTION_POWER_CONNECTED);
mContext.sendBroadcast(statusIntent);
}
else if (mPlugType == 0 && mLastPlugType != 0) {
statusIntent.setAction(Intent.ACTION_POWER_DISCONNECTED);
mContext.sendBroadcast(statusIntent);
}
if (sendBatteryLow) {
mSentLowBatteryBroadcast = true;
statusIntent.setAction(Intent.ACTION_BATTERY_LOW);
mContext.sendBroadcast(statusIntent);
That intent is fired from the BatteryService. You'll have to analyze the code a bit, but I'm pretty sure it does not fire repeatedly:
http://gitorious.org/android-eeepc/base/blobs/fda6fae156e31a287e3cfbf66e51ea1405cdf479/services/java/com/android/server/BatteryService.java
The actual values that it fires at are setup in the android resources, so it's configurable only during a system build. This is what we have for our hardware, but this will likely be different for each hardware platform that Android runs on:
<!-- Display low battery warning when battery level dips to this value -->
<integer name="config_lowBatteryWarningLevel">15</integer>
<!-- Close low battery warning when battery level reaches this value -->
<integer name="config_lowBatteryCloseWarningLevel">20</integer>
Unless you're developing a custom hardware platform, I wouldn't make any assumptions about what these values are set to.
There is another way that detect "config_lowBatteryWarningLevel" from "com.android.internal.R.integer" field.
enter code here
try {
Class clazz = Class.forName("com.android.internal.R$integer");
Field field = clazz.getDeclaredField("config_lowBatteryWarningLevel");
field.setAccessible(true);
int LowBatteryLevel = _context.getResources().getInteger(field.getInt(null));
Log.d("LowBattery","warninglevel " + LowBatteryLevel);
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
Is there a way to get battery level only when the level changes?
I know how to get the battery info using Intent.ACTION_BATTERY_CHANGED and then I compare the battery level of it with the last battery level (that I saved before) in case it equals I don't do anything else I do my stuff.
I also know that ACTION_BATTERY_CHANGED happens when there is battery info change (not only the level) so cause of that I need to check the level. I don't know why but sometimes it doesn't work well.
Is there a better way to do it?
There is no other (documented) way to get the battery level. Just ignore the broadcast when the level did not change. As you already do.
You can get the latest status immediately with the following:
IntentFilter batIntentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent battery = this.registerReceiver(null, batIntentFilter);
int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
Log.d("TAG", "Current Level: " + level);