当前位置: 首页 > news >正文

Glide结合OkHttp保证短信验证接口携带图形验证码接口返回Cookie值去做网络请求

一、实现效果

在这里插入图片描述

二、步骤

注意:仅展示核心部分代码

1、导入依赖

api 'com.github.bumptech.glide:glide:4.10.0'
kapt 'com.github.bumptech.glide:compiler:4.10.0'
api 'com.squareup.okhttp3:okhttp:3.11.0'
api 'com.squareup.okhttp3:logging-interceptor:3.11.0'

2、自定义MyAppGlideModule类

自定义Okhttp的cookie管理,在Okhttp初始化的时候设置进去。并在Glide中注册请求对象。

因为发送短信的请求需要利用图形验证码请求的cookie,所以cookie管理的逻辑就是,保存上一次请求的cookie,下一次请求的时候利用上一次请求的cookie。

大概业务流程原理如图所示:
在这里插入图片描述
代码如下:

package com.custom.jfrb.http;import android.content.Context;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
//......@GlideModule
public class MyAppGlideModule extends AppGlideModule {public static OkHttpClient okHttpClient;@Overridepublic void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {okHttpClient = new OkHttpClient.Builder().cookieJar(new CookiesManager()).build();registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(okHttpClient));}@Overridepublic boolean isManifestParsingEnabled() {return false;}/*** Cookie管理类*/private class CookiesManager implements CookieJar {//保存每个url的cookieprivate HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();//上一个请求urlprivate HttpUrl url;@Overridepublic void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {//保存链接的cookiecookieStore.put(httpUrl, list);//保存上一次的url,供给下一次cookie的提取。url = httpUrl;}@Overridepublic List<Cookie> loadForRequest(HttpUrl httpUrl) {//加载上一个链接的cookieList<Cookie> cookies = cookieStore.get(url);return cookies != null ? cookies : new ArrayList<Cookie>();}}
}

3、自定义输入图形验证码弹窗Dialog

package com.custom.jfrb.ui.jfrb.login;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import com.alibaba.fastjson.JSONObject;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;@SuppressLint("ValidFragment")
public class SMSCheckDialog extends DialogFragment {private ImageView ivCode;private SMSCheckCallback checkCallback;//手机号private String phone;//账号名private String account;//可以把请求短信验证码接口时候需要的接口参数通过构造方法传进来public SMSCheckDialog(SMSCheckCallback callback, String phone,String account) {this.checkCallback = callback;this.phone = phone;this.account = account;}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setStyle(STYLE_NORMAL, R.style.CustomDialog);setCancelable(false);}@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.dialog_sms_check, container, false);ImageView ivDelete = view.findViewById(R.id.iv_delete);ivCode = view.findViewById(R.id.iv_code);ivCode.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//加载图形验证码loadCapture();}});loadCapture();final EditText etCode = view.findViewById(R.id.et_code);ivDelete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//关闭图形验证码弹窗dismiss();}});Button ivSure = view.findViewById(R.id.iv_login);ivSure.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (TextUtils.isEmpty(etCode.getText().toString())) {RnToast.showToast(getContext(),"请输入图形验证码");return;}//图形验证码输入完成后,发送短信验证码请求new Thread(new Runnable() {@Overridepublic void run() {//去请求发送短信验证码getSmsCode(account,phone,etCode.getText().toString());}}).start();}});return view;}/*** 加载显示图形验证码URL*/private void loadCapture(){if (getContext() != null) {Log.e("mylog","执行loadCapture请求");String url = UserService.getImageCodeURL();Glide.with(getContext()).load(url).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(ivCode);}}/*** 请求短信验证码* @param account 账户* @param phone 手机号码* @param imageCode 图片验证码*/private void getSmsCode(String account,String phone,String imageCode){Map<String,Object> map = new HashMap<>();map.put("userName",account);map.put("telephone",phone);map.put("captchaCheckCode",imageCode);JSONObject jsonObject = new JSONObject(map);MediaType JSON = MediaType.parse("application/json; charset=utf-8");RequestBody body = RequestBody.create(jsonObject.toString(),JSON);String url = "网络请求地址......";Log.d("mylog_sms: ","短信验证码获取请求参数:"+"_账号:"+account+"_手机号:"+phone+"_验证码:"+imageCode);Request request = new Request.Builder().url(url).post(body).build();MyAppGlideModule.okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {Log.d("mylog_sms: ","短信验证码接口请求失败"+e.toString());}@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {Log.d("mylog_sms: ","短信验证码请求成功"+response.toString());if (response == null){Log.d("mylog_sms: ","请求失败!");checkCallback.onGetCodeFailed(getString(R.string.send_fail));dismiss();return;}if (response.body() == null){Log.d("mylog_sms: ","请求失败!");checkCallback.onGetCodeFailed(getString(R.string.send_fail));dismiss();return;}String result = response.body().string();JSONObject object = (JSONObject) JSONObject.parse(result);Log.d("mylog_sms: ","接受短信验证码接口返回数据:"+object);if ((int)object.get("code") == 0){Log.d("mylog_sms: ","验证成功!");checkCallback.onGetCode();}else{Log.d("mylog_sms: ","验证错误");checkCallback.onGetCodeFailed(object.get("msg").toString());}dismiss();}});}public interface SMSCheckCallback {void onGetCode();void onGetCodeFailed(String msg);}
}

