Android基础之十七使用网络技术

Android基础之十七使用网络技术

本章主要会讲述如何在手机端使用HTTP协议和服务器端进行网络交互,并对服务器返回的数据进行解析,这也是Android中最常使用到的网络技术了,下面就让我们一起来学习一下吧。

1 WebView的用法

借助它我们就可以在自己的应用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页

WebView的用法也是相当简单,下面我们就通过一个例子来学习一下吧。新建一个WebViewTest项目,然后修改activity_main.xml中的代码,如下所示

	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

可以看到,我们在布局文件中使用到了一个新的控件,WebView。这个控件当然也就是用来显示网页的了,这里的写法很简单,给它设置了一个id,并让它充满整个屏幕。

然后修改MainActivity中的代码,如下所示:

package com.example.webview;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {
	private WebView webview;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		webview=(WebView) findViewById(R.id.web_view);
		webview.getSettings().setJavaScriptEnabled(true);
		webview.setWebViewClient(new WebViewClient() {
			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				view.loadUrl(url); // 根据传入的参数再去加载新的网页
				return true; // 表示当前WebView可以处理打开新网页的请求,不用借助系统浏览器
			}
		});
		webview.loadUrl("http://www.baidu.com");
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

MainActivity中的代码也很短,首先使用findViewById()方法获取到了WebView的实例,然后调用WebView的getSettings()方法可以去设置一些浏览器的属性,这里我们并不去设置过多的属性,只是调用了setJavaScriptEnabled()方法来让WebView支持JavaScript脚本。

接下来是非常重要的一个部分,我们调用了WebView的setWebViewClient()方法,并传入了WebViewClient的匿名类作为参数,然后重写了shouldOverrideUrlLoading()方法。这就表明当需要从一个网页跳转到另一个网页时,我们希望目标网页仍然在当前WebView中显示,而不是打开系统浏览器。

最后一步就非常简单了,调用WebView的loadUrl()方法,并将网址传入

另外还需要注意,由于本程序使用到了网络功能,而访问网络是需要声明权限的,因此我们还得修改AndroidManifest.xml文件,并加入权限声明,如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.webviewtest"
    android:versionCode="1"
    android:versionName="1.0" >
    ……
    <uses-permission android:name="android.permission.INTERNET" />
    ……
</manifest>

2 使用HTTP协议访问网络

它的工作原理特别的简单,就是客户端向服务器发出一条HTTP请求,服务器收到请求之后会返回一些数据给客户端,然后客户端再对这些数据进行解析和处理就可以了。

2.1 使用HttpURLConnection

在Android上发送HTTP请求的方式一般有两种,HttpURLConnectionHttpClient,本小节我们先来学习一下HttpURLConnection的用法。

首先需要获取到HttpURLConnection的实例,一般只需new出一个URL对象,并传入目标的网络地址,然后调用一下openConnection()方法即可,如下所示:

URL url = new URL("http://www.baidu.com");

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

得到了HttpURLConnection的实例之后,我们可以设置一下HTTP请求所使用的方法。常用的方法主要有两个,GET和POST。GET表示希望从服务器那里获取数据,而POST则表示希望提交数据给服务器。写法如下:

connection.setRequestMethod("GET");

接下来就可以进行一些自由的定制了,比如设置连接超时、读取超时的毫秒数,以及服务器希望得到的一些消息头等。这部分内容根据自己的实际情况进行编写,示例写法如下:

connection.setConnectTimeout(8000);

connection.setReadTimeout(8000);

之后再调用getInputStream()方法就可以获取到服务器返回的输入流了,剩下的任务就是对输入流进行读取,如下所示:

InputStream in = connection.getInputStream();

最后可以调用disconnect()方法将这个HTTP连接关闭掉,如下所示:

connection.disconnect();

下面就让我们通过一个具体的例子来真正体验一下HttpURLConnection的用法。新建一个NetworkTest项目,首先修改activity_main.xml中的代码,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/send_request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Request" />
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <TextView
            android:id="@+id/response"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </ScrollView>

</LinearLayout>

