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. java设计模式(2)

    工厂模式定义 在面向对象程序设计中,工厂通常是用来创建其他对象的对象,工产模式根据不同的参数来实现不同的分配方案和创建对象. 在工产模式中,我们创建对象时不会对客户端暴露创建逻辑,而且是通过使用一个共 ...

  2. Silverlight DataGrid自适应数据

    silverlight的DataGrid如果改成fill模式 那么当数据超长也不会出现横向滚动条 如果改成按单元格模式 如果数据较短又会出现空白的地方 所以我自己写了个算法 目前实现了以list为数据 ...

  3. Qt程序发行Linux版,软件打包知识(patchelf 工具修改依赖库,确认 qmake -v 是自己使用的Qt版本,否则用export PATH进行修改)good

    patchelf 工具可以修改已编译运行程序的依赖库位置和指定库链接器 patchelf --set-rpath patchelf --set-interpreter 通过这个工具 https://g ...

  4. GIS基础软件及操作(六)

    原文 GIS基础软件及操作(六) 练习六.空间分析的应用 1.加深对缓冲区分析基本原理.方法的认识:2.熟练掌握距离制图创建缓冲区技术方法.3.掌握利用缓冲区分析方法解决地学空间分析问题的能力. 1. ...

  5. Android零基础入门第26节:layout_gravity和gravity大不同

    原文:Android零基础入门第26节:layout_gravity和gravity大不同 上一期我们一起学习了LinearLayout线性布局的方向.填充模型和权重,本期来一起学习LinearLay ...

  6. SignalR的简单使用(二)

    原文:SignalR的简单使用(二) 之前提到SignalR代理在网页,通过生成的Js来完成相关的功能.但我不禁想一个问题, 难到SignalR的服务端就能寄存在web端吗,通过访问网页能方式才能启动 ...

  7. PHP 的魔术方法及其应用

    PHP中将所有__(两个下划线)开头的类方法作为魔术方法,这方法之所以称为魔术方法是因为其实现的功能就如变魔术一样感觉很神奇.在特定的事件下触发,这真的很酷. **__construct()** 这个 ...

  8. 全面解析ECMAScript 6模块系统

    快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中.   <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...

  9. Qt实现小功能之列表无限加载(创意很不错:监听滚动条事件,到底部的时候再new QListWidgetItem)

    概念介绍 无限加载与瀑布流的结合在Web前端开发中的效果非常新颖,对于网页内容具备较好的表现形式.无限加载并没有一次性将内容全部加载进来,而是通过监听滚动条事件来刷新内容的.当用户往下拖动滚动条或使用 ...

  10. 再说Java集合,subList之于ArrayList

    上一章说了很多ArrayList相关的内容,但还有一块儿内容没说到,那就是subList方法.先看一段代码 public static void testSubList() { List<Str ...