- WebView的用法
- 使用HttpURLConnection
- 使用OkHttp
- Pull解析方式
9.1 WebView的用法
WebView控件,借助它我们就可以在自己的应用程序里嵌入一个浏览器,从而非常轻松地展示各种各样的网页。
public class MainActivity extends AppCompatActivity
{
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.web_view);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("http://www.baidu.com");
}
}
调用WebView的getSettings()方法可以去设置一些浏览器的属性,调用了setJavaScriptEnabled()方法来让WebView支持JavaScript脚本。
我们调用了WebView的setWebViewClient()方法,并传入了一个WebViewClient实例。这段代码的作用是,当需要从一个网页跳转到另一个网页时,我们希望目标网页仍然在当前WebView中显示,而不是打开系统浏览器。
调用WebView的loadUrl()方法,并将网址传入,即可展示相应网页的内容。
由于本程序使用到了网络功能,而访问网络是需要申明权限的。
<uses-permission android:name="android.permission.INTERNET"/>
9.2 使用HTTP协议访问网络
对于HTTP协议,它的工作原理非常简单,就是客服端向服务器发出一条HTTP请求,服务器收到请求之后会返回一些数据给客服端,然后客服端再对这些数据进行解析和处理就可以了。
使用HttpURLConnection
我们就学习一下现在官方建议使用的HttpURLConnection的用法
首先需要获取到HttpURLConnection的实例,一般只需new出一个URL对象,并传入目标的网络地址,然后调用一下openConnection()方法即可。
URL url = new URL("http://www.baidu.com");
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();
整体代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
private TextView responseText;
private Button sendRequest;
@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)
{
switch (v.getId())
{
case R.id.send_request:
setSendRequestWithHttpURLConnection();
break;
default:
break;
}
}
private void setSendRequestWithHttpURLConnection()
{
new Thread(new Runnable()
{
@Override
public void run()
{
HttpURLConnection connection = null;
BufferedReader reader = 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();
//下面对获取到的输入流进行读取
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();
}
private void showResponse(final String response)
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
//在这里进行UI操作,将结果显示到界面上
responseText.setText(response);
}
});
}
}
在Send Request按钮的点击事件里调用了sendRequestWithHttpURLConnection()方法,在这个方法中先是开启了一个子线程,然后在子线程里使用HttpURLConnection发出一条HTTP请求,请求的目标地址就是百度的首页。接着利用BufferedReader对服务器返回的流进行读取,并将结果传入到了showResponse()方法中。而在showResponse()方法中则是调用了一个runOnUiThread()方法,然后在这个方法的匿名类参数中进行操作,将返回的数据显示到界面上。那么这里为什么要用这个runOnUiThread()方法呢?这是因为Android不允许在子线程中进行UI操作的,我们需要通过这个方法将线程切换到主线程,然后再更新UI元素。
如果是想要提交数据给服务器应该怎么办呢?只要将HTTP请求的方法改成POST,并在获取输入流之前把要提交的数据写出即可。注意每条数据都要以键值对的形式存在,数据与数据之间用"&"符号隔开,比如说我们想要向服务器提交用户名和密码。
connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&password=123456");
9.2 使用OkHttp
在项目中添加OkHttp库的依赖。
compile 'com.squareup.okhttp3:okhttp:3.6.0'
添加上诉依赖会自动下载两个库,一个是OkHttp库,一个是OKio库,后者是前者的通信基础。
OkHttp的具体用法
首先需要创建一个OkHttpClient的实例。
OkHttpClient okHttpClient = new OkHttpClient();
接下来如果想要发起一条HTTP请求,就需要创建一个Request的对象。
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
我们可以在最终的build()方法之前连缀很多其他方法来丰富这个Request对象。比如可以通过url()方法来设置目标的网络地址。
之后调用OkHttpClient的newCall()方法来创建一个Call()对象,并调用它的execute()方法来发送请求并获取服务器返回的数据,其中Response对象就是服务器返回的数据了。
Response response = okHttpClient.newCall(request).execute();
String responeData = response.body().string();
如果是发起一条POST请求会比GET请求稍微复杂一点,我们需要先构建出一个RequestBody对象来存放待提交的参数。
RequestBody requestBody = new FormBody.Builder()
.add("username","admin")
.add("password","123456")
.build();
然后在Request.Builder中调用一下post()方法,将RequestBody对象传入。
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(requestBody)
.build();
接下来就和GET请求一样了,调用execute()方法来发送请求并获取服务器返回的数据即可。
整体代码:
private void sendRequestWithOkHttp()
{
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Response response = okHttpClient.newCall(request).execute();
showResponse(response.body().string());
} catch (IOException e)
{
e.printStackTrace();
}
}
}).start();
}
9.3 解析XML格式文件
安装Apache
软件,现存入一个XML
文件
<apps>
<app>
<id>1</id>
<name>Google Maps</name>
<version>1.0</version>
</app>
<app>
<id>2</id>
<name>Chrome</name>
<version>2.1</version>
</app>
<app>
<id>3</id>
<name>Google Play</name>
<version>2.3</version>
</app>
</apps>
Pull解析方式
Request request = new Request.Builder()
.url("http://192.168.1.101/get_data.xml")
.build();
这里将HTTP
请求的地址改成了http://192.168.1.101/get_data.xml
。192.168.1.101
是电脑本机的IP
地址。
如果是模拟器的话,http://10.0.2.2/get_data.xml
。10.0.2.2
对于模拟器来说就是电脑本机的IP
地址。
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 = "";
// 获取pull解析器对应事件类型
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(TAG, "id is : "+id);
Log.d(TAG, "name is : "+name);
Log.d(TAG, "version is : "+version);
}
break;
}
default:
break;
}
eventType = xmlPullParser.next();
}
} catch (Exception e) {
e.printStackTrace();
}
}
看下parseXMLWithPull()
方法,首先要获取到一个XmlPullParserFactory
的实例,并借助这个实例得到XmlPullParser
对象,然后调用XmlPullParser
的setInput()
方法将服务器返回的XML
数据设置进去就可以开始解析了。
eventType
: 事件类型START_DOCUMENT
: 表示读到文档的开始位置,START_TAG
:表示读到文档中的元素开始位置,如idEND_DOCUMENT
:表示读到文档结束的位置END_TAG
: 表示读到文档中的元素结束位置
通过getEventType()
可以得到当前的解析事件,然后在一个while
循环中不断地进行解析,如果当前的解析事件不等于XmlPullParser.END_DOCUMENT
,说明解析工作还没完成,调用next()
方法后可以获取下一个解析事件。
在while
循环中,我们通过getName()
方法得到当前节点的名字,如果发现节点名等于id
,name
或version
,就调用nextText()
方法来获取节点内具体的内容。