9.0 Android中的网络技术

Android中网络相关的技术,主要分别两种,一种为直接显示网页,另外一种为获取服务器中的数据进行设置。

权限声明

访问网络是需要声明权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.webviewtest"><uses-permission android:name="android.permission.INTERNET" />...</manifest>

WebView的使用

通过WebView的控件,直接显示网页,不需要考虑网页中的具体数据。

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)webView.settings.javaScriptEnabled=truewebView.webViewClient = WebViewClient()webView.loadUrl("https://www.baidu.com")}}

调用了WebView的setWebViewClient()方法,并传入了一个WebViewClient的实例。这段代码的作用是,当需要从一个网页跳转到另一个网页时,我们希望目标网页仍然在当前WebView中显示,而不是打开系统浏览器。

HttpURLConnection的使用

get获取数据

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? = nulltry {val response = StringBuilder()val url = URL("https://www.baidu.com")connection = url.openConnection() as HttpURLConnectionconnection.connectTimeout = 8000connection.readTimeout = 8000val input = connection.inputStream// 下面对获取到的输入流进行读取val reader = BufferedReader(InputStreamReader(input))reader.use {reader.forEachLine {response.append(it)}}} catch (e: Exception) {e.printStackTrace()} finally {connection?.disconnect()}}}}
}

post发送数据

connection.requestMethod = "POST"
val output = DataOutputStream(connection.outputStream)
output.writeBytes("username=admin&password=123456")

okHttp的使用

项目主页地址:
https://github.com/square/okhttp
添加依赖:

dependencies {...implementation 'com.squareup.okhttp3:okhttp:4.1.0'
}

版本根据官网中的最新版本进行添加

okHttp的具体用法

获取Client的实例

val client = OkHttpClient()

创建get的request实例

创建request,需要知道是否需要设置token

val request = Request.Builder().url("https://www.baidu.com").build()

获取response

同步获取

val response = client.newCall(request).execute()
val responseData = response.body?.string()

