This lesson shows you how to implement a simple application that connects to the network. It explains some of the best practices you should follow in creating even the simplest network-connected app.

本篇文档向您展示了如何实现一个可以连接到网络的应用。文章也给出了一些你在开发应用时应该注意的事项。

Note that to perform the network operations described in this lesson, your application manifest must include the following permissions:

记住,要想让你的应用执行一些与网络相关的操作,在你的manifest文件中添加以下的权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Choose an HTTP Client


Most network-connected Android apps use HTTP to send and receive data. Android includes two HTTP clients: HttpURLConnection and Apache HttpClient. Both support HTTPS, streaming uploads and downloads, configurable timeouts, IPv6, and connection pooling. We recommend using HttpURLConnection for applications targeted at Gingerbread and higher. For more discussion of this topic, see the blog post Android's HTTP Clients.

大多数的安卓网络应用都是使用http协议来收发数据的。安卓包括两个http客户端类,一个是HttpUrlConnection,一个是阿帕奇的HttpClient。这两者都支持https协议,流数据的上传和下载,配置连接时长,IPV6,以及连接池技术。我们建议,在Gingerbread或者更高的版本中,使用HttpUrlConnection类。

Check the Network Connection


Before your app attempts to connect to the network, it should check to see whether a network connection is available using getActiveNetworkInfo() and isConnected(). Remember, the device may be out of range of a network, or the user may have disabled both Wi-Fi and mobile data access. For more discussion of this topic, see the lesson Managing Network Usage.

在你的应用连接网络之前,先使用getActiveNetworkInfo方法和isConnected()检测下网络连接是否可用。记住,用户随时会走出网络的范围,或者是用户会关掉wi-fi什么的。

其中,isConnected(),

Indicates whether network connectivity exists and it is possible to establish connections and pass data.

Always call this before attempting to perform data transactions.

判断是否有是否与网络建立连接。

getActiveNetworkInfo

Returns details about the currently active data network. When connected, this network is the default route for outgoing connections. You should always check isConnected() before initiating network traffic. This may return null when no networks are available.

public void myClickHandler(View view) {
...
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
// fetch data
} else {
// display error
}
...
}

Perform Network Operations on a Separate Thread


Network operations can involve unpredictable delays. To prevent this from causing a poor user experience, always perform network operations on a separate thread from the UI. The AsyncTask class provides one of the simplest ways to fire off a new task from the UI thread. For more discussion of this topic, see the blog postMultithreading For Performance.

与网络相关的操作难免会有时延的问题,时延也是不可预见的。为了避免时延引起的糟糕的用户体验,将任何与网络相关的操作放在单独的线程中。AsyncTask类就提供了一个不错的方法,可以让一个与网络相关的操作不在主线程中运行。

In the following snippet, the myClickHandler() method invokes new DownloadWebpageTask().execute(stringUrl). The DownloadWebpageTask class is a subclass ofAsyncTaskDownloadWebpageTask implements the following AsyncTask methods:

在下面的实例中,myClickHandler方法会调用new DownloadWebpageTask().execute(stringUrl).其中,DownloadWebpageTask类是AsyncTask类的一个子类,当然了,它就要实现AsyncTask类的方法:没有直接用AsyncTask类,而是使用它的子类。

  • doInBackground() executes the method downloadUrl(). It passes the web page URL as a parameter. The method downloadUrl() fetches and processes the web page content. When it finishes, it passes back a result string.

实现的第一个方法是doInBackground。这个方法会执行子类DownloadWebpageTaskdownloadUrl方法。也就是将下载操作放在doInBackground方法中实现。downloadUrl方法的参数是一个要下载的网页地址。downloadUrl下载该网页,并且处理网页内容。当处理网页操作结束后,downloadUrl方法会返回一个字符串。

第二个要实现的方法是onPostExecute。这个方法会自动接收downloadUrl方法返回的处理结果字符串,也就是接收doInBackGround方法返回的字符串。并且将这个字符串显示在界面上。

public class HttpExampleActivity extends Activity {
private static final String DEBUG_TAG = "HttpExample";
private EditText urlText;
private TextView textView; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
urlText = (EditText) findViewById(R.id.myUrl);
textView = (TextView) findViewById(R.id.myText);
} // When user clicks button, calls AsyncTask.
// Before attempting to fetch the URL, makes sure that there is a network connection.
public void myClickHandler(View view) {
// Gets the URL from the UI's text field.
String stringUrl = urlText.getText().toString();
ConnectivityManager connMgr = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
new DownloadWebpageText().execute(stringUrl);
} else {
textView.setText("No network connection available.");
}
} // Uses AsyncTask to create a task away from the main UI thread. This task takes a
// URL string and uses it to create an HttpUrlConnection. Once the connection
// has been established, the AsyncTask downloads the contents of the webpage as
// an InputStream. Finally, the InputStream is converted into a string, which is
// displayed in the UI by the AsyncTask's onPostExecute method.
private class DownloadWebpageText extends AsyncTask {
@Override
protected String doInBackground(String... urls) { // params comes from the execute() call: params[0] is the url.
try {
return downloadUrl(urls[0]);
} catch (IOException e) {
return "Unable to retrieve web page. URL may be invalid.";
}
}
// onPostExecute displays the results of the AsyncTask.
@Override
protected void onPostExecute(String result) {
textView.setText(result);
}
}
...
}

