使用WebView控件访问网络
WebView这个控件主要是让我们的程序能够在不打开手机内置浏览器的情况下访问网页,就相当于是在我们的程序中安放了一下小型的浏览器,从而让我们的程序能够连接到互联网上,从而能够很轻松的展示各种网页。
在程序中使用WebView访问网络主要有三个步骤:
第一步:在布局中设置WebView控件,并在主代码中获取到WebView实例。
第二步:使用getSettings()来对对WebView进行设置。
第二步:对WebView使用loadUrl()方法,并将网址传入,之后就能够访问网页了。
知道了主要步骤,我们就来实践一下。创建一个空项目,然后对布局进行修改:
我们只是在布局中加了WebView的控件,这个控件和其他的控件的属性相似,我们让它完全的展开在父布局上面。接着是修改主代码:
package com.example.yzbkaka.webviewtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView)findViewById(R.id.web_view); //获取实例
webView.getSettings().setJavaScriptEnabled(true); //是否支持JS脚本
webView.setWebViewClient(new WebViewClient()); //是否支持换页
webView.loadUrl("http://www.bing.com"); //加载网站
}
}
在主代码中我们先是使用findViewById()的方法获取到了WebView的实例,接着是使用了getSettings()方法来为WebView设置一些属性,这里我们为WebView简单设置了支持JS脚本的属性。接着是使用setWebViewClient()方法让我们在WebView中打开新的网页时仍然是能够在WebView中浏览,而不是去打开手机浏览器。最后就是通过loadUrl方法将要打开的网站传入。
使用手机网络需要我们实现去申请权限:
最后在联网的手机上运行程序,即可访问bing了。
使用HTTP协议访问网络
1.HTTP工作原理
HTTP的工作原理简单来说客户端想服务端的服务器发送一条HTTP请求,然后服务端在收到请求之后会返回一些数据给客户端,最后客户端再对这些数据进行处理和解析即可。
2.发送HTTP
在Android原生的库中我们一般是采用HttpURLConnection类来进行发送HTTP请求的操作。我们来新建一个空项目来体验一下。首先是修改主布局代码:
我们设置了一个开始按钮,当之后我们运行程序时点击按钮就可以发送HTTP请求,并且会将数据返回来显示在下面的TextView中。
接着我们修改主代码:
package com.example.yzbkaka.networktest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button sendRequest;
private TextView responseText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendRequest = (Button)findViewById(R.id.send);
responseText = (TextView)findViewById(R.id.response);
sendRequest.setOnClickListener(this);
}
@Override
public void onClick(View view) {
if(view.getId() == R.id.send){
sendHTTPWithURLConnection();
}
}
public void sendHTTPWithURLConnection(){
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
BufferedReader reader = null;
try{
URL url = new URL("http://www.bing.com");
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while((line = reader.readLine()) != null){
response.append(line);
}
showResponse(response.toString());
}catch(Exception e){
e.printStackTrace();
}finally {
if(reader != null){
try{
reader.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(connection != null){
connection.disconnect();
}
}
}
}).start();
}
public void showResponse(final String response){
runOnUiThread(new Runnable() {
@Override
public void run() {
responseText.setText(response);
}
});
}
}
我们使用HttpURLConnection类发送HTTP请求主要是写在sendHTTPWithURL Connection()方法当中,我们可以将其中的思路分解成4步:
第一步:获取HttpURLConnection的实例。我们是先新建一个URL实例并将我们想要请求的地址输入进去,接着就是使用openConnection()方法。
第二步:对HttpURLConnection的实例进行一些属性的设置。setRequestMethod()是设置从服务器获取还是发送数据;setConnectTimeout()是设置连接超时的毫秒数;setReadTimeout()是设置读取超时的毫秒数。
第三步:使用Java流来读取数据。
第四步:使用disconnect()方法来将连接断开。
最后我们申明网络权限,然后运行程序就会看到一堆HTML代码,这些就是服务器返回给我们的数据。
解析数据
在前面我们发送HTTP请求的时候选择的网站服务器是bing,但是由于bing是一个供我们使用的搜索网站,因此它返回来的数据就是bing的HTML代码。不过我们建立能够访问网络的程序都会连接到自己的服务器,自已的服务器一般是用来供我们上传数据或者提取数据的,因此我们的服务器中应该是只存在数据的,而这些数据一般有XML和JSON两种格式。我们为了提取到我们需要的数据,就需要对这样的格式进行解析。
1.解析XML数据
XML的数据与HTML的风格类似,比较容易理解
一般解析XML格式的数据有两种方法,下面来使用这两种方法将上面的XML格式的数据来进行解析。
Pull解析
首先我们需要用一个String类型的responseData来存储上述数据,接着我们可以封装一个parseXMLWithPull()方法来进行具体的操作:
public void parseXMLWithPull(String responseData){
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser(); //获取XmlPullParser实例
xmlPullParser.setInput(new StringReader(responseData)); //将XML格式数据传入到XmlPullParser
int evenType = xmlPullParser.getEventType(); //得到当前的解析事件
String id = "";
String name = "";
String version = "";
while(evenType != XmlPullParser.END_DOCUMENT){ //如果没有解析完,就开始解析
String nodeName = xmlPullParser.getName(); //得到当前的标签
switch(evenType){
case XmlPullParser.START_TAG:{
if("id".equals(nodeName)){ //如果等于
id = xmlPullParser.nextText();
}
if("name".equals(nodeName)){ //如果等于
name = xmlPullParser.nextText();
}
if("version".equals(nodeName)){
version = xmlPullParser.nextText(); //如果等于
}
break;
}
case XmlPullParser.END_TAG:{
if("app".equals(nodeName)){
//完成一个标签之后的操作
}
break;
}
default:
break;
}
evenType = xmlPullParser.next(); //获取下一个解析事件
}
}catch(Exception e){
e.printStackTrace();
}
}
SAX解析
采用SAX解析相对于Pull解析来说步骤比较的多,不过这种方法是很容易理解的。首先我们先创建一个Myhandler类并让它继承自DefaultHandler类,然后重写父类的5个方法:
public class MyHandler extends DefaultHandler {
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
@Override
//在开始解析XML的时候调用
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 {
if ("id".equals(nodeName)) { // 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中
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)) {
//在解析完标签之后的操作
id.setLength(0); // 最后要将StringBuilder清空掉
name.setLength(0);
version.setLength(0);
}
}
@Override
//在标签解析完之后调用
public void endDocument() throws SAXException {
super.endDocument();
}
}
接着我们在主代码中来将XML传入,我们还是将数据存储到String类型的responseData中,然后封装一个parseXMLWithSAX()方法来进行具体的操作:
public void parseXMLWithSAX(String responseData){
try{
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
MyHandler handler = new MyHandler();
xmlReader.setContentHandler(handler); //将Myhandler加载进去
xmlReader.parse(new InputSource(new StringReader(responseData))); //将数据放进去进行解析
}catch (Exception e){
e.printStackTrace();
}
}
2.解析JSON数据
JSON格式的数据相对于XML会更加的简洁,同时解析JSON数据的方法也很简单,可是使用Android官方提供的JSONObject,也可是通过添加GSON依赖来进行解析。
JSONObject解析
我们同样,先使用String类型的responseData来存储上面的的JSON数据,接着我们来封装一个parseJSONWithJSONObject()的方法来进行具体的操作:
public void parseJSONWithJSONObject(String responseData){
try{
JSONArray jsonArray = new JSONArray(responseData); //将数据传入到JSONArray实例当中
for(int i = 0;i < jsonArray.length();i++){
JSONObject jsonObject = jsonArray.getJSONObject(i); //按照次序将数据赋给JSONObject实例
String id = jsonObject.getString("id"); //对JSONObject实例进行解析
String name = jsonObject.getString("name");
String version = jsonObject.getString("version");
Log.d("this","id is"+ id); //解析完得到数据后的操作
Log.d("this","name is"+ name);
Log.d("this","version is"+ version);
}
}catch (Exception e){
e.printStackTrace();
}
}
GSON解析
GSON是一个谷歌的开元库,因此使用它我们需要先添加依赖:
implementation 'com.google.code.gson:gson:2.7'
GSON的特别之处在于它能够JSON格式的数据自动映射为一个对象,而数据里面的内容就是我们在这个对象里面需要定义的数据。例如对上面的JSON数据来说,我们可以定义一个MyClass的类,并在该类里面定义id、version和name,并写出基本的Getter和Setter:
public class MyClass {
String id;
String name;
String version;
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setVersion(String version) {
this.version = version;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
}
接着我们封装一个parseJSONWithGSON()的方法来使用GSON解析数据:
public void parseJSONWithGSON(String responseData){
Gson gson = new Gson();
List myclassList = gson.fromJson(responseData,new TypeToken(){}.getType()); //将数据传入
for(MyClass myClass : myclassList){
Log.d("this","id is"+ myClass.getId()); //解析完得到数据后的操作
Log.d("this","name is"+ myClass.getName());
Log.d("this","version is"+ myClass.getVersion());
}
}