异步获取:

   client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {//响应失败}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {//响应成功val responseData = response.body?.string()}});

发起Post的请求

val requestBody = FormBody.Builder().add("username", "admin").add("password", "123456").build()val request = Request.Builder().url("https://www.baidu.com").post(requestBody).build()

从Android 9.0系统开始,应用程序默认只允许使用HTTPS类型的网络请求,HTTP类型的网络请求因为有安全隐患默认不再被支持,如果使用的是HTTP,需要设置文件,res -> xml ->network_config.xml文件。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config><base-config cleartextTrafficPermitted="true"><trust-anchors><certificates src="system" /></trust-anchors></base-config>
</network-security-config>

这段配置文件是允许我们以明文的方式在网络上传输数据,而HTTP使用的就是明文传输方式。
需要修改manifest文件中的内容,如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.networktest">...<applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"android:networkSecurityConfig="@xml/network_config">...</application>
</manifest>

解析XML数据的两种方法:

①pull方法

方法parseXMLWithPull中的,即为使用Pull方法解析XML格式的数据

class MainActivity : AppCompatActivity() {...private fun sendRequestWithOkHttp() {thread {try {val client = OkHttpClient()val request = Request.Builder()// 指定访问的服务器地址是计算机本机.url("http://10.0.2.2/get_data.xml").build()val response = client.newCall(request).execute()val responseData = response.body?.string()if (responseData != null) {parseXMLWithPull(responseData)}} catch (e: Exception) {e.printStackTrace()}}}...private fun parseXMLWithPull(xmlData: String) {try {val factory = XmlPullParserFactory.newInstance()val xmlPullParser = factory.newPullParser()xmlPullParser.setInput(StringReader(xmlData))var eventType = xmlPullParser.eventTypevar id = ""var name = ""var version = ""while (eventType != XmlPullParser.END_DOCUMENT) {val nodeName = xmlPullParser.namewhen (eventType) {// 开始解析某个节点XmlPullParser.START_TAG -> {when (nodeName) {"id" -> id = xmlPullParser.nextText()"name" -> name = xmlPullParser.nextText()"version" -> version = xmlPullParser.nextText()}}// 完成解析某个节点XmlPullParser.END_TAG -> {if ("app" == nodeName) {Log.d("MainActivity", "id is $id")Log.d("MainActivity", "name is $name")Log.d("MainActivity", "version is $version")}}}eventType = xmlPullParser.next()}} catch (e: Exception) {e.printStackTrace()}}
}

②SAX方法

class MainActivity : AppCompatActivity() {...private fun sendRequestWithOkHttp() {thread {try {val client = OkHttpClient()val request = Request.Builder()// 指定访问的服务器地址是计算机本机.url("http://10.0.2.2/get_data.xml").build()val response = client.newCall(request).execute()val responseData = response.body?.string()if (responseData != null) {parseXMLWithSAX(responseData)}} catch (e: Exception) {e.printStackTrace()}}}...private fun parseXMLWithSAX(xmlData: String) {try {val factory = SAXParserFactory.newInstance()val xmlReader = factory.newSAXParser().XMLReaderval handler = ContentHandler()// 将ContentHandler的实例设置到XMLReader中xmlReader.contentHandler = handler// 开始执行解析xmlReader.parse(InputSource(StringReader(xmlData)))} catch (e: Exception) {e.printStackTrace()}}
}

ContentHandler的定义:

class ContentHandler : DefaultHandler() {private var nodeName = ""private lateinit var id: StringBuilderprivate lateinit var name: StringBuilderprivate lateinit var version: StringBuilderoverride fun startDocument() {id = StringBuilder()name = StringBuilder()version = StringBuilder()}override fun startElement(uri: String, localName: String, qName: String, attributes:Attributes) {// 记录当前节点名nodeName = localNameLog.d("ContentHandler", "uri is $uri")Log.d("ContentHandler", "localName is $localName")Log.d("ContentHandler", "qName is $qName")Log.d("ContentHandler", "attributes is $attributes")}override fun characters(ch: CharArray, start: Int, length: Int) {// 根据当前节点名判断将内容添加到哪一个StringBuilder对象中when (nodeName) {"id" -> id.append(ch, start, length)"name" -> name.append(ch, start, length)"version" -> version.append(ch, start, length)}}override fun endElement(uri: String, localName: String, qName: String) {if ("app" == 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 fun endDocument() {}}

id、name和version中都可能是包括回车或换行符的,需要调用trim。

解析JSON数据

官方提供的JSONObject,使用Google的开源库GSON。或者使用一些第三方的开源库如Jackson、FastJSON等。

①官方的JSONObject

......private fun parseJSONWithJSONObject(jsonData: String) {try {val jsonArray = JSONArray(jsonData)for (i in 0 until jsonArray.length()) {val jsonObject = jsonArray.getJSONObject(i)val id = jsonObject.getString("id")val name = jsonObject.getString("name")val version = jsonObject.getString("version")Log.d("MainActivity", "id is $id")Log.d("MainActivity", "name is $name")Log.d("MainActivity", "version is $version")}} catch (e: Exception) {e.printStackTrace()}}
}

②使用GSON解析

添加依赖

dependencies {...implementation 'com.google.code.gson:gson:2.8.5'
}

解析一段字符串
{“name”:“Tom”,“age”:20}
设置Person的类,直接进行转换

val gson = Gson()
val person = gson.fromJson(jsonData, Person::class.java)

解析字符串数组
需要借助TypeToken将期望解析成的数据类型传入fromJson()方法中

val typeOf = object : TypeToken<List<Person>>() {}.type
val people = gson.fromJson<List<Person>>(jsonData, typeOf)

jsonData为需要解析的字符串数组

网络请求回调方法:

interface HttpCallbackListener {fun onFinish(response: String)fun onError(e: Exception)
}
object HttpUtil {fun sendHttpRequest(address: String, listener: HttpCallbackListener) {thread {var connection: HttpURLConnection? = nulltry {val response = StringBuilder()val url = URL(address)connection = url.openConnection() as HttpURLConnectionconnection.connectTimeout = 8000connection.readTimeout = 8000val input = connection.inputStreamval reader = BufferedReader(InputStreamReader(input))reader.use {reader.forEachLine {response.append(it)}}// 回调onFinish()方法listener.onFinish(response.toString())} catch (e: Exception) {e.printStackTrace()// 回调onError()方法listener.onError(e)} finally {connection?.disconnect()}}}}

使用json

object HttpUtil {...fun sendOkHttpRequest(address: String, callback: okhttp3.Callback) {val client = OkHttpClient()val request = Request.Builder().url(address).build()client.newCall(request).enqueue(callback)}
}

使用

HttpUtil.sendOkHttpRequest(address, object : Callback {override fun onResponse(call: Call, response: Response) {// 得到服务器返回的具体内容val responseData = response.body?.string()}override fun onFailure(call: Call, e: IOException) {// 在这里对异常情况进行处理}
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/850615.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac m1使用docker安装mysql5.7,并且开启binlog

1. 使用 mysql/mysql-server:5.7 镜像 创建一个名为 docker-compose.yml 的文件&#xff0c;内容如下&#xff1a; version: 3.1services:mysql:image: mysql/mysql-server:5.7container_name: mysql57ports:- "3306:3306"environment:MYSQL_ROOT_PASSWORD: yourpa…

k8s学习--kubernetes服务自动伸缩之水平收缩(pod副本收缩)VPA详细解释与安装

文章目录 前言VPA简介简单理解详细解释VPA的优缺点优点1.自动化资源管理2.资源优化3.性能和稳定性提升5.成本节约6.集成性和灵活性 缺点1.Pod 重启影响可用性2.与 HPA 冲突3.资源监控和推荐滞后&#xff1a;4.实现复杂度&#xff1a; 核心概念Resource Requests 和 Limits自动调…

51单片机采用定时器T1的方式1的中断计数方式,外接开关K4按4次后,8只LED闪烁不停

1、功能描述 采用定时器T1的方式1的中断计数方式&#xff0c;外接开关K4按4次后&#xff0c;8只LED闪烁不停 2、实验原理 定时器原理:8051的定时器可以用于计数外部事件或执行内部定时操作。在本程序中&#xff0c;定时器1被设置为模式2&#xff0c;即8位自动重装载定时器模式…

DefaultTokenServices源码

文章目录 DefaultTokenServices实现的接口AuthorizationServerTokenServicesResourceServerTokenServicesConsumerTokenServices 代码属性定义createAccessToken(OAuth2Authentication)createRefreshToken(OAuth2Authentication) DefaultTokenServices DefaultTokenServices是…

Unity Shader基础知识的入门了解

目录 1、Unity 中的shader 里面的所谓的顶点坐标&#xff0c;用通俗的语言讲解一下? 什么是顶点&#xff1f; 顶点坐标是什么&#xff1f; 通俗解释顶点坐标 在Unity Shader中的顶点坐标 在Shader中使用顶点坐标 总结 2、顶点UV1/UV2 是什么意思&#xff0c;用通俗的语…

LeetCode116.填充每个节点的下一个右侧节点指针

法一&#xff1a; /* // Definition for a Node. class Node { public:int val;Node* left;Node* right;Node* next;Node() : val(0), left(NULL), right(NULL), next(NULL) {}Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}Node(int _val, Node* _left…

AI大模型学习(非常详细)零基础入门到精通,收藏这一篇就够了

前言 随着人工智能技术的快速发展&#xff0c;AI大模型学习正成为一项备受关注的研究领域。为了提高模型的准确性和效率&#xff0c;研究者们需要具备深厚的数学基础和编程能力&#xff0c;并对特定领域的业务场景有深入的了解。通过不断优化模型结构和算法&#xff0c;AI大模…

python如何输入回车

Python默认遇到回车的时候&#xff0c;输入结束。所以我们需要更改这个提示符&#xff0c;在遇到空行的时候&#xff0c;输入才结束。 raw_input就是从标注输入读取输入&#xff0c;输入的是什么就是什么。 文档解释&#xff1a; The function then reads a line from input,…

软考 系统架构设计师系列知识点之杂项集萃(30)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;29&#xff09; 第47题 安全性是根据系统可能收到的安全威胁的类型来分类的。其中&#xff0c;&#xff08; &#xff09;保证信息不泄露给未授权的用户、实体或过程&#xff1b;&#xff08; &a…

RabbitMQ 2万字面试题及参考答案

目录 什么是RabbitMQ? RabbitMQ的Broker、Exchange、Queue、Binding、Routing Key、VHost分别是什么? RabbitMQ中的生产者(Producer)和消费者(Consumer)的角色是什么? 什么是RabbitMQ的Channel? RabbitMQ支持哪些消息传输保证层级(如At most once, At least once…

不相同的字符串 acm模式刷题

题目描述 给定一个只包含小写字母的字符串&#xff0c;每次操作可以将两个相同的字母删除&#xff0c;然后在字符串的末尾新增任意一个小写字母。请问最少需要多少次操作&#xff0c;才能使字符串中所有的字母都不相同。 输入描述 第一行是一个整数 N&#xff0c;表示后续会有 …

UFS协议入门-分层结构

写在前面:本文参考UFS jedec3.1,本文思维导图如下 1. 分层概述 UFS协议分为3层,从上至下分别是:应用层(UAP),传输层(UTP),互联层(UIC),具体结构如下图所示。 2.1 应用层 在应用层(UAP)中,包括:UFS指令集(UCS),设备管理器(Device Manager),任务管理器(Task Manager…

代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

LeetCode 122.买卖股票的最佳时机II 题目链接&#xff1a;122.买卖股票的最佳时机II 踩坑&#xff1a;差点陷入不必要的细节&#xff0c;比如怎么表现买入卖出&#xff0c;怎么体现同一天买入卖出 思路&#xff1a;这里的股票买卖是看了天眼&#xff0c;明天的涨跌今天就知道…

基于FPGA的图像一维FFT变换IFFT逆变换verilog实现,包含tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 fpga仿真结果 matlab调用FPGA的仿真结果进行图像显示 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 ......................…

检测数据类型的方法有哪些

1.typeof&#xff0c;问题是对null的结果是object console.log(typeof 42); // "number" console.log(typeof hello); // "string" console.log(typeof true); // "boolean" console.log(typeof undefined); // "undefined" console.…

Knife4j 生成 API 文档

文章目录 Knife4j 简介使用步骤Knife4j 常用注解的列表案例可能遇到报错 Knife4j 简介 Knife4j 是一个增强的 Swagger 文档生成工具&#xff0c;提供了更加友好的界面和更多功能&#xff0c;使得 API 文档更加美观且易于使用。它是基于 Spring Boot 和 Swagger 进行封装的&…

2024年二级建造师考试题库及答案

一、单选题 11.对于同类型产品规格多、工序重复、工作量小的施工过程&#xff0c;编制人工定额宜采用的方法是&#xff08;&#xff09;。 A.经验估算法 B.技术测定法 C.统计分析法 D.比较类推法 答案&#xff1a;D 解析&#xff1a;本题考察的是"制定人工定额的常…

Xcode 安装17.5 simulator 总是失败

升级到xcode15.4后需要安装ios17.5模拟器 但是在下载过程中会遇到报错 : The network connection is lost 解决方案&#xff1a; 先将模拟器下载到本地 Xcode 安装17.5 simulator 下载地址&#xff1a; Sign In - Applhttps://developer.apple.com/download/all/?qXcode 下…

C# WPF入门学习主线篇(十五)—— DockPanel布局容器

C# WPF入门学习主线篇&#xff08;十五&#xff09;—— DockPanel布局容器 欢迎来到C# WPF入门学习系列的第十五篇。在前几篇文章中&#xff0c;我们探讨了 Canvas、StackPanel 和 WrapPanel 布局容器及其使用方法。本篇博客将介绍另一种强大且常用的布局容器——DockPanel。…