目录
WebView的用法
控件,借助它我们可以在自己的应用程序中嵌入一个浏览器
1.创建WebView控件
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webView"/>
2.获取WebView对象,设置相关属性
WebView webView = (WebView)findViewById(R.id.webView);
//webView.getSettings()方法可设置一些浏览器的属性
webView.getSettings().setJavaScriptEnabled(true);
//设置WebView支持JavaScript脚本
webView.setWebViewClient(new WebViewClient());
//当需要从一个网页跳转到另一个网页时,我们希望目标网页在当前WebView中显示,而不是打开系统浏览器
webView.loadUrl("http://www.baidu.com"); //传入要打开的网址
3.添加权限
<uses-permission android:name="android.permission.INTERNET"/>
此时运行发现打不开网页,需要设置android:usesCleartextTraffic=“true”
<application
...
android:usesCleartextTraffic="true"
...
</application>
由于这里要使用明文网络流量所以要设置成true
android:usesCleartextTraffic
指示应用程序是否打算使用明文网络流量,例如明文HTTP。目标API级别为27或更低的应用程序的默认值为“ true”。面向API级别28或更高级别的应用默认为“ false”。
当属性设置为“ false”时,平台组件(例如,HTTP和FTP堆栈,DownloadManager和MediaPlayer)将拒绝应用程序使用明文流量的请求。
强烈建议第三方库也采用此设置。避免明文通信的主要原因是缺乏机密性,真实性和防篡改保护;网络攻击者可以窃听所传输的数据,并且还可以对其进行修改而不会被检测到
使用HTTP协议访问网络
HttpURLConnection
从服务器获取数据
-
获取HttpURLConnection实例
这里是借助URL对象获取
URL url = new URL("http://www.baidu.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
- 设置请求所用的方法
GET:从服务器获取数据
POST:提交数据给服务器
connection.setRequestMethod("GET");
- 获取服务器的返回流,读取数据
完整代码如下:
private void sendRequestWithHttpURLConnection() {
//网络请求是费时操作,所以要开启线程来发起网络请求
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
BufferedReader bufferedReader = null;
try {
URL url = new URL("http://www.baidu.com");
connection =(HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET"); //设置HTTP请求所用的方法
connection.setConnectTimeout(8000); //设置连接超时的毫秒数
connection.setReadTimeout(8000); //设置读取超时的毫秒数
InputStream in = connection.getInputStream(); //获取到服务器返回的输入流
//对输入流进行读取
bufferedReader = new BufferedReader(new InputStreamReader(in));
StringBuilder stringBuilder = new StringBuilder();
String Line;
while ( (Line = bufferedReader.readLine()) != null){
stringBuilder.append(Line);
}
//shouResponse(stringBuilder.toString());
}catch (Exception e){
e.printStackTrace();
}finally {
if(connection != null)
connection.disconnect();
if(bufferedReader != null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
提交数据给服务器
方法和上面一样,只是把GET改为POST
private void acceptRequestWithHttpURLConnection() {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
BufferedWriter writer = null;
try {
URL url = new URL("http://www.baidu.com");
connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("STOP");
//获取输出流用于输出数据
OutputStream os = connection.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(os);
dataOutputStream.writeBytes("username=admin&password=123456");
/*
String st = textView.getText().toString();
writer = new BufferedWriter(new OutputStreamWriter(os));
writer.write(st);
*/
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
当然别忘了申请网络权限
<uses-permission android:name="android.permission.INTERNET"/>
使用OkHttp
OkHttp是Square公司开发的一款出色的开源库GitHub地址
添加依赖,可通过上面的网址获取最新的
implementation("com.squareup.okhttp3:okhttp:4.9.0")
使用:
- 获取服务器返回的数据
private void sendOKHttp() {
new Thread(new Runnable() {
@Override
public void run() {
try {
OkHttpClient client = new OkHttpClient(); //第一步:创建一个OkHttpClient的实例
Request request = new Request.Builder() //第二步:创建一个Request对象
.url("http://www.baidu.com")
.build();
Response response = client.newCall(request).execute();
//第三步:调用OkHttpClient的newCall方法创建Call对象,并调用他的execute()方法来发送请求并获取服务器返回的数据
//返回的数据可从Response对象中得到
String data = response.body().string();
shouResponse(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
- 提交数据到服务器
private void acceptOkHttp() {
new Thread(new Runnable() {
@Override
public void run() {
//第一步:构建一个RequestBody对象来存储待提交的数据
RequestBody requestBody = new FormBody.Builder()
.add("username","admin")
.add("password","123456")
.build();
//第二步:创建一个OkHttpClient的实例
OkHttpClient client = new OkHttpClient();
//第三步:创建一个Request对象
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(requestBody)
.build();
try {
//第四步:发送请求
Response response = client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
解析XML格式数据
Pull解析方式
private void parseXMLWithPUll(String st) {
/*PuLL解析XML格式数据
第一步:获取XmlPullParserFactory对象
第二步: 通过第一步获取的XmlPullParserFactory获取XmlPullParser对象
第三步:通过setInput()设置要解析的XML数据
第四步:执行解析逻辑
*/
try {
//获取XmlPullParserFactory实例
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
//获取XmlPullParser对象
XmlPullParser xmlPullParser = factory.newPullParser();
//设置要解析的XML数据
xmlPullParser.setInput(new StringReader(st));
//执行解析逻辑
int eventType = xmlPullParser.getEventType();
String id = "";
String name = "";
while(eventType!=xmlPullParser.END_DOCUMENT){
String getName = xmlPullParser.getName();
switch (eventType){
//开始解析某个节点
case XmlPullParser.START_TAG:
if("id".equals(getName))
id = xmlPullParser.nextText();
else if("name".equals(getName))
name = xmlPullParser.getName();
break;
//完成解析某个节点
case XmlPullParser.END_TAG :
//执行拿出数据后的操作,比如打印等
break;
}
eventType = xmlPullParser.next();
}
}catch (Exception e){
e.printStackTrace();
}
}
SAX解析方式
新建一个类继承自DefaultHandler,并重写父类的5个方法
package com.example.networktest;
import android.util.Log;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class ContentHandler extends DefaultHandler {
private String nodeName;
private StringBuilder id;
private StringBuilder name;
private StringBuilder version;
@Override
public void startDocument() throws SAXException {
//开始XML解析时调用
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());
id.setLength(0); //清空
name.setLength(0);
version.setLength(0);
}
}
@Override
public void endDocument() throws SAXException {
//完成整个XML解析时调用
super.endDocument();
}
}
调用,解析
private void parseXMLWithSAX(String respondata) {
//SAX解析
try {
//第一步:创建SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
//第二步:获取XMLReader对象
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
//第三步:获取DefaultHandler子类对象,传给XMLReader对象
ContentHandler handler = new ContentHandler();
xmlReader.setContentHandler(handler);
//第四步传入数据,开始执行解析
xmlReader.parse(new InputSource(new StringReader(respondata)));
} catch (SAXException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
解析JSON格式数据
JSONObject解析
private void parseJSONWithJSONObject(String data) {
//使用JSONObject解析json类型数据
try {
// 第一步获取JSONArray数组
JSONArray jsonArray = new JSONArray(data);
//第二步:遍历,拿到对应的数据
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject = jsonArray.getJSONObject(i);
String get1 = jsonObject.getString("name1");
String get2 = jsonObject.getString("name2");
String get3 = jsonObject.getString("name3");
}
} catch (Exception e) {
e.printStackTrace();
}
}
GSON解析
GSON是谷歌提供的开源库,让解析更简单。可以将一段JSON格式的字符串自动映射成一个对象。GitHub地址
- 添加依赖库
implementation 'com.google.code.gson:gson:2.8.6'
- 定义一个类,把要解析的设置成字段,提供get,set方法
package com.example.revise_9_2;
public class App {
private String get1;
private String get2;
private String get3;
public String getGet1() {
return get1;
}
public void setGet1(String get1) {
this.get1 = get1;
}
public String getGet2() {
return get2;
}
public void setGet2(String get2) {
this.get2 = get2;
}
public String getGet3() {
return get3;
}
public void setGet3(String get3) {
this.get3 = get3;
}
}
3.将JSON数据解析成类对象
如果JSON格式数据是这种:{“name”:“Tom”,“age”:20}解析方式如下:
Gson gson = new Gson();
App app = gson.fromJson(data,App.class);
之后就可通过类对象去得到数据
如果JSON格式数据是数组解析方式如下:
Gson gson = new Gson();
List<App> appList = gson.fromJson(data,new TypeToken<List<App>>(){
}.getType());
之后可通过遍历数组得到每一个类对象,拿到数据
完整如下
private void parseJSONWithGSON(String data) {
Gson gson = new Gson();
List<App> appList = gson.fromJson(data,new TypeToken<List<App>>(){
}.getType());
for(App app : appList){
String s1 = app.getGet1();
String s2 = app.getGet2();
String s3 = app.getGet3();
}
}
把HTTP请求封装成工具类
我们可以把HTTP的GET请求封装在类里,方便调用
对于HttpURLConnection我们要写一个接口使用回调的方法返回数据,而对于OkHttp它内部吧开启线程回调都处理好了,可直接使用。
接口:
package com.example.revise_9_1;
public interface HttpCallbcakListener {
void onFinish(String response);
void onError(Exception e);
}
工具类:
package com.example.revise_9_1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class HttpUtil {
public static void sendHttpRequest(final String address, final HttpCallbcakListener listener){
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection httpURLConnection = null;
BufferedReader bufferedReader = null;
try {
URL url = new URL(address);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(8000); //设置读取超时
httpURLConnection.setConnectTimeout(8000); //读取连接超时
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
InputStream inputStream = httpURLConnection.getInputStream();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String Line;
while((Line=bufferedReader.readLine())!= null){
stringBuilder.append(Line);
}
if(listener!=null)
//吧得到的数据通过接口返回
listener.onFinish(stringBuilder.toString());
} catch (Exception e) {
if(listener!=null)
//如果发生错误,返回对应的错误类型
listener.onError(e);
e.printStackTrace();
}finally {
if(httpURLConnection!=null)
httpURLConnection.disconnect();
if(bufferedReader!=null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.build();
//OkHtt在enqueue()方法的内部已经帮我们开好子线程了,它会在子线程中去执行HTTP请求,并将结果回调到okhttp3.Callback中
client.newCall(request).enqueue(callback);
}
}
调用:
String adress = "http://www.baidu.com";
HttpUtil.sendHttpRequest(adress, new HttpCallbcakListener() {
@Override
public void onFinish(final String response) {
//处理数据
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(response);
}
});
}
@Override
public void onError(Exception e) {
e.printStackTrace();
}
});
String adress1 = "http://www.baidu.com";
HttpUtil.sendOkHttpRequest(adress1, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
final String st = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
textView.setText(st);
}
});
}
});