The sequence of events in this snippet is as follows:

这个实例代码执行的逻辑顺序是:

  1. When users click the button that invokes myClickHandler(), the app passes the specified URL to theAsyncTask subclass DownloadWebpageTask.

当用户点击一个按钮后,会调用myClickHandler方法,在这个方法中,会将指定的要下载的链接传递给AsyncTask类的子类DownloadWebpageTask

2. The AsyncTask method doInBackground() calls the downloadUrl() method.

AsyncTask类的方法doInBackground会调用downloadUrl方法。

3. The downloadUrl() method takes a URL string as a parameter and uses it to create a URL object.

downloadUrl方法将下载页面的地址作为参数,并以此参数创建一个URL对象。

4. The URL object is used to establish an HttpURLConnection.

再使用这个URL对象创建一个HttpURLConnection连接。

5. Once the connection has been established, the HttpURLConnection object fetches the web page content as an InputStream.

一旦这个连接建立,HttpURLConnection对象下载网页内容,并且将网页内容作为流;

6. The InputStream is passed to the readIt() method, which converts the stream to a string.

网页流再次传递给readIt方法,在readIt方法中,会将网页流转换为字符串。

7. Finally, the AsyncTask's onPostExecute() method displays the string in the main activity's UI.

最后,AsyncTask的onPostExecute方法会将这个转换后额字符串显示在界面上。

Connect and Download Data


In your thread that performs your network transactions, you can use HttpURLConnection to perform a GET and download your data. After you call connect(), you can get an InputStream of the data by callinggetInputStream().

在线程中执行网络操作时,你可以使用HttpURLConnection这个类来执行get操作,以下载网页内容。当你调用了connect方法,再次调用getInputStream方法时,你就可以获取网页内容的流了。

In the following snippet, the doInBackground() method calls the method downloadUrl(). ThedownloadUrl() method takes the given URL and uses it to connect to the network via HttpURLConnection. Once a connection has been established, the app uses the method getInputStream() to retrieve the data as anInputStream.

在下面的实例中,doInBackground方法会调用downloadUrl方法。downloadUrl以指定的要下载的网页地址为参数,通过HttpURLConnection来连接到这个网页。一旦连接建立了,就可以使用getInputStream方法来获取网页流数据了。

// Given a URL, establishes an HttpUrlConnection and retrieves
// the web page content as a InputStream, which it returns as
// a string.
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
// Only display the first 500 characters of the retrieved
// web page content.
int len = 500; try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.d(DEBUG_TAG, "The response is: " + response);
is = conn.getInputStream(); // Convert the InputStream into a string
String contentAsString = readIt(is, len);
return contentAsString; // Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}

Note that the method getResponseCode() returns the connection's status code. This is a useful way of getting additional information about the connection. A status code of 200 indicates success.

记住,getResponseCode返回创建连接时的服务器的响应。这是一个获取额外信息的方法。200一般表示连接成功。

Convert the InputStream to a String


An InputStream is a readable source of bytes. Once you get an InputStream, it's common to decode or convert it into a target data type. For example, if you were downloading image data, you might decode and display it like this:

InputStream就是可读的字节序列。一旦你获取了InputStream,一般而言,你需要将其解码或者转化为一个具体的类型。即,字节序列谁都看不懂,要把它转化成有意义的东西,比如字符串,位图等。比如,如果你下载了一个图片,你需要解码这个字节序列成图片,并且显示这个图片:

InputStream is = null;
...
Bitmap bitmap = BitmapFactory.decodeStream(is);
ImageView imageView = (ImageView) findViewById(R.id.image_view);
imageView.setImageBitmap(bitmap);

In the example shown above, the InputStream represents the text of a web page. This is how the example converts the InputStream to a string so that the activity can display it in the UI:

在上述的例子中,InputStream代表了网页的文本内容。下面的代码显示了如何将InputStream转化为字符串的,这样activity就可显示这个字符串了:

// Reads an InputStream and converts it to a String.
public String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}

总结:

1. 与网络相关的操作放在单独的线程中,如可以使用AsyncTask类的子类,实现doInBackground方法和onPostExecuter方法;

2. 判断下当前用户设备是否已经连接上网络了,以及网络的连接状态,比如,移动网络是否已经打开,wifi是否已经打开;

