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;

    @Override
    public 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));
    }

    @Override
    public boolean isManifestParsingEnabled() {
        return false;
    }

    /**
     * Cookie管理类
     */
    private class CookiesManager implements CookieJar {

        //保存每个url的cookie
        private HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();

        //上一个请求url
        private HttpUrl url;

        @Override
        public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
            //保存链接的cookie
            cookieStore.put(httpUrl, list);
            //保存上一次的url,供给下一次cookie的提取。
            url = httpUrl;
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl httpUrl) {

            //加载上一个链接的cookie
            List<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;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(STYLE_NORMAL, R.style.CustomDialog);
        setCancelable(false);
    }

    @Nullable
    @Override
    public 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() {
            @Override
            public void onClick(View v) {
            	//加载图形验证码
                loadCapture();
            }
        });
        loadCapture();
        final EditText etCode = view.findViewById(R.id.et_code);
        ivDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            	//关闭图形验证码弹窗
                dismiss();
            }
        });
        Button ivSure = view.findViewById(R.id.iv_login);
        ivSure.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (TextUtils.isEmpty(etCode.getText().toString())) {
                    RnToast.showToast(getContext(),"请输入图形验证码");
                    return;
                }
                //图形验证码输入完成后,发送短信验证码请求
                new Thread(new Runnable() {
                    @Override
                    public 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() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.d("mylog_sms: ","短信验证码接口请求失败"+e.toString());
            }

            @Override
            public 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.ConstraintLayout
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="@drawable/shape_white_8">

        <ImageView
            android: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" />

        <TextView
            android: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" />

        <ImageView
            android: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" />

        <EditText
            android: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" />
        <Button
            android: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() {
        @Override
        public void onGetCode() {
            //短信验证码接口请求成功
            countdown();
        }

        @Override
        public void onGetCodeFailed(String msg) {
            runOnUiThread(new Runnable() {
                @Override
                public 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>() {
                    @Override
                    public Long apply(Long aLong) throws Exception {
                        return count - aLong;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Long>() {
                    @Override
                    public void onSubscribe(Disposable d) {
//                        addSubscribe(d);
                    }

                    @SuppressLint("SetTextI18n")
                    @Override
                    public void onNext(Long aLong) {
                        mTvGetCode.setText(aLong + "s");
                        mTvGetCode.setEnabled(false);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        mTvGetCode.setText(getString(R.string.change_phone9));
                        mTvGetCode.setEnabled(true);
                    }
                });
    }

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

四、完成,Nice!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

非应届生简历模板(13篇)

无论您是职场新人还是转行求职者&#xff0c;一份出色的简历都是获得心仪岗位的关键。本文为大家精选了13篇专业的非应届生简历模板&#xff0c;无论您的经验如何&#xff0c;都可以灵活参考借鉴&#xff0c;提升自己的简历质量。让简历脱颖而出&#xff0c;轻松斩获心仪职位&a…

【【FPGA 之 MicroBlaze定时器中断实验】】

FPGA 之 MicroBlaze定时器中断实验 AXI Timer 具有 AXI 总线接口&#xff0c;能够产生不同时间周期和占空比的时钟、脉冲产生电路、产生与时间有关的中断和用于电机控制的脉宽调制信号。 AXI Timer IP 核提供了一个 AXI4 Lite 接口用于与处理器通信&#xff1b;它内部有两个可…

OpenCV-Python:计算机视觉框架

1.背景 俗话说“工欲善其事必先利其器”&#xff0c;想要学好计算机视觉&#xff0c;需要借助于相关的计算机视觉库&#xff0c;这样在进行学习的时候可以达到事半功倍的效果。 2.早期计算机视觉框架概述 Matlab的最早历史可以追溯到1970年&#xff0c;开始是作为数据处理工…

VL53-400激光测距传感器

一、产品简介 先由激光二极管对准目标发射激光脉冲。经目标反射后激光向各方向散射。部分散射光返回到传感器接收器&#xff0c;被光学系统接收后成像到雪崩光电二极管上。雪崩光电二极管是一种内部具有放大功能的光学传感器&#xff0c;因此它能检测极其微弱的光信号。记录并…

数据库设计实践:粒度的理解与应用示例

粒度是描述数据存储和表示的详细程度。在数据库设计中&#xff0c;理解和正确选择粒度是非常重要的&#xff0c;因为它直接影响到数据的存储效率、查询性能和数据分析的灵活性。 文章目录 粒度的类型&#xff1a;案例粒度选择的考虑因素实际应用 粒度的类型&#xff1a; 细粒度…

UI自动化Selenium find_elements和find_element的区别

# 如果获取的element是list&#xff0c;那么需要用find_elements方法&#xff1b;此方法会返回list&#xff0c;然后使用len() 方法&#xff0c;计算对象的个数&#xff1b; # find_element方法返回的不是list对象&#xff0c;所以导致没办法计算对象个数 # 1.返回值类型不同…

智慧工地一体化解决方案(里程碑管理)源码

智慧工地为管理人员提供及时、高效、优质的远程管理服务&#xff0c;提升安全管理水平&#xff0c;确保施工安全提高施工质量。实现对人、机、料、法、环的全方位实时监控&#xff0c;变被动“监督”为主动“监控”。 一、建设背景 施工现场有数量多、分布广&#xff0c;总部统…

2023.11.30 关于 MyBatis 动态 SQL 的使用

目录 引言 if 标签 trim 标签 where 标签 set 标签 foreach 标签 引言 动态 sql 是 MyBatis 的强大特性之一允许你根据输入的参数动态地构建 sql 语句从而在运行时根据不同的条件生成不同的 sql 核心思想 基于提供的数据和条件&#xff0c;能够修改、增加、删除 sql…

极智芯 | 解读国产AI算力 昆仑芯产品矩阵

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 解读国产AI算力 昆仑芯产品矩阵。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq 昆仑芯来源于百度,2018 年…

用CHAT 写一份销售人员激励方案

问CHAT &#xff1a;写一份销售人员早会激励方案 CHAT回复&#xff1a; 标题&#xff1a;鼓舞斗志&#xff0c;迎接新的一天 -- 销售人员早会激励方案 一、会议的氛围设定&#xff1a; 深呼吸&#xff0c;准备开始一天的事业&#xff1a;清晨的阳光&#xff0c;温暖而明亮&…

redis------在java中操作redis

Redis&#xff08;非关系型数据库&#xff09;简介 redis下载 点击即可进入redis中文网进行下载 百度网盘windows版本 提取码 DMH6 redis主要特点 基于内存存储&#xff0c;读写性能高 适合存储热点数据&#xff08;热点商品、资讯、新闻&#xff09; 企业应用广泛 redis不同…

【代码】CNN-GRU-Attention基于卷积神经网络和门控循环单元网络结合注意力机制的多变量回归预测

程序名称&#xff1a;CNN-GRU-Attention基于卷积神经网络和门控循环单元网络结合注意力机制的多变量回归预测 实现平台&#xff1a;matlab 代码简介&#xff1a;为更准确地预测&#xff0c;提出基于注意力机制的CNN-G&#xff32;U预测模型。该模型主要借助一维卷积单元提取数…

Filebeat使用指南

Filebeat介绍主要优势主要功能配置日志的解析Kibana中设置日志解析安装步骤安装Filebeat安装监控通过prometheus监控 Filebeat和Logstash的主要区别 Filebeat介绍 Filebeat是使用Golang实现的轻量型日志采集器&#xff0c;也是Elasticsearch stack的一员。它可以作为一个agent…

全网关键词采集,免费关键词采集软件使用方法

网站的SEO优化已经成为企业提升在线可见性的不二选择。而关键词的选择和使用则是SEO优化的核心。本文将专心分享关键词采集的正确用法&#xff0c;助您在SEO的道路上掌握正确的方向。 关键词采集&#xff1a;SEO的基础 让我们明确关键词采集的重要性。在搜索引擎的世界里&…

计算机组成学习-数据的表示和运算总结

1、进制与编码 1.1 进位计数法 常用的进位计数法有十进制、二进制、八进制、十六进制等。十六进制每个 数位可取0〜9、A、B、C、D、E、F中的任意一个&#xff0c;其中A、B、C、D、E、F分别表示 10〜15。 八进制数字通常以前缀 "0"&#xff08;零&#xff09;加上数…

【openssl】Window系统如何编译openssl

本文主要记录如何编译出windows版本的openss的lib库 1.下载openssl&#xff0c;获得openssl-master.zip。 a.可以通过github&#xff08;网址在下方&#xff09;上下载最新的代码、今天是2023.12.1我用的master版本&#xff0c;下载之后恭喜大侠获得《openssl-master.zip》 …

Redis高可用集群架构

高可用集群架构 哨兵模式缺点 主从切换阶段&#xff0c; redis服务不可用&#xff0c;高可用不太友好只有单个主节点对外服务&#xff0c;不能支持高并发单节点如果设置内存过大&#xff0c;导致持久化文件很大&#xff0c;影响数据恢复&#xff0c;主从同步性能 高可用集群…

【开源】基于JAVA语言的考研专业课程管理系统

项目编号&#xff1a; S 035 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S035&#xff0c;文末获取源码。} 项目编号&#xff1a;S035&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高…

Python练习题(一)

&#x1f4d1;前言 本文主要是【Python】——Python练习题的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&am…

vscode 里怎么自动提示 webpack 配置项?

webpack 的配置项非常多&#xff0c;容易忘记&#xff0c;能自动提示很有用&#xff0c;就是在配置文件里面添加下面代码 // 下面这行用于 vscode 中智能化自动提示 webpack 配置项 /** type {import(webpack).Configuration} */