summaryrefslogtreecommitdiffstats
path: root/docs/html/training/monitoring-device-state
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/training/monitoring-device-state')
-rw-r--r--docs/html/training/monitoring-device-state/battery-monitoring.jd156
-rw-r--r--docs/html/training/monitoring-device-state/connectivity-monitoring.jd90
-rw-r--r--docs/html/training/monitoring-device-state/docking-monitoring.jd90
-rw-r--r--docs/html/training/monitoring-device-state/index.jd63
-rw-r--r--docs/html/training/monitoring-device-state/manifest-receivers.jd64
5 files changed, 463 insertions, 0 deletions
diff --git a/docs/html/training/monitoring-device-state/battery-monitoring.jd b/docs/html/training/monitoring-device-state/battery-monitoring.jd
new file mode 100644
index 0000000..a442140
--- /dev/null
+++ b/docs/html/training/monitoring-device-state/battery-monitoring.jd
@@ -0,0 +1,156 @@
+page.title=Monitoring the Battery Level and Charging State
+parent.title=Monitoring Device State to Optimize Battery Life
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Determining and Monitoring the Docking State and Type
+next.link=docking-monitoring.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#DetermineChargeState">Determine the Current Charging State</a></li>
+ <li><a href="#MonitorChargeState">Monitor Changes in Charging State</a></li>
+ <li><a href="#CurrentLevel">Determine the Current Battery Level</a></li>
+ <li><a href="#MonitorLevel">Monitor Significant Changes in Battery Level</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+</ul>
+
+</div>
+</div>
+
+<p>When you're altering the frequency of your background updates to reduce the effect of those
+updates on battery life, checking the current battery level and charging state is a good place to
+start.</p>
+
+<p>The battery-life impact of performing application updates depends on the battery level and
+charging state of the device. The impact of performing updates while the device is charging over AC
+is negligible, so in most cases you can maximize your refresh rate whenever the device is connected
+to a wall charger. Conversely, if the device is discharging, reducing your update rate helps
+prolong the battery life.</p>
+
+<p>Similarly, you can check the battery charge level, potentially reducing the frequency of&mdash;or
+even stopping&mdash;your updates when the battery charge is nearly exhausted.</p>
+
+
+<h2 id="DetermineChargeState">Determine the Current Charging State</h2>
+
+<p>Start by determining the current charge status. The {@link android.os.BatteryManager}
+broadcasts all battery and charging details in a sticky {@link android.content.Intent} that includes
+the charging status.</p>
+
+<p>Because it's a sticky intent, you don't need to register a {@link
+android.content.BroadcastReceiver}&mdash;by simply calling {@code registerReceiver} passing in
+{@code null} as the receiver as shown in the next snippet, the current battery status intent is
+returned. You could pass in an actual {@link android.content.BroadcastReceiver} object here, but
+we'll be handling updates in a later section so it's not necessary.</p>
+
+<pre>IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+Intent batteryStatus = context.registerReceiver(null, ifilter);</pre>
+
+<p>You can extract both the current charging status and, if the device is being charged, whether
+it's charging via USB or AC charger:<p>
+
+<pre>// 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 = battery.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
+boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;</pre>
+
+<p>Typically you should maximize the rate of your background updates in the case where the device is
+connected to an AC charger, reduce the rate if the charge is over USB, and lower it
+further if the battery is discharging.</p>
+
+
+<h2 id="MonitorChargeState">Monitor Changes in Charging State</h2>
+
+<p>The charging status can change as easily as a device can be plugged in, so it's important to
+monitor the charging state for changes and alter your refresh rate accordingly.</p>
+
+<p>The {@link android.os.BatteryManager} broadcasts an action whenever the device is connected or
+disconnected from power. It's important to to receive these events even while your app isn't
+running&mdash;particularly as these events should impact how often you start your app in order to
+initiate a background update&mdash;so you should register a {@link
+android.content.BroadcastReceiver} in your manifest to listen for both events by defining the
+{@link android.content.Intent#ACTION_POWER_CONNECTED} and {@link
+android.content.Intent#ACTION_POWER_DISCONNECTED} within an intent filter.</p>
+
+<pre>&lt;receiver android:name=".PowerConnectionReceiver">
+ &lt;intent-filter>
+ &lt;action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
+ &lt;action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
+ &lt;/intent-filter>
+&lt;/receiver></pre>
+
+<p>Within the associated {@link android.content.BroadcastReceiver} implementation, you can extract
+the current charging state and method as described in the previous step.</p>
+
+<pre>public class PowerConnectionReceiver extends BroadcastReceiver {
+ &#64;Override
+ public void onReceive(Context context, Intent intent) {
+ int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+ boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
+ status == BatteryManager.BATTERY_STATUS_FULL;
+
+ int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
+ boolean usbCharge = chargePlug == BATTERY_PLUGGED_USB;
+ boolean acCharge = chargePlug == BATTERY_PLUGGED_AC;
+ }
+}</pre>
+
+
+<h2 id="CurrentLevel">Determine the Current Battery Level</h2>
+
+<p>In some cases it's also useful to determine the current battery level. You may choose to reduce
+the rate of your background updates if the battery charge is below a certain level.</p>
+
+<p>You can find the current battery charge by extracting the current battery level and scale from
+the battery status intent as shown here:</p>
+
+<pre>int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+
+float batteryPct = level / (float)scale;</pre>
+
+
+<h2 id="MonitorLevel">Monitor Significant Changes in Battery Level</h2>
+
+<p>You can't easily continually monitor the battery state, but you don't need to.</p>
+
+<p>Generally speaking, the impact of constantly monitoring the battery level has a greater
+impact on the battery than your app's normal behavior, so it's good practice to only monitor
+significant changes in battery level&mdash;specifically when the device enters or exits a low
+battery state.</p>
+
+<p>The manifest snippet below is extracted from the intent filter element within a broadcast
+receiver. The receiver is triggered whenever the device battery becomes low or exits the low
+condition by listening for {@link android.content.Intent#ACTION_BATTERY_LOW} and {@link
+android.content.Intent#ACTION_BATTERY_OKAY}.</p>
+
+<pre>&lt;receiver android:name=".BatteryLevelReceiver">
+&lt;intent-filter>
+ &lt;action android:name="android.intent.action.ACTION_BATTERY_LOW"/>
+ &lt;action android:name="android.intent.action.ACTION_BATTERY_OKAY"/>
+ &lt;/intent-filter>
+&lt;/receiver></pre>
+
+<p>It is generally good practice to disable all your background updates when the battery is
+critically low. It doesn't matter how fresh your data is if the phone turns itself off before you
+can make use of it.</p>
+
+<p>In many cases, the act of charging a device is coincident with putting it into a dock. The next
+lesson shows you how to determine the current dock state and monitor for changes in device
+docking.</p>
+
diff --git a/docs/html/training/monitoring-device-state/connectivity-monitoring.jd b/docs/html/training/monitoring-device-state/connectivity-monitoring.jd
new file mode 100644
index 0000000..4c71279
--- /dev/null
+++ b/docs/html/training/monitoring-device-state/connectivity-monitoring.jd
@@ -0,0 +1,90 @@
+page.title=Determining and Monitoring the Connectivity Status
+parent.title=Monitoring Device State to Optimize Battery Life
+parent.link=index.html
+
+trainingnavtop=true
+
+previous.title=Determining and Monitoring the Docking State and Type
+previous.link=docking-monitoring.html
+next.title=Manipulating Broadcast Receivers On Demand
+next.link=manifest-receivers.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#DetermineConnection">Determine if you Have an Internet Connection</a></li>
+ <li><a href="#DetermineType">Determine the Type of your Internet Connection</a></li>
+ <li><a href="#MonitorChanges">Monitor for Changes in Connectivity</a></li>
+</ol>
+
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+</ul>
+
+</div>
+</div>
+
+<p>Some of the most common uses for repeating alarms and background services is to schedule regular
+updates of application data from Internet resources, cache data, or execute long running downloads.
+But if you aren't connected to the Internet, or the connection is too slow to complete your
+download, why both waking the device to schedule the update at all?</p>
+
+<p>You can use the {@link android.net.ConnectivityManager} to check that you're actually
+connected to the Internet, and if so, what type of connection is in place.</p>
+
+
+<h2 id="DetermineConnection">Determine if You Have an Internet Connection</h2>
+
+<p>There's no need to schedule an update based on an Internet resource if you aren't connected to
+the Internet. The following snippet shows how to use the {@link android.net.ConnectivityManager}
+to query the active network and determine if it has Internet connectivity.</p>
+
+<pre>ConnectivityManager cm =
+ (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
+NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+boolean isConnected = activeNetwork.isConnectedOrConnecting();</pre>
+
+
+<h2 id="DetermineType">Determine the Type of your Internet Connection</h2>
+
+<p>It's also possible to determine the type of Internet connection currently available.</p>
+
+<p>Device connectivity can be provided by mobile data, WiMAX, Wi-Fi, and ethernet connections. By
+querying the type of the active network, as shown below, you can alter your refresh rate based on
+the bandwidth available.</p>
+
+<pre>boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;</pre>
+
+<p>Mobile data costs tend to be significantly higher than Wi-Fi, so in most cases, your app's update
+rate should be lower when on mobile connections. Similarly, downloads of significant size should be
+suspended until you have a Wi-Fi connection.</p>
+
+<p>Having disabled your updates, it's important that you listen for changes in connectivity in order
+to resume them once an Internet connection has been established.</p>
+
+
+<h2 id="MonitorChanges">Monitor for Changes in Connectivity</h2>
+
+<p>The {@link android.net.ConnectivityManager} broadcasts the {@link
+android.net.ConnectivityManager#CONNECTIVITY_ACTION} ({@code
+"android.net.conn.CONNECTIVITY_CHANGE"}) action whenever the connectivity details have changed. You
+can register a broadcast receiver in your manifest to listen for these changes and resume (or
+suspend) your background updates accordingly.</p>
+
+<pre>&lt;action android:name="android.net.conn.CONNECTIVITY_CHANGE"/></pre>
+
+<p>Changes to a device's connectivity can be very frequent&mdash;this broadcast is triggered
+every time you move between mobile data and Wi-Fi. As a result, it's good practice to monitor
+this broadcast only when you've previously suspended updates or downloads in order to resume them.
+It's generally sufficient to simply check for Internet connectivity before beginning an update and,
+should there be none, suspend further updates until connectivity is restored.</p>
+
+<p>This technique requires toggling broadcast receivers you've declard in the manifest, which is
+described in the next lesson.</p>
diff --git a/docs/html/training/monitoring-device-state/docking-monitoring.jd b/docs/html/training/monitoring-device-state/docking-monitoring.jd
new file mode 100644
index 0000000..6a4a9a8
--- /dev/null
+++ b/docs/html/training/monitoring-device-state/docking-monitoring.jd
@@ -0,0 +1,90 @@
+page.title=Determining and Monitoring the Docking State and Type
+parent.title=Monitoring Device State to Optimize Battery Life
+parent.link=index.html
+
+trainingnavtop=true
+previous.title= Monitoring the Battery Level and Charging State
+previous.link=battery-monitoring.html
+next.title= Determining and Monitoring the Connectivity Status
+next.link=connectivity-monitoring.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#CurrentDockState">Request the Audio Focus</a></li>
+ <li><a href="#DockType">Determine the Current Dock Type</a></li>
+ <li><a href="#MonitorDockState">Monitor for Changes in the Dock State or Type</a></li>
+</ol>
+
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+</ul>
+
+</div>
+</div>
+
+<p>Android devices can be docked into several different kinds of docks. These include car or home
+docks and digital versus analog docks. The dock-state is typically closely linked to the charging
+state as many docks provide power to docked devices.</p>
+
+<p>How the dock-state of the phone affects your update rate depends on your app. You may choose
+to increase the update frequency of a sports center app when it's in the desktop dock, or disable
+your updates completely if the device is car docked. Conversely, you may choose to maximize your
+updates while car docked if your background service is updating traffic conditions.</p>
+
+<p>The dock state is also broadcast as a sticky {@link android.content.Intent}, allowing you to
+query if the device is docked or not, and if so, in which kind of dock.</p>
+
+
+<h2 id="CurrentDockState">Determine the Current Docking State</h2>
+
+<p>The dock-state details are included as an extra in a sticky broadcast of the {@link
+android.content.Intent#ACTION_DOCK_EVENT} action. Because it's sticky, you don't need to register a
+{@link android.content.BroadcastReceiver}. You can simply call {@link
+android.content.Context#registerReceiver registerReceiver()} passing in {@code null} as the
+broadcast receiver as shown in the next snippet.</p>
+
+<pre>IntentFilter ifilter = new IntentFilter(Intent.ACTION_DOCK_EVENT);
+Intent dockStatus = context.registerReceiver(null, ifilter);</pre>
+
+<p>You can extract the current docking status from the {@code EXTRA_DOCK_STATE} extra:<p>
+
+<pre>int dockState = battery.getIntExtra(EXTRA_DOCK_STATE, -1);
+boolean isDocked = dockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;</pre>
+
+
+<h2 id="DockType">Determine the Current Dock Type</h2>
+
+<p>If a device is docked, it can be docked in any one of four different type of dock:
+<ul><li>Car</li>
+<li>Desk</li>
+<li>Low-End (Analog) Desk</li>
+<li>High-End (Digital) Desk</li></ul></p>
+
+<p>Note that the latter two options were only introduced to Android in API level 11, so it's good
+practice to check for all three where you are only interested in the type of dock rather than it
+being digital or analog specifically:</p>
+
+<pre>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;</pre>
+
+
+<h2 id="MonitorDockState">Monitor for Changes in the Dock State or Type</h2>
+
+<p>Whenever the the device is docked or undocked, the {@link
+android.content.Intent#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:</p>
+
+<pre>&lt;action android:name="android.intent.action.ACTION_DOCK_EVENT"/></pre>
+
+<p>You can extract the dock type and state within the receiver implementation using the same
+techniques described in the previous step.</p>
diff --git a/docs/html/training/monitoring-device-state/index.jd b/docs/html/training/monitoring-device-state/index.jd
new file mode 100644
index 0000000..e92e1e8
--- /dev/null
+++ b/docs/html/training/monitoring-device-state/index.jd
@@ -0,0 +1,63 @@
+page.title=Monitoring Device State to Optimize Battery Life
+
+trainingnavtop=true
+startpage=true
+next.title=Monitoring the Battery Level and Charging State
+next.link=battery-monitoring.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+<ul>
+ <li>Android 2.0 (API level 5) or higher</li>
+ <li>Experience with <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a></li>
+</ul>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>
+</ul>
+
+</div>
+</div>
+
+<p>For your app to be a good citizen, it should seek to limit its impact on the battery life of its
+host device. After this class you will be able to build apps that monitor modify their functionality
+and behavior based on the state of the host device.</p>
+
+<p>By taking steps such as disabling background service updates when you lose connectivity, or
+reducing the rate of such updates when the battery level is low, you can ensure that the impact of
+your app on battery life is minimized, without compromising the user experience.</p>
+
+<h2>Lessons</h2>
+
+<!-- Create a list of the lessons in this class along with a short description of each lesson.
+These should be short and to the point. It should be clear from reading the summary whether someone
+will want to jump to a lesson or not.-->
+
+<dl>
+ <dt><b><a href="battery-monitoring.html">Monitoring the Battery Level and Charging State</a></b></dt>
+ <dd>Learn how to alter your app's update rate by determining, and monitoring, the current battery
+level and changes in charging state.</dd>
+
+ <dt><b><a href="docking-monitoring.html">Determining and Monitoring the Docking State and
+Type</a></b></dt>
+ <dd>Optimal refresh rates can vary based on how the host device is being used. Learn how to
+determine, and monitor, the docking state and type of dock being used to affect your app's
+behavior.</dd>
+
+ <dt><b><a href="connectivity-monitoring.html">Determining and Monitoring the Connectivity
+Status</a></b></dt>
+ <dd>Without Internet connectivity you can't update your app from an online source. Learn how to
+check the connectivity status to alter your background update rate. You'll also learn to check for
+Wi-Fi or mobile connectivity before beginning high-bandwidth operations.</dd>
+
+ <dt><b><a href="manifest-receivers.html">Manipulating Broadcast Receivers On Demand</a></b></dt>
+ <dd>Broadcast receivers that you've declared in the manifest can be toggled at runtime to disable
+those that aren't necessary due to the current device state. Learn to improve
+efficiency by toggling and cascading state change receivers and delay actions until the device is in
+a specific state.</dd>
+</dl> \ No newline at end of file
diff --git a/docs/html/training/monitoring-device-state/manifest-receivers.jd b/docs/html/training/monitoring-device-state/manifest-receivers.jd
new file mode 100644
index 0000000..bf5462a
--- /dev/null
+++ b/docs/html/training/monitoring-device-state/manifest-receivers.jd
@@ -0,0 +1,64 @@
+page.title=Manipulating Broadcast Receivers On Demand
+parent.title=Monitoring Device State to Optimize Battery Life
+parent.link=index.html
+
+trainingnavtop=true
+
+previous.title=Determining and Monitoring the Connectivity Status
+previous.link=connectivity-monitoring.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="ToggleReceivers">Toggle and Cascade State Change Receivers to Improve
+Efficiency</a></li>
+</ol>
+
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+</ul>
+
+</div>
+</div>
+
+<p>The simplest way to monitor device state changes is to create a {@link
+android.content.BroadcastReceiver} for each state you're monitoring and register each of them in
+your application manifest. Then within each of these receivers you simply reschedule your recurring
+alarms based on the current device state.</p>
+
+<p>A side-effect of this approach is that your app will wake the device each time any of these
+receivers is triggered&mdash;potentially much more frequently than required.</p>
+
+<p>A better approach is to disable or enable the broadcast receivers at runtime. That way you can
+use the receivers you declared in the manifest as passive alarms that are triggered by system events
+only when necessary.</p>
+
+
+<h2 id="ToggleReceivers">Toggle and Cascade State Change Receivers to Improve Efficiency </h2>
+
+<p>Use can use the {@link android.content.pm.PackageManager} to toggle the enabled state on any
+component defined in the manifest, including whichever broadcast receivers you wish to enable or
+disable as shown in the snippet below:</p>
+
+<pre>ComponentName receiver = new ComponentName(context, myReceiver.class);
+
+PackageManager pm = context.getPackageManager();
+
+pm.setComponentEnabledSetting(receiver,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP)</pre>
+
+<p>Using this technique, if you determine that connectivity has been lost, you can disable all of
+your receivers except the connectivity-change receiver. Conversely, once you are connected you can
+stop listening for connectivity changes and simply check to see if you're online immediately before
+performing an update and rescheduling a recurring update alarm.</p>
+
+<p>You can use the same technique to delay a download that requires higher bandwidth to complete.
+Simply enable a broadcast receiver that listens for connectivity changes and initiates the
+download only after you are connected to Wi-Fi.</p>