3. 根据下载的网页地址URL创建HttpUrlConnection类,HttpUrlConnection.connect建立连接。

4. 记住,关闭inputStream流;

5. 将返回的网页流数据解码为有意义的东西。

Connecting to the Network的更多相关文章

  1. Network authentication method and device for implementing the same

    A network authentication method is to be implemented using a network authentication device and a use ...

  2. Ethical Hacking - NETWORK PENETRATION TESTING(1)

    Pre--Connection-Attacks that can be done before connecting to the network. Gaining Access - How to b ...

  3. Maven 代理设置

    在maven的安装目录下 %MAVEN_HOME%/conf/setting.xml 中进行设置 <proxies>    <!-- proxy     | Specificatio ...

  4. 解决maven下载jar慢的问题(如何更换Maven下载源)

    修改 配置文件 maven 安装 路径 F:\apache-maven-3.3.9\conf 修改 settings.xml 在 <mirrors> <!-- mirror | Sp ...

  5. maven学习(上)- 基本入门用法

    一.下载及安装 1.1 下载maven 3.1.1 先到官网http://maven.apache.org/download.cgi 下载最新版本(目前是3.1.1 ),下载完成后,解压到某个目录(本 ...

  6. Maven日常 —— 你应该知道的一二三

    以前在日常工作中,使用Maven只是机械的执行Maven clean.Maven install,对其中的原理与过程并无了解,近期阅读了<Maven实战>,对Maven有了更深入的理解. ...

  7. Maven配置Nexus私服

    官方文档:http://books.sonatype.com/nexus-book/3.0/reference/maven.html#maven-sect-single-group 1,下载安装 首先 ...

  8. maven私服搭建

    一.软件安装 地址:http://www.sonatype.org/nexus/thank-you-for-downloading/?dl=tgz 解压: 启动: >> nexus sta ...

  9. maven settings.xml 阿里云

    <?xml version="1.0" encoding="UTF-8"?> <!--Licensed to the Apache Softw ...

随机推荐

  1. Unpaired/Partially/Unsupervised Image Captioning

    这篇涉及到以下三篇论文: Unpaired Image Captioning by Language Pivoting (ECCV 2018) Show, Tell and Discriminate: ...

  2. Qt之自定义搜索框——QLineEdit里增加一个Layout,还不影响正常输入文字(好像是一种比较通吃的方法)

    简述 关于搜索框,大家都经常接触.例如:浏览器搜索.Windows资源管理器搜索等. 当然,这些对于Qt实现来说毫无压力,只要思路清晰,分分钟搞定. 方案一:调用QLineEdit现有接口 void ...

  3. 微信小程序把玩(十八)picker组件

    原文:微信小程序把玩(十八)picker组件 picker选择器分为三种,普通选择器,时间选择器, 日期选择器 用mode属性区分,默认是普通选择器.测试时时间和日期点击无反应不知道是BUG还是啥!没 ...

  4. 蚂蚁金服招聘-JAVA资深开发工程师/专家-蚂蚁金服保险

    岗位描述: 1.协助业务方梳理业务需求,提供业务规划方案.架构设计方案: 2.负责业务系统的规划设计,制定产品的技术发展路线,完成重要业务模块及核心框架的搭建及编码实现: 3.发现和解决业务系统的技术 ...

  5. shell脚本配置ssh免密登陆

    通过shell脚本配置免密登陆,分为两个脚本,一个是配置文件config.env,一个是正式脚本sshkey.sh. # config.envexport HOST_USER=(root) expor ...

  6. Android零基础入门第43节:ListView优化和列表首尾使用

    原文:Android零基础入门第43节:ListView优化和列表首尾使用 前面连续几期都在学习ListView的各种使用方法,如果细心的同学可能会发现其运行效率是有待提高的,那么本期就来一起学习有哪 ...

  7. ORACLE 11.2.0.4 RAC安装在rhel6上

    . 关闭ipv4防火墙(两个节点): [root@RAC01 ~]# service iptables stop [root@RAC01 ~]# service iptables status ipt ...

  8. 向github提交本地项目

    首先你需要一个github账号,所有还没有的话先去注册吧! https://github.com/ 我们使用git需要先安装git工具,这里给出下载地址,下载后一路直接安装即可: https://gi ...

  9. PowerShell将Windows store应用程序安装为开发者模式

    原文: PowerShell将Windows store应用程序安装为开发者模式 在本地部署Windows 商店应用程序时,我们会遇到Add-AppDevPackage.ps1脚本,这个脚本和所在安装 ...

  10. [收录] Highcharts-ng —— AngularJS 的图表扩展

    原文:http://www.tuicool.com/articles/u6VZJjQ Highcharts-ng 是一个 AngularJS 的指令扩展,实现了在AngularJS 应用中集成High ...