注意这里我们使用了一个新的控件,ScrollView,它是用来做什么的呢?由于手机屏幕的空间一般都比较小,有些时候过多的内容一屏是显示不下的,借助ScrollView控件的话就可以允许我们以滚动的形式查看屏幕外的那部分内容。另外,布局中还放置了一个Button和一个TextView,Button用于发送HTTP请求,TextView用于将服务器返回的数据显示出来。

接着修改MainActivity中的代码,如下所示:

public class MainActivity extends Activity implements OnClickListener {

	public static final int SHOW_RESPONSE = 0;

	private Button sendRequest;

	private TextView responseText;

	private Handler handler = new Handler() {

		public void handleMessage(Message msg) {
			switch (msg.what) {
			case SHOW_RESPONSE:
				String response = (String) msg.obj;
				// 在这里进行UI操作,将结果显示到界面上
				responseText.setText(response);
			}
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		sendRequest = (Button) findViewById(R.id.send_request);
		responseText = (TextView) findViewById(R.id.response_text);
		sendRequest.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.send_request) {
			sendRequestWithHttpURLConnection();
		}
	}

	private void sendRequestWithHttpURLConnection() {
		// 开启线程来发起网络请求
		new Thread(new Runnable() {
			@Override
			public void run() {
				HttpURLConnection connection = null;
				try {
					URL url = new URL("http://www.baidu.com");
					connection = (HttpURLConnection) url.openConnection();
					connection.setRequestMethod("GET");
					connection.setConnectTimeout(8000);
					connection.setReadTimeout(8000);
					InputStream in = connection.getInputStream();
					// 下面对获取到的输入流进行读取
				BufferedReader reader = new BufferedReader(new InputStreamReader(in));
					StringBuilder response = new StringBuilder();
					String line;
					while ((line = reader.readLine()) != null) {
						response.append(line);
					}
					Message message = new Message();
					message.what = SHOW_RESPONSE;
					// 将服务器返回的结果存放到Message中
					message.obj = response.toString();
					handler.sendMessage(message);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					if (connection != null) {
						connection.disconnect();
					}
				}
			}
		}).start();
	}

}

以看到,我们在Send Request按钮的点击事件里调用了sendRequestWithHttpURL- Connection()方法,在这个方法中先是开启了一个子线程,然后在子线程里使用HttpURLConnection发出一条HTTP请求,请求的目标地址就是百度的首页。接着利用BufferedReader对服务器返回的流进行读取,并将结果存放到了一个Message对象中。这里为什么要使用Message对象呢?当然是因为子线程中无法对UI进行操作了。我们希望可以将服务器返回的内容显示到界面上,所以就创建了一个Message对象,并使用Handler将它发送出去。之后又在Handler的handleMessage()方法中对这条Message进行处理,最终取出结果并设置到TextView上。

过在开始运行之前,仍然别忘了要声明一下网络权限。修改AndroidManifest.xml中的代码

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.networktest"
    android:versionCode="1"
    android:versionName="1.0" >
    ……
    <uses-permission android:name="android.permission.INTERNET" />
    ……
</manifest>

好了,现在运行一下程序,并点击Send Request按钮,结果如图2所示。

这是返回的 htmL格式,另外如果也可以以json数据的格式返回。

那么如果是想要提交数据给服务器应该怎么办呢?其实也不复杂,只需要将HTTP请求的方法改成POST,并在获取输入流之前把要提交的数据写出即可。注意每条数据都要以键值对的形式存在,数据与数据之间用&符号隔开,比如说我们想要向服务器提交用户名和密码,就可以这样写:

connection.setRequestMethod("POST");

DataOutputStream out = new DataOutputStream(connection.getOutputStream());

out.writeBytes("username=admin&password=123456");

2.2 使用HttpClient

HttpClient是Apache提供的HTTP网络访问接口,从一开始的时候就被引入到了Android API中。它可以完成和HttpURLConnection几乎一模一样的效果,但两者之间的用法却有较大的差别,那么我们自然要看一下HttpClient是如何使用的了。

首先你需要知道,HttpClient是一个接口,因此无法创建它的实例,通常情况下都会创建一个DefaultHttpClient的实例,如下所示:

HttpClient httpClient = new DefaultHttpClient();

接下来如果想要发起一条GET请求,就可以创建一个HttpGet对象,并传入目标的网络地址,然后调用HttpClient的execute()方法即可:

HttpGet httpGet = new HttpGet("http://www.baidu.com");

httpClient.execute(httpGet);

 并传入目标的网络地址,如下所示:

HttpPost httpPost = new HttpPost("http://www.baidu.com");

然后通过一个NameValuePair集合来存放待提交的参数,并将这个参数集合传入到一个UrlEncodedFormEntity中,然后调用HttpPost的setEntity()方法将构建好的UrlEncodedFormEntity传入,如下所示:

List<NameValuePair> params = new ArrayList<NameValuePair>();

params.add(new BasicNameValuePair("username", "admin"));

params.add(new BasicNameValuePair("password", "123456"));

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, "utf-8");

httpPost.setEntity(entity);

接下来的操作就和HttpGet一样了,调用HttpClient的execute()方法,并将HttpPost对象传入即可:

httpClient.execute(httpPost);

执行execute()方法之后会返回一个HttpResponse对象,服务器所返回的所有信息就会包含在这里面。通常情况下我们都会先取出服务器返回的状态码,如果等于200就说明请求和响应都成功了,如下所示:

if (httpResponse.getStatusLine().getStatusCode() == 200) {

// 请求和响应都成功了

}

接下来在这个if判断的内部取出服务返回的具体内容,可以调用getEntity()方法获取到一个HttpEntity实例,然后再用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串即可,如下所示:

HttpEntity entity = httpResponse.getEntity();

String response = EntityUtils.toString(entity);

注意如果服务器返回的数据是带有中文的,直接调用EntityUtils.toString()方法进行转换会有乱码的情况出现,这个时候只需要在转换的时候将字符集指定成utf-8就可以了,如下所示:

String response = EntityUtils.toString(entity, "utf-8");

好了,基本的用法就是如此,接下来就让我们把NetworkTest这个项目改用HttpClient的方式再实现一遍吧。

由于布局部分完全不用改动,所以现在直接修改MainActivity中的代码,如下所示

public class MainActivity extends Activity implements OnClickListener {
	……
	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.send_request) {
			sendRequestWithHttpClient();
		}
	}

	private void sendRequestWithHttpClient() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					HttpClient httpClient = new DefaultHttpClient();
					HttpGet httpGet = new HttpGet("http://www.baidu.com");
					HttpResponse httpResponse = httpClient.execute(httpGet);
					if (httpResponse.getStatusLine().getStatusCode() == 200) {
						// 请求和响应都成功了
						HttpEntity entity = httpResponse.getEntity();
						String response = EntityUtils.toString(entity, "utf-8");
						Message message = new Message();
						message.what = SHOW_RESPONSE;
						// 将服务器返回的结果存放到Message中
						message.obj = response.toString();
						handler.sendMessage(message);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
	}
	……
}

时间: 2025-01-02 14:22:31

Android基础之十七使用网络技术的相关文章

android基础(六)网络数据解析方法

在网络上传输数据时最常用的方法有两种:XML和JSON,下面就对这两种类型的数据解析进行讲解. 一.XML数据解析 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析器. (1)SAX解析 SAX(Simple API for XML)解析器是一种基于事件的解析器,它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的.当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理.在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器

android基础(五)网络编程

