Get battery level of connected smartwatches - android

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

Related

Is EXTRA_PLUGGED always BATTERY_PLUGGED_WIRELESS on watches with wireless cradle?

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.

Determine specific charger input

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;

How and when does the Android system send the ACTION_BATTERY_CHANGED sticky broadcast?

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

How to get battery level change in android (only when there is level/percent change)?

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);

android accurate battery level changes?

I have written an application, and I want to know how much of the battery it consumes.
I'm testing it on smartphone (ACER Liquid Mt), but I can only read the battery level with an accuracy of 1% via the battery manager.
It will take a lot of runs to make the percentage decrease with 1%. So my question is this: Is it possible to get a more accurate battery level and is the battery level trustable?
I read some things that the battery level in software wouldn't be very accurate.
It will take a lot of runs to make the percentage decrease with 1% doesn't mean it is inaccurate, It could be that the battery is very durable. And because it is in percentage, 1 percent of battery power could be a lot of energy.
For getting battery level, I use a BroadcastReceiver, you may try it and see if it is accurate enough:
class BatteryLifeBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
int level = intent.getIntExtra("level", 0);
int scale = intent.getIntExtra("scale", 100);
int batteryLevel = (float) level / scale;
// use batteryLevel...
}
}
}
// register the receiver in Activity.onResume()
registerReceiver(mBatteryLifeBroadcastReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
// unregister it in Activity.onPause()
unregisterReceiver(mBatteryLifeBroadcastReceiver);

Categories

Resources