文章目录
- 使用网络技术
- WebView的用法
- 使用HTTP访问网络
- 使用HttpURLConnection
- 使用OkHttp
使用网络技术
- 在Android开发当中,我们应该合理的使用网络编写出更加出色的应用程序,下面学习以下如何在手机端使用HTTP和服务器进行网络交互,并对服务器返回的数据进行解析,这也是在Android当中最常用到的网络技术
WebView的用法
- 在开发的过程中有时候我们会遇到一些比较特殊的需求,比如说是要在应用程序当中展示一些网页,但是通常来说加载和显示到网页是浏览器应该做的事情,但是在需求当中又不允许我们打开浏览器,我们不可能自己去写一个浏览器出来,这时候应该怎么办呢?
- 其实Android早就考虑到了这种特殊的需求,给开发人员提供了一个WebView控件,借助这个控件我们就可以在自己的应用程序当中嵌入一个浏览器,从而轻松的展示各种各样的网页.
- 下面新建一个WebViewTest项目来使用一下这个控件的使用
- 修改activity_main.xml文件当中的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
- 可以看到在该文件当中只包含了一个WebView控件,这个空间就是用来显示网页的,这里的写法也比较简单,给它设置了一个id,然后让他充满了整个屏幕
- 然后修改MainActivity当中的代码
class MainActivity : AppCompatActivity() {
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView.settings.javaScriptEnabled = true
webView.webViewClient = WebViewClient()
webView.loadUrl("https://www.baidu.com")
}
}
- 上述代码也比较简单,通过WebView的getSettings()方法可以设置一些浏览器的属性,在这里调用了setJavaScriptEnabled()方法,让WebView支持JavaScript脚本
- 接下来是比较重要的部分,调用了WebView的setWebViewClient()方法并且传入了一个WebViewClient()的实例,这段代码的作用是,当需要从一个网页跳转到另外一个网页的时候,我们希望目标网页仍然在当前WebView当中进行显示,而不是打开系统浏览器.
- 最后一步就是调用了WebView的loadUrl()方法,并将网址传入,即可展示相应的网页内容
- 另外需要注意的是,由于本程序使用了网络功能,需要在AndroidManifest.xml文件当中,加入网络权限声明
<uses-permission android:name="android.permission.INTERNET" />
- 然后运行程序就可以看到我们打开了百度的网页
使用HTTP访问网络
- HTTP协议的基本原理简单来说就是,客户端向服务器发送一条HTTP请求,服务器在收到请求之后会返回一些数据给客户端,然后客户端再对这些数据进行解析和处理就可以了,一个浏览器的基本原理其实也就是这样.
- 在上述代码的WebView控件当中就是向百度的服务器发送了一条HTTP请求,接着服务器分析出我们想要访问的是百度的首页,接着把网页的HTML代码进行返回,然后WebView再调用手机浏览器内核对返回的HTML代码进行解析,最终将网页展示出来.
- 简单来说,WebView已经在后台帮我们处理好了发送HTTP请求,接收服务器响应,解析返回的数据,以及最终的页面展示这几个步骤.
使用HttpURLConnection
- 在过去Android发送HTTP请求的方式一般有两种:HttpURLConnection和HttpClient两种方式
- 但是HttpClient存在API数量过多,扩展困难等问题,所以在Android6.0系统中HttpClient的功能被完全移除了
- 下面看看官方推荐的HttpURLConnection的用法
- 首先需要获取HttpURLConnection实例,一般只需要创建一个URL对象,并传入目标的网络地址,然后调用一下openConnection()方法即可,如下所示
val url = URL("Https://www.baidu.com")
val connection = url.openConnection() as HttpURLConnection
- 在得到HttpURLConnection的实例之后,我们可以设置一下HTTP请求所使用的方法,常用的方法主要有:POST,GET
- POST一般表示希望提交数据给服务器,GET一般表示从服务器获取数据
- 写法如下:
connection.requestMethod = "GET"
- 接下来可以进行一些自由的定制,比如设置连接超时,读取超时的毫秒数,以及服务器希望得到的一些消息头.这部分内容根据自己的实际情况进行编写,示例写法如下:
connection.connectTimeout = 8000
connection.readTimeout = 8000
- 之后再调用getInputstream()方法就可以获取到服务器返回的输入流了,剩下的任务就是对输入流进行读取:
val input = connection.inputStream
- 最后可以调用disconnect()方法,将这个HTTP连接进行关闭
connection.disconnect()
- 下面新建一个NetworkTest项目,来体验一下HttpURLConnection的用法
- 首先修改activity_main.xml文件中的代码
<?xml version="1.0" encoding="utf-8"?>
<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/sendRequestBtn"
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/respondText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>
-
在这里面我们主要使用了一个新的控件ScrollView,因为由于手机屏幕比较小,有时候过多的内容显示不下,借助ScrollView控件就可以通过滚动屏幕的方式来查看屏幕以外的内容了
-
另外还有一个按钮和一个TextView,分别用来发送HTTP请球和显示服务器返回的数据的
-
现在写MainActivity当中的代码来编写具体的逻辑
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sendRequestBtn.setOnClickListener {
sendRequestWithHttpURLConnection()
}
}
private fun sendRequestWithHttpURLConnection() {
//开启线程发起网络请求
thread {
var connection: HttpURLConnection? = null
try {
val response = StringBuilder()
val url = URL("https://www.baidu.com")
connection = url.openConnection() as HttpURLConnection
connection.connectTimeout = 8000
connection.readTimeout = 8000
val input = connection.inputStream
//下面对获取到的输入流进行读取
val reader = BufferedReader(InputStreamReader(input))
reader.use {
reader.forEachLine {
response.append(it)
}
}
showResponse(response.toString())
} catch (e: Exception) {
e.printStackTrace()
} finally {
connection?.disconnect()
}
}
}
private fun showResponse(response: String) {
runOnUiThread {
//在这里进行UI操作,将结果显示到界面上
respondText.text = response
}
}
}
- 在sendRequestWithHttpURLConnection()方法中,先开启了一个子线程,然后在这个子线程中先使用HttpURLConnection发出了一条HTTP请求,然后利用BufferReader对服务器返回的流进行读取,并将结果传入到showResponse()方法当中
- 而在showResponse()方法中,调用了runOnUiThread()方法,之所以调用这个方法是因为,Android是不允许在子线程当中更新UI的,而这个方法是利用了异步消息处理机制,所以借助这个方法我们将服务器返回的数据更新到界面上
- 最后还要再声明一下网络权限
<uses-permissi android:name="android.permission.INTERNET" />
- 现在运行程序点击按钮就可以看到下面的这些数据
- 可以看到服务器给我们返回的就是这种HTML代码,只不过浏览器可以将这些HTML代码解析渲染成为精美的网页
- 上述是从服务器获取数据,加假如我们想要向服务器提交数据该怎么办?
- 这时候我们可以使用POST方法,并在获取输入流之前将要提交的数据进行写出即可
- 每条数据都要以键值对的形式存在,数据与数据之间使用"&"符号进行隔开,比如我们想要向服务器提交用户名和密码,我们可以这样写
connection.requestMethod = "POST"
val output = DataOutputStream(connection.outputStream)
output.writeBytes("username=admin&password=123456")
使用OkHttp
-
在开源盛行的今天,除过HttpURLConnection,也并不是没有其他的选择,有许多出色的网络通信库都可以替代原生的HttpURLConnection,而OkHttp无疑是做的最出色的一个
-
OkHttp是Square公司开发的一款在接口封装上做的简单易用,就连底层也是自成一派,现在已经成为广大Android开发者首选的网络通信库
-
OkHttp的项目主页地址是:Http://github.com/square/okhttp
-
在使用OkHttp之前我们需要现在项目当中添加OkHttp库的依赖
implementation("com.squareup.okhttp3:okhttp:4.10.0")
- 添加上述依赖之后会自动下载两个库,一个是OkHttp库,一个Okio库,后者是前者的通信基础.
- 使用OkHttp首先需要创建一个OkHttpClient实例,如下所示
val client = OkHttpClient()
- 接下来如果想要发起一条HTTP请球,就需要创建一个Request对象:
val request = Request.Builder().build()
- 上述代码是创建一了一个空的request对象,沃恩可以在最终的build()方法之前连缀很多个其他的方法来丰富这个Request对象,比如可以通过url()方法来设置目标网络地址,如下所示
val request = Request.Builder()
.url("https://www.baidu.com")
.build()
- 之后调用OkHttpClient的newCall()方法来创建一个Call对象,并调用它的execute()方法,来发送请求并获取服务器返回的数据,写法如下:
val response = client.newCall(resquest).execute()
- Response对象就是服务器返回的数据了,我们可以使用以下写法来的到返回的具体内容
val responseData = response.body?.string()
- 如果我们要发起一条POST请求,会比GET请求稍微复杂一点,我们需要先构建Request Body对象来存放待提交的参数,如下所示:
val requestBody = FormBody.Builder()
.add("username", "admin")
.add("password", "123456")
.build()
- 然后在Request.Builder中调用一下post()方法,并将RequestBody对象传入
val request = Request.Builder()
.url("https://www.baidu.com")
.post(requestBody)
.build()
- 接下来的操作就和GET请求一样了.调用execute()方法来发送请求并获取服务器返回的数据即可
- 在NetworkTest项目当中改用OkHttp的方式实现一遍
private fun sendRequestWithOkHttp() {
thread {
try {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://www.baidu.com")
.build()
val response = client.newCall(request).execute()
val responseData = response.body?.string()
if (responseData != null) {
showResponse(responseData)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
- 该方法实现的效果和之前编写的sendRequestWithHttpURLConnection()方法实现的效果是一样的,但是在使用上还是简便了一些的.