4、相关布局文件

styles.xml文件中放入如下自定义Style

<style name="CustomDialog" parent="android:style/Theme.Dialog"><!--背景颜色及和透明程度--><item name="android:windowBackground">@android:color/transparent</item><!--是否去除标题 --><item name="android:windowNoTitle">true</item><!--是否去除边框--><item name="android:windowFrame">@null</item><!--是否浮现在activity之上--><item name="android:windowIsFloating">true</item><!--是否模糊--><item name="android:backgroundDimEnabled">true</item></style>

Dialog图形验证码验证弹窗的布局文件

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="300dp"android:layout_height="wrap_content"android:layout_gravity="center"android:background="@drawable/shape_white_8"><ImageViewandroid:id="@+id/iv_delete"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="12dp"android:src="@drawable/close"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/tv_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="24dp"android:layout_marginTop="20dp"android:layout_marginEnd="10dp"android:text="请输入图形验证码"android:textColor="#999999"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/iv_delete" /><ImageViewandroid:id="@+id/iv_code"android:layout_width="70dp"android:layout_height="28dp"android:layout_marginTop="8dp"android:layout_marginEnd="24dp"android:scaleType="fitXY"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintTop_toBottomOf="@id/tv_text" /><EditTextandroid:id="@+id/et_code"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginStart="24dp"android:layout_marginEnd="8dp"android:textColor="@color/color_222222"android:textSize="16sp"android:hint="@string/enter_image_code"android:paddingTop="10dp"android:paddingBottom="5dp"android:background="@drawable/edittext_bg"android:textCursorDrawable="@drawable/edit_text_cursor"android:textColorHint="@color/color_D5D5D5"android:inputType="text"android:maxLength="4"app:layout_constraintBottom_toBottomOf="@+id/iv_code"app:layout_constraintEnd_toStartOf="@id/iv_code"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="@+id/iv_code" /><Buttonandroid:id="@+id/iv_login"android:layout_width="match_parent"android:layout_height="40dp"android:layout_marginTop="36dp"android:layout_marginBottom="36dp"android:layout_marginStart="36dp"android:layout_marginEnd="36dp"android:background="@drawable/shape_jfrb_login_button"android:textColor="@color/white"android:text="@string/login_confirm"android:textSize="@dimen/sp_16"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/iv_code" /></androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>

三、使用

图形验证码输入弹窗的调用

