Monday, January 11, 2016

Using Android's BATTERY_CHANGED Intent in Tasker

Monitoring the status of my tablet's battery has always been part of the Digital Dash project (http://mikesgeneralblog.blogspot.com/2015/06/digital-dash-documentation-part-4.html).  And later the function was expanded to bring in the phone's battery information as well.  That part of the project has always worked pretty well and I haven't changed the code in a long time.

Now, however, I've discovered a more efficient way to gather this information and have rewritten that part of the system to take advantage of it.  It allows me to replace what had been two profiles and three tasks, with a single profile with one task attached to it.

The key is another Android Broadcast Intent, similar to the TIME_TICK intent I wrote about in my last post. (http://mikesgeneralblog.blogspot.com/2016/01/using-androids-timetick-intent-in-tasker.html)  The main difference is that where the TIME_TICK intent didn't provide any real information (it was just a synchronizing pulse), the BATTERY_CHANGED intent that we'll be using has a payload that contains a lot of info about the device's battery.

Setup to monitor this intent is nearly identical to the TIME_TICK: Create a new Event profile and choose "Intent Received" from the "System" category.  In the "Action" field enter "android.intent.action.BATTERY_CHANGED" (without quotes).  Then link to the task you want to run from this profile.

Here's what mine looks like:

Profile: V3_ BatteryTracker (472)
        Cooldown: 10
        Event: Intent Received [ Action:android.intent.action.BATTERY_CHANGED Cat:None Cat:None Scheme:* Mime Type:* ]
        State: Variable Value [ %V3_DrivingMode Set ]
Enter: V3_BattMon (483)
        A1: Variable Set [ Name:%V3_BatteryDisplay To:%level% Do Maths:Off Append:Off ] If [ %plugged = 0 ]
        A2: Variable Set [ Name:%V3_BatteryDisplay To:<u>%level%</u> Do Maths:Off Append:Off ] If [ %plugged > 0 ]


(Note that, as usual, my profile has a second context, %V3_DrivingMode Set, to keep it from firing unless my Digital Dash system is running.  You don't need that context just to monitor the battery.)

Although this is pretty simple arrangement, there are a couple of points to keep in mind if you're thinking of using this intent.  First of all, notice that I've put a 10-second cooldown on the profile to limit it's maximum firing rate.  That's because this intent will change any time one of several battery conditions changes.  It's not quite like Tasker's built-in "Battery Changed" event that only fires when the battery level changes.  The BATTERY_CHANGED intent (which Tasker is undoubtedly monitoring behind the scenes) puts out new information not only when the battery level changes, but also when the powered status changes, when the battery health changes, and when the the battery temperature changes, along with several other triggers.  

The upshot is that this intent can be updated very frequently and since I don't need or want to have that kind of granularity, I've restricted the profile to firing only once every 10 seconds, at a maximum.

The second things to take note of are the names of the Tasker variables that I'm using: %plugged and %level.  They're obviously local variables, but I didn't make up the names; they are the ones created by Tasker and based on the names provided by the intent itself.  Since there are a lot of other variables associated with this intent (and no real documentation about how they translate to Tasker) it's probably worth a few minutes to lay it out. (You can't just choose these variables from Tasker's drop-down list because they are generated dynamically at runtime.) 

The Android system documentation contains a section on the "Battery Manager" class, which provides the details of this intent.  You can find it here: http://developer.android.com/reference/android/os/BatteryManager.html

There you'll find a list of all the constants used by this class and the information they can contain.  This document is the key to sorting out the Tasker names and knowing what values to look for.

For example, let's take the %plugged variable.  As you can see in the code above, if this variable is not 0, I wrap the battery level in HTML underline tags before displaying it.  This gives me a visual indicator of the power state on the main screen.

If you look at the Battery Manager documentation, you'll see this entry:

public static final String EXTRA_PLUGGED

Added in API level 5
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.
Constant Value: "plugged"
The "Constant Value" gives you the name of the Tasker variable (once you add the leading %).  It also give you a hint about what the variable might contain, but there's more information available.
If you scroll up a bit, you'll find these entries, all with the word "plugged" in their names:

public static final int BATTERY_PLUGGED_AC

Added in API level 1
Power source is an AC charger.
Constant Value: 1 (0x00000001)

public static final int BATTERY_PLUGGED_USB

Added in API level 1
Power source is a USB port.
Constant Value: 2 (0x00000002)

public static final int BATTERY_PLUGGED_WIRELESS

Added in API level 17
Power source is wireless.
Constant Value: 4 (0x00000004)
These are the other values that might be present in the %plugged variable.  Knowing that you can test for any state and act accordingly.
Likewise, you can find the names for other variables, such as the ones for health, voltage, status, and so on.  By linking the names back to the constants, you can determine what type of information can be retrieved.
Some variables, like temperature, require a little more digging, however.  If you set up the profile and flash the %temperature value, you might see something like: 223  Don't worry; it doesn't mean your battery is at the boiling point.  The intent reports the battery temperature in tenths of a degree Celsius.  So, a value of 223 means 23.3 degrees Celsius or about 72.14 degrees Fahrenheit.  So, basically room temperature.
The fact that this intent contains the battery temperature is the main reason I put the cooldown period on the profile.  When my Digital Dash project begins ramping up, the battery temperature changes rapidly and I didn't want to have the profile firing every time the temperature changed a tenth of a degree.
This single intent could be a starting point for a pretty comprehensive Tasker-based battery monitoring system.  Take a look at the documentation and see just how much information you can gather with just one profile.





1 comment:

victoria said...
This comment has been removed by a blog administrator.