您的位置:首页 > 移动开发 > Android开发

android-Transferring Data Without Draining the Battery

2016-01-08 14:10 597 查看
》The state machine for a typical 3G network radio consists of three energy states:

Full power: Used when a connection is active, allowing the device to transfer data at its highest possible rate.
Low power: An intermediate state that uses around 50% of the battery power at the full state.
Standby: The minimal energy state during which no network connection is active or required.

By comparison, the same app that bundles transfers of 3 seconds of every minute will keep the radio in the high power state for only 8 seconds, and will keep it in the low power state for only an additional 12 seconds.

The second example allows the radio to be idle for an additional 40 second every minute, resulting in a massive reduction in battery consumption.
It's generally more efficient to reuse existing network connections than to initiate new ones. Reusing connections also allows the network to more intelligently react to congestion
and related network data issues.

》To better identify the cause of transfer spikes, the Traffic Stats API allows you to tag the data transfers occurring within a thread using the
TrafficStats.setThreadStatsTag()
method, followed by manually tagging (and untagging) individual
sockets using
tagSocket()
and
untagSocket()
. For example:
TrafficStats.setThreadStatsTag(0xF00D);
TrafficStats.tagSocket(outputSocket);
// Transfer data using socket
TrafficStats.untagSocket(outputSocket);


The Apache
HttpClient
and
URLConnection
libraries automatically tag sockets based on the current
getThreadStatsTag()
value. These libraries also tag and untag sockets when recycled through keep-alive
pools.
TrafficStats.setThreadStatsTag(0xF00D);
try {
// Make network request using HttpClient.execute()
} finally {
TrafficStats.clearThreadStatsTag();
}


Socket tagging is supported in Android 4.0, but real-time stats will only be displayed on devices running Android 4.0.3 or higher.

Optimizing Battery Life discusses
how to build battery-efficient apps that modify their refresh frequency based on the state of the host device. That includes disabling background service updates when you lose connectivity and reducing the rate of updates when the battery level is low.

When scheduling updates, use inexact repeating alarms that allow the system to "phase shift" the exact moment each alarm triggers.
int alarmType = AlarmManager.ELAPSED_REALTIME;
long interval = AlarmManager.INTERVAL_HOUR;
long start = System.currentTimeMillis() + interval;

alarmManager.setInexactRepeating(alarmType, start, interval, pi);


It's often useful to assert a minimum update frequency and to reset the frequency whenever the app is used, for example:
SharedPreferences sp =
context.getSharedPreferences(PREFS, Context.MODE_WORLD_READABLE);

boolean appUsed = sp.getBoolean(PREFS_APPUSED, false);
long updateInterval = sp.getLong(PREFS_INTERVAL, DEFAULT_REFRESH_INTERVAL);

if (!appUsed)
if ((updateInterval *= 2) > MAX_REFRESH_INTERVAL)
updateInterval = MAX_REFRESH_INTERVAL;

Editor spEdit = sp.edit();
spEdit.putBoolean(PREFS_APPUSED, false);
spEdit.putLong(PREFS_INTERVAL, updateInterval);
spEdit.apply();

rescheduleUpdates(updateInterval);
executeUpdateOrPrefetch();

》The most fundamental way to reduce your downloads is to download only what you need. In terms of data, that means implementing REST APIs that allow you to specify query criteria
that limit the returned data by using parameters such as the time of your last update.

Android 4.0 added a response cache to
HttpURLConnection
. You can enable HTTP response caching on supported devices using reflection as follows:
private void enableHttpResponseCache() {
try {
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
File httpCacheDir = new File(getCacheDir(), "http");
Class.forName("android.net.http.HttpResponseCache")
.getMethod("install", File.class, long.class)
.invoke(null, httpCacheDir, httpCacheSize);
} catch (Exception httpResponseCacheNotAvailable) {
Log.d(TAG, "HTTP response cache is unavailable.");
}
}

》When it comes to impact on battery life, not all connection types are created equal. Not only does the Wi-Fi radio use significantly less battery than its wireless radio counterparts,
but the radios used in different wireless radio technologies have different battery implications.

When connected over a wireless radio, higher bandwidth generally comes at the price of higher battery cost. Meaning that LTE typically consumes more energy than 3G, which is in turn
more expensive than 2G.

You can use the connectivity manager to determine the active wireless radio, and modify your prefetching routines accordingly:
ConnectivityManager cm =
(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

TelephonyManager tm =
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();

int PrefetchCacheSize = DEFAULT_PREFETCH_CACHE;

switch (activeNetwork.getType()) {
case (ConnectivityManager.TYPE_WIFI):
PrefetchCacheSize = MAX_PREFETCH_CACHE; break;
case (ConnectivityManager.TYPE_MOBILE): {
switch (tm.getNetworkType()) {
case (TelephonyManager.NETWORK_TYPE_LTE |
TelephonyManager.NETWORK_TYPE_HSPAP):
PrefetchCacheSize *= 4;
break;
case (TelephonyManager.NETWORK_TYPE_EDGE |
TelephonyManager.NETWORK_TYPE_GPRS):
PrefetchCacheSize /= 2;
break;
default: break;
}
break;
}
default: break;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: