《Android第一行代码》第10章 网络379–410
WebView
通过WebView控件,我们可以在应用程序中嵌入浏览器,从而实现在应用程序中浏览各种各样的网页。
-
首先在main.xml中声明webview控件;
-
然后在MainActivity中实现相应的逻辑;
` 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"); }
}`
-
最后在AndroidManifest.xml中声明网络权限。
使用HTTP协议访问网络
在 Android 上发送 HTTP 请求的方式一般有两种,HttpURLConnection 和 HttpClient,
- HttpURLConnection
获取 HttpURLConnection 的实例,一般只需 new 出一个 URL 对象,并传入
目标的网络地址,然后调用一下 openConnection()方法即可.得到HttpURLConnection 的实例之后,我们可以设置一下 HTTP 请求所使用的方法。常用的方法主要有两个,GET 和 POST。GET 表示希望从服务器那里获取数据,而 POST 则表示希望提交数据给服务器。之后再调用 getInputStream()方法就可以获取到服务器返回的输入流了,剩下的任务就是对输入流进行读取,最后可以调用 disconnect()方法将这个 HTTP 连接关闭掉。
URL url = new URL("http://www.baidu.com"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); InputStream in = connection.getInputStream(); connection.disconnect();
- HttpClient
HttpClient是 Apache 提供的 HTTP 网络访问接口。
HttpClient httpClient = new DefaultHttpClient();
接下来如果想要发起一条 GET 请求,就可以创建一个 HttpGet 对象,并传入目标的网络地址,然后调用 HttpClient 的 execute()方法即可:
HttpGet httpGet = new HttpGet("http://www.baidu.com");
httpClient.execute(httpGet);
如果是发起一条 POST 请求会比 GET 稍微复杂一点,我们需要创建一个 HttpPost 对象,并传入目标的网络地址,如下所示:
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");
XML文本格式的解析
在网络上传输数据时最常用的格式有两种,XML 和 JSON。
XML常用解析方式:Pull解析和 SAX 解析。
Pull解析示例:
private void parseXMLWithPull(String xmlData) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlData));
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
String version = "";
while (eventType != XmlPullParser.END_DOCUMENT) {
String nodeName = xmlPullParser.getName();
switch (eventType) {
// 开始解析某个结点
case XmlPullParser.START_TAG: {
if ("id".equals(nodeName)) {
id = xmlPullParser.nextText();
} else if ("name".equals(nodeName)) {
name = xmlPullParser.nextText();
} else if ("version".equals(nodeName)) {
version = xmlPullParser.nextText();
}
break;
}
// 完成解析某个结点
case XmlPullParser.END_TAG: {
if ("app".equals(nodeName)) {
Log.d("MainActivity", "id is " + id);
Log.d("MainActivity", "name is " + name);
Log.d("MainActivity", "version is " + version);
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
SAX解析示例:
//单独声明的类
public class ContentHandler extends DefaultHandler {
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
@Override
public void startDocument() throws SAXException {
id = new StringBuilder();
name = new StringBuilder();
version = new StringBuilder();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// 记录当前结点名
nodeName = localName;
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中
if ("id".equals(nodeName)) {
id.append(ch, start, length);
} else if ("name".equals(nodeName)) {
name.append(ch, start, length);
} else if ("version".equals(nodeName)) {
version.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("app".equals(localName)) {
Log.d("ContentHandler", "id is " + id.toString().trim());
Log.d("ContentHandler", "name is " + name.toString().trim());
Log.d("ContentHandler", "version is " + version.toString().trim());
// 最后要将StringBuilder清空掉
id.setLength(0);
name.setLength(0);
version.setLength(0);
}
}
@Override
public void endDocument() throws SAXException {
}
}
//在MainActivity中的方法
private void parseXMLWithSAX(String xmlData) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
ContentHandler handler = new ContentHandler();
// 将ContentHandler的实例设置到XMLReader中
xmlReader.setContentHandler(handler);
// 开始执行解析
xmlReader.parse(new InputSource(new StringReader(xmlData)));
} catch (Exception e) {
e.printStackTrace();
}
}
JSON文本格式的解析
比起 XML,JSON 的主要优势在于它的体积更小,在网络上传输的时候可以更省流量。但缺点在于,它的语义性较差,看起来不如 XML 直观。
- 使用 JSONObject
- 使用 GSON