//图形验证码校验
SMSCheckDialog checkDialog = new SMSCheckDialog(new SMSCheckDialog.SMSCheckCallback() {@Overridepublic void onGetCode() {//短信验证码接口请求成功countdown();}@Overridepublic void onGetCodeFailed(String msg) {runOnUiThread(new Runnable() {@Overridepublic void run() {//短信验证码接口请求失败}});}}, phone,account);checkDialog.show(getSupportFragmentManager(), "SMSCheckDialog");

发送短信验证码成功后等待间隙的60s倒计时文字显示

 private void countdown() {final long count = 60L;Observable.intervalRange(0, 61, 0, 1, TimeUnit.SECONDS).map(new Function<Long, Long>() {@Overridepublic Long apply(Long aLong) throws Exception {return count - aLong;}}).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Long>() {@Overridepublic void onSubscribe(Disposable d) {
//                        addSubscribe(d);}@SuppressLint("SetTextI18n")@Overridepublic void onNext(Long aLong) {mTvGetCode.setText(aLong + "s");mTvGetCode.setEnabled(false);}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {mTvGetCode.setText(getString(R.string.change_phone9));mTvGetCode.setEnabled(true);}});}

附:参考Glide结合Okhttp做cookie管理实现注册需求的图片验证码短信验证码功能

四、完成,Nice!

相关文章:

Glide结合OkHttp保证短信验证接口携带图形验证码接口返回Cookie值去做网络请求

一、实现效果 二、步骤 注意&#xff1a;仅展示核心部分代码 1、导入依赖 api com.github.bumptech.glide:glide:4.10.0 kapt com.github.bumptech.glide:compiler:4.10.0 api com.squareup.okhttp3:okhttp:3.11.0 api com.squareup.okhttp3:logging-interceptor:3.11.02、自…...

怎样用Ajax提交from表单并接收其中的json数据

怎样用Ajax提交表单并接收其中的json数据 需求&#xff1a;实现点击按钮后&#xff0c;数据以表单形式提交至服务器&#xff0c;并接收来自服务器的返回数据。过程中页面不刷新。 AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法。AJAX 是与服务器交换数据并…...

【动态规划】LeetCode-746LCR 088.使用最小花费爬楼梯

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…...

Unity 接入TapADN播放广告时闪退 LZ4JavaSafeCompressor

通过跟踪安卓日志&#xff0c;发现报如下错误 Didnt find class "com.tapadn.lz4.LZ4JavaSafeCompressor" 解决方案&#xff1a; 去掉Minify这边的勾选&#xff0c;再打包即可。...

【九】linux下部署frp客户端服务端实践(内网穿透)

linux下部署frp客户端服务端实践 简介&#xff1a; 今天有一个这样的需求&#xff0c;部署在公司内部局域网虚拟机上的服务需要在外网能够访问到&#xff0c;这不就是内网穿透的需求吗&#xff0c;之前通过路由器实现过&#xff0c;现在公司这块路由器不具备这个功能了&#x…...

华为1+x网络系统建设与运维(中级)-练习题2

一.设备命令 LSW1 [Huawei]sys LSW1 同理可得&#xff0c;给所有设备改名 二.VLAN LSW1 [LSW1]vlan ba 10 20 [LSW1]int g0/0/1 [LSW1-GigabitEthernet0/0/1]port link-type trunk [LSW1-GigabitEthernet0/0/1]port trunk allow-pass vlan 10 20 [LSW1-GigabitEthernet0/0/1]in…...

自定义类型-结构体,联合体和枚举-C语言

引言 能看到结构体&#xff0c;说明C语言想必学习的时间也不少了&#xff0c;在之前肯定也学习过基本数据类型&#xff0c;包括整型int&#xff0c;浮点型float等等。可是在日常生活中&#xff0c;想要描述一个事物并没有那么简单。比如&#xff0c;你要描述一本书&#xff0c…...

Windows 安装redis,设置开机自启动

Windows 安装redis,设置开机自启动 文章目录 Windows 安装redis,设置开机自启动下载, 解压到指定目录设置redis密码启动redis服务端停止redis服务端设置自启动 下载, 解压到指定目录 官网地址: https://redis.io/ 安装包下载地址: https://github.com/tporadowski/redis/relea…...

Windows安装Mysql Workbench及常用操作

Mysql Workbench是mysql自带的可视化操作界面&#xff0c;功能是强大的&#xff0c;但界面和navicat比&#xff0c;就是觉得别扭&#xff0c;但其实用惯了也还好&#xff0c;各有特色吧。这里记录一下常用的操作。 官方手册&#xff1a;MySQL Workbench 一、安装 1. 下载 官方…...

【计算机网络】15、NAT、NAPT 网络地址转换、打洞

文章目录 一、概念二、分类&#xff08;主要是传统 NAT&#xff09;2.1 基本 NAT2.2 NAPT 三、访问NAT下的内网设备的方式3.1 多拨3.2 端口转发、DMZ3.3 UPnP IGD、NAT-PMP3.4 服务器中转&#xff1a;frp 内网穿透3.4.1 NAT 打洞3.4.2 NAT 类型与打洞成功率3.4.2.1 完全圆锥形 …...

【送书活动三期】解决docker服务假死问题

工作中使用docker-compose部署容器&#xff0c;有时候会出现使用docker-compose stop或docker-compose down命令想停掉容器&#xff0c;但是依然无法停止或者一直卡顿在停止中的阶段&#xff0c;这种问题很让人头疼啊&#xff01; 目录 问题描述问题排查问题解决终极杀招-最粗暴…...

【每日一题】拼车+【差分数组】

文章目录 Tag题目来源解题思路方法一&#xff1a;差分 写在最后 Tag 【差分数组】【数组】【2023-12-02】 题目来源 1094. 拼车 解题思路 本题朴素的解题思路是统计题目中提到的每一个站点的车上人数&#xff0c;如果某个站点的车上人数大于车上的座位数直接返回 false&…...

【开源】基于JAVA的农村物流配送系统

项目编号&#xff1a; S 024 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S024&#xff0c;文末获取源码。} 项目编号&#xff1a;S024&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2…...

7、Jenkins+Nexus3+Docker+K8s实现CICD

文章目录 基本环境配置一、Jenkins安装必要插件二、Jenkins系统配置三、新建流水线四、在项目工程里添加Jenkinsfile、deploy.yml五、在项目工程里添加Dockerfile在这里插入图片描述 总结 提示&#xff1a;本章主要记录各基本环境搭建好后如何配置Jenkins流水线部署微服务到K8s…...

解决git action发布失败报错:Error: Resource not accessible by integration

现象&#xff1a; 网上说的解决方法都是什么到github个人中心setting里面的action设置里面去找。 可这玩意根本就没有&#xff01; 正确解决办法&#xff1a; 在你的仓库页面&#xff0c;注意是仓库页面的setting里面&#xff1a; Actions> General>Workflow permisss…...

[传智杯 #2 决赛] 补刀

题目描述 UIM 在写程序的空闲玩一款 MOBA 游戏。 当敌方的小兵进入到我方防御塔的范围内&#xff0c;就会持续受到防御塔造成的伤害&#xff1b;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 0 或者更低&#xff0c;就会被击杀。为了获得经验&#xff0c;UIM 希望在防…...

C语言:求Sn=a+aa+aaa+aaaa+……(n个a)之值,其中a表示一个数字,n表示a的位数,n由键盘录入。

分析&#xff1a; 在主函数 main 中&#xff0c;程序首先定义四个整型变量 a、n、i 和 sn&#xff0c;并初始化 a、n 和 i 的值&#xff0c;其中 sn 用于记录数列的和。然后使用 scanf 函数从标准输入中读取用户输入的两个整数 a 和 n。 接下来&#xff0c;程序通过 while …...

【nlp】4.1 fasttext工具介绍(文本分类、训练词向量、词向量迁移)

fasttext工具介绍与文本分类 1 fasttext介绍1.1 fasttext作用1.2 fasttext工具包的优势1.3 fasttext的安装1.4 验证安装2 fasttext文本分类2.1 文本分类概念2.2 文本分类种类2.3 文本分类的过程2.4 文本分类代码实现2.4.1 获取数据2.4.2 训练集与验证集的划分2.4.3 训练模型2.4…...

Spring中的事务管理

1 基本概念 事务&#xff1a;将一组操作抽象成一个不可再分的单位&#xff0c;这组操作可以有很多个&#xff0c;但是它们要么就全部都执行成功&#xff0c;这时算作事务执行成功&#xff1b;要不其中有操作执行失败&#xff0c;则其余操作都视为执行失败&#xff0c;这时候需…...

量子光学的进步:光子学的“下一件小事”

量子光学是量子力学和光学交叉领域中发展迅速的一门学科&#xff0c;探索光的基本特性及其与物质在量子水平上的相互作用。通过利用光的独特特性&#xff0c;量子光学为通信、计算、密码学和传感等各个学科的变革性进步铺平了道路。 如今&#xff0c;量子光学领域的研究人员和工…...

微信小程序获取定位显示在百度地图上位置出现偏差

项目场景&#xff1a; 背景&#xff1a; 微信小程序端获取手机定位坐标&#xff0c;以及正确展示位置通过详细地址解析为定位坐标显示在小程序端以及PC后台小程序获取的地理坐标与百度地图坐标相互转化 相关知识 目前国内主要有以下三种坐标系&#xff1a; WGS84&#xff1a…...

【LeetCode 0170】【哈希】两数之和(3) 数据结构设计

https://leetcode.com/problems/two-sum-iii-data-structure-design/ 描述 Design and implement a TwoSum class. It should support the following operations: add and find. add(input) – Add the number input to an internal data structure. find(value) – Find if …...

005、简单页面-容器组件

之——布局 目录 之——布局 杂谈 正文 1.布局基础知识 2.Column 3.Row 4.实践 杂谈 布局容器组件。 一个丰富的页面需要很多组件组成&#xff0c;那么&#xff0c;我们如何才能让这些组件有条不紊地在页面上布局呢&#xff1f;这就需要借助容器组件来实现。 容器组件是…...

stm32中断调用流程

USART1_IRQHandler(void)(中断服务函数) -> HAL_UART_IRQHandler(UART_HandleTypeDef *huart)(中断处理函数) -> UART_Receive_IT(UART_HandleTypeDef *huart) (接收函数) -> HAL_UART_RxCpltCallback(huart);(中断回调函数) HAL_UART_IRQHandler(UART_HandleTypeDef…...

18487.1 - 2015 电动汽车充电系统标准 第1部分 关键点梳理

一、部分知识介绍 1、连接方式 使用电缆和连接器将电动汽车接入电网&#xff08;电源&#xff09;的方法。 1.1、连接方式A 1.2、连接方式B 1.3、连接方式C 2、电动汽车控电设备 2.1、按照输出电压分类 1&#xff09;交流 单相 220V&#xff0c;三相 380V. 2&#xff09…...

WPF实战项目十八(客户端):添加新增、查询、编辑功能

1、ToDoView.xmal添加引用&#xff0c;添加微软的行为类 xmlns:i"http://schemas.microsoft.com/xaml/behaviors" 2、给项目添加行为 <i:Interaction.Triggers><i:EventTrigger EventName"MouseLeftButtonUp"><i:InvokeCommandAction Com…...

职位招聘管理与推荐系统Python+Django网页界面+协同过滤推荐算法

一、介绍 职位招聘管理与推荐系统。本系统使用Python作为主要开发语言&#xff0c;以WEB网页平台的方式进行呈现。前端使用HTML、CSS、Ajax、BootStrap等技术&#xff0c;后端使用Django框架处理用户请求。 系统创新点&#xff1a;相对于传统的管理系统&#xff0c;本系统使用…...

C#文件流二进制文件的读写

目录 一、BinaryWriter类 二、BinaryReader类 三、示例 1.源码 2.生成效果 二进制文件的写入与读取主要是通过BinaryWriter类和BinaryReader类来实现的。 一、BinaryWriter类 BinaryWriter类以二进制形式将基元类型写入流&#xff0c;并支持用特定的编码写入字符串&#…...

如何正确选择爬虫采集接口和API?区别在哪里?

在信息时代&#xff0c;数据已经成为了一个国家、一个企业、一个个人最宝贵的资源。而爬虫采集接口则是获取这些数据的重要手段之一。本文将从以下八个方面进行详细讨论&#xff1a; 1.什么是爬虫采集接口&#xff1f; 2.爬虫采集接口的作用和意义是什么&#xff1f; 3.爬虫…...

k8s部署jenkins

1.先决条件 1.因为国内的容器镜像加速器无法实时更新docker hub上的镜像资源.所以可以自己进行jenkins的容器镜像创建,. 2.这里用到了storageClass k8s的动态制备.详情参考: k8s-StoargClass的使用-基于nfs-CSDN博客 3.安装docker服务.(用于构建docker image) 2.构建jenki…...