Managing Network Usage
This lesson describes how to write applications that have fine-grained control over their usage of network resources. If your application performs a lot of network operations, you should provide user settings that allow users to control your app’s data habits, such as how often your app syncs data, whether to perform uploads/downloads only when on Wi-Fi, whether to use data while roaming, and so on. With these controls available to them, users are much less likely to disable your app’s access to background data when they approach their limits, because they can instead precisely control how much data your app uses.
本篇文档想你展示了,如何实际这样一个应用,应用可以对自己访问网络资源进行有效地控制。如果应用执行了很多网络操作,那么你应该给用户提供一些设置操作,比如,多久同步一次数据,是否当有wifi时执行上传下载操作等等。有了这些设置项,用户才不会对你的应用反感。也就是,给用户一些网络操作方面的设置。
For general guidelines on how to write apps that minimize the battery life impact of downloads and network connections, seeOptimizing Battery Life and Transferring Data Without Draining the Battery.
Check a Device's Network Connection
A device can have various types of network connections. This lesson focuses on using either a Wi-Fi or a mobile network connection. For the full list of possible network types, see ConnectivityManager
.
一个设备可能有不同类型的网络连接。本片文档将会聚焦于wifi和一般的移动数据连接。当然了,如果你对其他的连接类型感兴趣,可以参考ConnectivityManager
。这个类中定义了很多不同的网络连接方式。
Wi-Fi is typically faster. Also, mobile data is often metered, which can get expensive. A common strategy for apps is to only fetch large data if a Wi-Fi network is available.
wifi的速度是很快的。当英语要获取很大的数据时,首选当然是wifi了。
Before you perform network operations, it's good practice to check the state of network connectivity. Among other things, this could prevent your app from inadvertently using the wrong radio. If a network connection is unavailable, your application should respond gracefully. To check the network connection, you typically use the following classes:
在你的应用执行网络操作之前,要养成检测网络连接的好习惯。如果没有可用的网络连接,你的应用要有友好的提示信息。为了检测网络连接,你可以通过以下两种方式:所谓检测网络连接,可以理解为本地连接,在这种本地连接的基础上,是HttpUrlConnection的连接。
ConnectivityManager
: Answers queries about the state of network connectivity. It also notifies applications when network connectivity changes.
ConnectivityManager可用于检查网络连接状态。而且,当网络连接改变时,也提供同志功能。
NetworkInfo
: Describes the status of a network interface of a given type (currently either Mobile or Wi-Fi).
NetworkInfo
描述了如wifi等网络连接更多的信息。
private static final String DEBUG_TAG = "NetworkStatusExample";
...
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
boolean isWifiConn = networkInfo.isConnected();
networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
boolean isMobileConn = networkInfo.isConnected();
Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);
Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);
tests network connectivity for Wi-Fi and mobile. It determines whether these network interfaces are available (that is, whether network connectivity is possible) and/or connected (that is, whether network connectivity exists and if it is possible to establish sockets and pass data):
下面的代码测试了wifi连接,也就是检测这些连接类型是否可用,也就是检查下,网络连接是否有可能建立,如果能够建立,那么再检查下网络是否已经连接。只有连接了,才能使用sockets来收发数据。
Note that you should not base decisions on whether a network is "available." You should always checkisConnected()
before performing network operations, sinceisConnected()
handles cases like flaky mobile networks, airplane mode, and restricted background data.
注意,在执行网络操作之前,一定要通过isConnected
检查下网络是否已经连接。
A more concise way of checking whether a network interface is available is as follows. The methodgetActiveNetworkInfo()
returns a NetworkInfo
instance representing the first connected network interface it can find, or null
if none of the interfaces is connected (meaning that an internet connection is not available):
一种更为精确的检查本地连接是否连接的方式如下。getActiveNetworkInfo
方法会返回一个NetworkInfo
实例。这个实例代表了getActiveNetworkInfo
方法发现的第一个连接的本地连接,如果没有本地连接时连接的话,则返回一个null。
public boolean isOnline() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
Manage Network Usage
You can implement a preferences activity that gives users explicit control over your app's usage of network resources. For example:
技术上而言,你还需要设计一个“设置”活动,允许用户显示的通过这个活动来设置网络资源,比如:就像有些应用,刚开始运行时会检查网络连接,如果没有连接的话,会让用户进入网络界面进行设置。
- You might allow users to upload videos only when the device is connected to a Wi-Fi network.
只有在设备连接上wi-fi时,你的应用才会允许用户上传视频。
- You might sync (or not) depending on specific criteria such as network availability, time interval, and so on.
To write an app that supports network access and managing network usage, your manifest must have the right permissions and intent filters.
要想让用户能够通过你的应用来设置网络,你需要在manifest文件设置相应的权限等。这里强调了两件事情,一个是允许应用访问网络,一个是允许应用提供网络访问的控制。
- The manifest excerpted below includes the following permissions:
android.permission.INTERNET
—Allows applications to open network sockets.
android.permission.INTERNET
-允许应用打开网络套接字。这个是允许应用访问网络资源。android.permission.ACCESS_NETWORK_STATE
—Allows applications to access information about networks.
android.permission.ACCESS_NETWORK_STATE
-允许用户访问网络信息。这个是允许应用访问网络信息。
- You can declare the intent filter for the
ACTION_MANAGE_NETWORK_USAGE
action (introduced in Android 4.0) to indicate that your application defines an activity that offers options to control data usage.ACTION_MANAGE_NETWORK_USAGE
shows settings for managing the network data usage of a specific application. When your app has a settings activity that allows users to control network usage, you should declare this intent filter for that activity. In the sample application, this action is handled by the classSettingsActivity
, which displays a preferences UI to let users decide when to download a feed.
另外,还需在manifest文件的“网络设置”活动的intent过滤器中,设置ACTION_MANAGE_NETWORK_USAGE
行为。该行为会显示网络设置。在同样的应用中,这个行为会被类SettingsActivity
处理,这个类,也就是一个活动,会显示一个配置界面,允许用户声明合适下载一个种子(这些都是官方源码里的东西)。因此,如果应用要给用户提供一个可以配置的活动,就需要在活动的intent filter声明一个ACTION_MANAGE_NETWORK_USAGE
。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.networkusage"
...> <uses-sdk android:minSdkVersion="4"
android:targetSdkVersion="14" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <application
...>
...
<activity android:label="SettingsActivity" android:name=".SettingsActivity">
<intent-filter>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
Implement a Preferences Activity
As you can see in the manifest excerpt above, the sample app's activity SettingsActivity
has an intent filter for the ACTION_MANAGE_NETWORK_USAGE
action. SettingsActivity
is a subclass of PreferenceActivity
. It displays a preferences screen (shown in figure 1) that lets users specify the following:
正如上面manifest文件中可看到,例子源码中的SettingsActivity
活动有一个intent过滤器,该过滤器有一个ACTION_MANAGE_NETWORK_USAGE
行为。SettingsActivity
是PreferenceActivity
子类。SettingsActivity
会显示一个配置界面,这个配置界面会允许用户:
- Whether to display summaries for each XML feed entry, or just a link for each entry.
源码中的东西
- Whether to download the XML feed if any network connection is available, or only if Wi-Fi is available.
源码中的东西。
Here is SettingsActivity
. Note that it implements OnSharedPreferenceChangeListener
. When a user changes a preference, it fires onSharedPreferenceChanged()
, which sets refreshDisplay
to true. This causes the display to refresh when the user returns to the main activity:
以下是SettingsActivity的源码。注意,
SettingsActivity
实现了OnSharedPreferenceChangeListener
接口。当用户修改了一个配置项,就会触发OnSharedPreferenceChangeListener
事件。这个事件会将变量refreshDisplay
设置为true,也就是说,会在用户退回到主activity时,刷新显示界面。
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Loads the XML preferences file
addPreferencesFromResource(R.xml.preferences);
} @Override
protected void onResume() {
super.onResume(); // Registers a listener whenever a key changes
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
} @Override
protected void onPause() {
super.onPause(); // Unregisters the listener set in onResume().
// It's best practice to unregister listeners when your app isn't using them to cut down on
// unnecessary system overhead. You do this in onPause().
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
} // When the user changes the preferences selection,
// onSharedPreferenceChanged() restarts the main activity as a new
// task. Sets the the refreshDisplay flag to "true" to indicate that
// the main activity should update its display.
// The main activity queries the PreferenceManager to get the latest settings. @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
// Sets refreshDisplay to true so that when the user returns to the main
// activity, the display refreshes to reflect the new settings.
NetworkActivity.refreshDisplay = true;
}
}
Respond to Preference Changes
When the user changes preferences in the settings screen, it typically has consequences for the app's behavior. In this snippet, the app checks the preferences settings in onStart()
. if there is a match between the setting and the device's network connection (for example, if the setting is "Wi-Fi"
and the device has a Wi-Fi connection), the app downloads the feed and refreshes the display.
用户会在配置活动中改变一些配置项。如下源码显示,应用会在启动时检查旧有的配置数据,如果,比如,设置中设置了如果已经连接了wifi就会如何如何,而应用启动时,设备还真的已经连接了wifi,应用就会下载种子。
public class NetworkActivity extends Activity {
public static final String WIFI = "Wi-Fi";
public static final String ANY = "Any";
private static final String URL = "http://stackoverflow.com/feeds/tag?tagnames=android&sort=newest"; // Whether there is a Wi-Fi connection.
private static boolean wifiConnected = false;
// Whether there is a mobile connection.
private static boolean mobileConnected = false;
// Whether the display should be refreshed.
public static boolean refreshDisplay = true; // The user's current network preference setting.
public static String sPref = null; // The BroadcastReceiver that tracks network connectivity changes.
private NetworkReceiver receiver = new NetworkReceiver(); @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Registers BroadcastReceiver to track network connection changes.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
receiver = new NetworkReceiver();
this.registerReceiver(receiver, filter);
} @Override
public void onDestroy() {
super.onDestroy();
// Unregisters BroadcastReceiver when app is destroyed.
if (receiver != null) {
this.unregisterReceiver(receiver);
}
} // Refreshes the display if the network connection and the
// pref settings allow it. @Override
public void onStart () {
super.onStart(); // Gets the user's network preference settings
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); // Retrieves a string value for the preferences. The second parameter
// is the default value to use if a preference value is not found.
sPref = sharedPrefs.getString("listPref", "Wi-Fi"); updateConnectedFlags(); if(refreshDisplay){
loadPage();
}
} // Checks the network connection and sets the wifiConnected and mobileConnected
// variables accordingly.
public void updateConnectedFlags() {
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
if (activeInfo != null && activeInfo.isConnected()) {
wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;
} else {
wifiConnected = false;
mobileConnected = false;
}
} // Uses AsyncTask subclass to download the XML feed from stackoverflow.com.
public void loadPage() {
if (((sPref.equals(ANY)) && (wifiConnected || mobileConnected))
|| ((sPref.equals(WIFI)) && (wifiConnected))) {
// AsyncTask subclass
new DownloadXmlTask().execute(URL);
} else {
showErrorPage();
}
}
... }
Detect Connection Changes
The final piece of the puzzle is the BroadcastReceiver
subclass, NetworkReceiver
. When the device's network connection changes, NetworkReceiver
intercepts the action CONNECTIVITY_ACTION
, determines what the network connection status is, and sets the flags wifiConnected
and mobileConnected
to true/false accordingly. The upshot is that the next time the user returns to the app, the app will only download the latest feed and update the display if NetworkActivity.refreshDisplay
is set to true
.
在上面的代码中,还有一个BroadcastReceiver
子类,也就是NetworkReceiver
。当设备的网络连接发生变化时,NetworkReceiver会拦截
CONNECTIVITY_ACTION
行为,它会探知目前是wifi连接上,还是手机网连接上,然后相应的设置标志位。
Setting up a BroadcastReceiver that gets called unnecessarily can be a drain on system resources. The sample application registers the BroadcastReceiver
NetworkReceiver
in onCreate()
, and it unregisters it in onDestroy()
. This is more lightweight than declaring a <receiver>
in the manifest. When you declare a <receiver>
in the manifest, it can wake up your app at any time, even if you haven't run it for weeks. By registering and unregistering NetworkReceiver
within the main activity, you ensure that the app won't be woken up after the user leaves the app. If you do declare a <receiver>
in the manifest and you know exactly where you need it, you can use setComponentEnabledSetting()
to enable and disable it as appropriate.
例子源码中在onCreate
中注册了BroadcastReceiver
NetworkReceiver
接收器,然后在onDestroy
中卸载接收器。这可比在manifest文件中声明一个<receiver>
元素要轻量级多了。如果你在manifest文件中声明了一个<receiver>,这个元素会在任何时候唤起你的应用,即使你N年都没有运行这个应用了。通过在主要的活动中注册和反注册
NetworkReceiver
,那么当用户不运行应用的时候,也不会被什么东西唤起。
public class NetworkReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager conn = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = conn.getActiveNetworkInfo(); // Checks the user prefs and the network connection. Based on the result, decides whether
// to refresh the display or keep the current display.
// If the userpref is Wi-Fi only, checks to see if the device has a Wi-Fi connection.
if (WIFI.equals(sPref) && networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
// If device has its Wi-Fi connection, sets refreshDisplay
// to true. This causes the display to be refreshed when the user
// returns to the app.
refreshDisplay = true;
Toast.makeText(context, R.string.wifi_connected, Toast.LENGTH_SHORT).show(); // If the setting is ANY network and there is a network connection
// (which by process of elimination would be mobile), sets refreshDisplay to true.
} else if (ANY.equals(sPref) && networkInfo != null) {
refreshDisplay = true; // Otherwise, the app can't download content--either because there is no network
// connection (mobile or Wi-Fi), or because the pref setting is WIFI, and there
// is no Wi-Fi connection.
// Sets refreshDisplay to false.
} else {
refreshDisplay = false;
Toast.makeText(context, R.string.lost_connection, Toast.LENGTH_SHORT).show();
}
}
Managing Network Usage的更多相关文章
- Connecting to the Network
This lesson shows you how to implement a simple application that connects to the network. It explain ...
- 【Android Developers Training】 79. 连接到网络
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- Android Training
Building Apps with Content Sharing Simple Data --> Intent && ActionProvider 介绍如何让应用程序共享简单 ...
- Android开发训练之第五章——Building Apps with Connectivity & the Cloud
Building Apps with Connectivity & the Cloud These classes teach you how to connect your app to t ...
- Network Load Balancing Technical Overview--reference
http://technet.microsoft.com/en-us/library/bb742455.aspx Abstract Network Load Balancing, a clusteri ...
- [转] Firewall and network filtering in libvirt
Firewall and network filtering in libvirt There are three pieces of libvirt functionality which do n ...
- Android 性能优化(5)网络优化 (1) Collecting Network Traffic Data 用Network Traffic tool :收集传输数据
Collecting Network Traffic Data 1.This lesson teaches you to Tag Network Requests 标记网络类型 Configure a ...
- http2协议翻译(转)
超文本传输协议版本 2 IETF HTTP2草案(draft-ietf-httpbis-http2-13) 摘要 本规范描述了一种优化的超文本传输协议(HTTP).HTTP/2通过引进报头字段压缩以及 ...
- Running a Remote Desktop on a Windows Azure Linux VM (远程桌面到Windows Azure Linux )-摘自网络(试了,没成功 - -!)
A complete click-by-click, step-by-step video of this article is available ...
随机推荐
- SpringBoot简易搭建
1.建立maven工程 2.打开pom文件, 将以下配置拷贝过去 <parent> <groupId>org.springframework.boot</groupId& ...
- 网络流量查看工具为 iftop
作者: daodaoliang 时间: 2016年5月23日 版本: v0.0.1 邮箱: daodaoliang@yeah.net 日常用的网络流量查看工具为 iftop, 但是他仅仅只能简单的查看 ...
- SQL Server 限制IP登陆(登陆触发器运用)
原文:SQL Server 限制IP登陆(登陆触发器运用) 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 补 ...
- Win10《芒果TV》更新v3.6.0秋收版:新增追剧磁贴、记忆续播、跳转列表
热血青春,唱响革命战歌,<秋收起义>正在芒果TV热播,Win10版<芒果TV>更新v3.6.0秋收版,新增追剧磁贴.记忆续播.跳转列表. Win10版<芒果TV>V ...
- Win10版《芒果TV》获评2016年度Windows Store最佳官方/休闲娱乐应用(LiveSino和微软信仰中心联合评选)
微软信仰中心于2016年12月9日联合了 LiveSino 进行了最佳 Windows Store 应用特辑的投票评选,通过为期20天的海量用户投票,Win10版<芒果TV>荣获最佳官方应 ...
- SqlServer 可更新订阅升级字段队列数据丢失原因
原文:SqlServer 可更新订阅升级字段队列数据丢失原因 之前简单描述过数据冲突发生的原因:SQLServer可更新订阅数据冲突的一个原因 ,但具体内部原理是怎么丢失的还不清楚,今天补充说明.可更 ...
- 笔记:Advanced Installer 打包Web应用
原文:笔记:Advanced Installer 打包Web应用 公司要做一款增值税小产品,区别于ACME,本产品核心只有销项部分,面对的客户群是小企业,单税盒单开票机..... 我要做的主要有以下几 ...
- Survey Report on Data Skew in Big Data
1 Introduction 信息时代产生了大量的数据,运用和使用数据已经成为一个公司乃至一个国家核心实力的重要组成部分.当代大数据一般指的是:数据量巨大,需要运用新处理模式才能具有更强的决策力.洞察 ...
- postgresql + JDBC 学习
Based on debian 9, postgresql 9.6 and Java 8, at Dec-24-2018 ======================================= ...
- C# 遍历窗体控件顺序问题
今天在做C# winform 窗体控件遍历时遇到控件顺序的问题,也就是控件被遍历的先后问题.实际情况如下所述. 窗体界面如下: 界面构成是:主界面有一个 Panel (Panel_14),Panel_ ...