android 的网络编程一般可以分为两种:基于Socket的,基于Http的. 一.socket与Http socket封装了TCP/IP协议,TPC/IP协议是传输层协议,主要解决数据如何在网络中传输.socket通信方式是当服务器端与客户端建立起了socket连接后,服务器端可以直接将数据传输到客户端.(建立socket连接:建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket .套接字之间的连接过

Android基础入门教程——7.6.1 Socket学习网络基础准备

Android基础入门教程--7.6.1 Socket学习网络基础准备 标签(空格分隔): Android基础入门教程 本节引言: 为了照顾没学过Java Socket的初学者,或者说捋一捋Android开发中涉及到的网络协议相关的概念, 毕竟面试的时候,面试官来了句给我说下网络协议有几层?那么IP协议在哪层?Socket是什么鬼? 分哪几种?TCP和UDP协议又在哪层?有什么区别-嗯,这-所以学习本节概念性的理论还是很有 必要的!那么话不多说,开始本节内容~ 1.OSI七层网络模型浅析 当然,

网络技术基础概念和个人笔记总结(1)

防伪码:不经一番寒彻骨,怎得梅花扑鼻香 本次主要更新网络技术部署与运维个人笔记,附加作业练习(共八章节,分为四次更新) 二.三层交换技术 1.单臂路由的缺陷 a."单臂"本身将成为网络的骨干链路,容易形成瓶颈. b.子接口仍然依托于物理接口,就实际而言不灵活 c.每次vlann间转发都需要查看路由表,严重浪费设备资源 2.使用三层交换技术实现vlan间通信(面试题) 三层交换机的配置命令 a.启用路由功能:ip routing b.虚接口配置ip(充当网关) int vlan 2 ip

《2015最新Android基础入门教程》完结散花~

<2015最新Android基础入门教程>完结散花~ 标签(空格分隔): 反思小结 引言: 从六月底就开始编写这套教程,历时将近五个多月,今天终于写完了,全套教程正文部分148篇, 十大章,从基本UI控件到四大组件,Intent,Fragment,事件处理,数据存储,网络编程,绘图与动画, 多媒体,系统服务等都进行了详细的讲解!代码都是都是在Android Studio上进行编写的,全文 采用Markdown,行文结构清晰,还结合了实际开发中一些常见的问题进行了剖析-由于个人能力的局限, 虽然

Android基础入门教程——10.14 Android GPS初涉

Android基础入门教程--10.14 Android GPS初涉 标签(空格分隔): Android基础入门教程 本节引言: 说到GPS这个名词,相信大家都不陌生,GPS全球定位技术嘛,嗯,Android中定位的方式 一般有这四种:GPS定位,WIFI定准,基站定位,AGPS定位(基站+GPS): 本系列教程只讲解GPS定位的基本使用!GPS是通过与卫星交互来获取设备当前的经纬度,准确 度较高,但也有一些缺点,最大的缺点就是:室内几乎无法使用-需要收到4颗卫星或以上 信号才能保证GPS的准确

分享基于Android系统的XMPP即时通讯技术项目实战(仿微信开发架构,自定义控件)

即时通讯技术是 网络技术中的明珠.即时通讯产品改变了人们的生活习惯.经过十几年的发展,即时通讯功能的应用也逐渐从专门软件才能实现的功能逐渐成为标准配置.即时通讯技术的应用不仅仅只是用于社交领域,在大多的协同工作领域,以及需要分布结构的网络通讯领域都是非常重要的.讲师本人在android领域有多年的开发经验,在即时通讯系统方面也有深入的研究.在本课程中,详细讲解了android开发中要解决的一些主要的问题,即时通讯在客户端实现的过程,并手把手的进行操作,方便学习和理解.因为课时的原因,对于一些初级

android基础知识

1. 前言 1.1. 什么是3G.4G Ÿ 第三代移动通信技术(3rd - Generation),速率一般在几百Kbps,较之前的2G和2.5G在数据传输速度上有很大提升. Ÿ 第四代移动通信技术(4th - Generation),速度可达到100Mbps以上,几乎可以满足人们的所有传输数据的需求. Ÿ 目前主流的3G技术标准有三种: WCDMA:全球80%以上的3G网络都是采用此种制式.中国联通运营.186 CDMA2000:目前日韩及北美使用较多.中国电信运营. 189 TD-SCDMA

Android基础-04

Android基础-04 网络编程 从网络上获取数据: 文本.图片.音乐.视频. 01_网络图片查看器(重点) 步骤: 1.创建URL对象,打开一个HTTP类型的连接: 2.设置请求方式GET.POST,连接的超时时间等请求参数: 3.得到服务器端返回的响应数据(以二进制流的形式返回响应数据),判断响应码是不是200请求成功.404找不到资源.503服务器端内部错误: 4.把二进制流的响应数据转换成需要的数据类型: 模版代码: // 1.创建URL对象,打开一个HTTP类型的连接: URL ur