Determine specific charger input - android

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;

Related

Android charging or plugged to a power source states

I have an dashcam which automatically starts and stops recording based on charging (start on charging and stop when it stops charging)
So I have something like this at the BroadcastReceiver.onReceive
Intent.ACTION_POWER_CONNECTED -> {
startRecording()
}
Intent.ACTION_POWER_DISCONNECTED -> {
stopRecording()
}
Some users reported that recording stops when their device becomes fully charged though it is still plugged to a power source via USB.
So it seems BatteryManager sends the event that the power is not connected.
What can I do in this case to know for sure that it is still plugged to a source power?
Mb should I use the following solution?
Intent.ACTION_BATTERY_CHANGED -> {
val plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0
// conditionally it looks like this: if (plugged) startRec() else stopRec()
}

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.

Get battery level of connected smartwatches

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

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

ACTION_HEADSET_PLUG not documented extra strange "state"?

I'm doing some test with Intent.ACTION_HEADSET_PLUG.
Giving the fact that the following code should be the one who give the responses (From com.android.server.HeadsetObserver class 2.2.1 r1):
private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
if ((headsetState & headset) != (prevHeadsetState & headset)) {
// Pack up the values and broadcast them to everyone
Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
int state = 0;
int microphone = 0;
if ((headset & HEADSETS_WITH_MIC) != 0) {
microphone = 1;
}
if ((headsetState & headset) != 0) {
state = 1;
}
intent.putExtra("state", state);
intent.putExtra("name", headsetName);
intent.putExtra("microphone", microphone);
if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
// TODO: Should we require a permission?
ActivityManagerNative.broadcastStickyIntent(intent, null);
}
}
And in the documentation they say: state - 0 for unplugged, 1 for plugged.
I strangely get two different state by plugging two different headsets:
0 = unplugged
1 = Headset with microphone
2 = Headset without microphone
The question is: where the State 2 (two) come from? Can someone enlighten me?
Thanks
I am using that extra state myself in one of my applications. One of your headsets has a mic the other doesn't. Also make sure you a plugging it in all the way, but don't break anything :)
0 - unplugged as in no headset attached to the device
1 - headset with microphone as in wired headset that had a mic so you can talk and the device uses it as a input as you talk
2 - a headset with no microphone as in your regular old stereo headset that you would normally hook up to your stereo system to listen to music with
This is extremely good info to verify that what was just connected is a wired headset that you expect to be able to talk in to and be heard correctly.

Categories

Resources