背景

在使用鸿洋大神的玩Android网站开放的api开发android app时,使用Retrofit请求登录api,需要保存Cookie以备其他需要登陆后才能操作的api使用。

自定义拦截器实现持久化Cookie

首先定义响应拦截器,该拦截器实现从response获取set-cookie字段的值,并将其保存在本地。

public class SaveCookiesInterceptor implements Interceptor {

private static final String COOKIE_PREF = "cookies_prefs";

private Context mContext;

protected SaveCookiesInterceptor(Context context) {

mContext = context;

}

@Override

public Response intercept(Chain chain) throws IOException {

Request request = chain.request();

Response response = chain.proceed(request);

//set-cookie可能为多个

if (!response.headers("set-cookie").isEmpty()) {

List cookies = response.headers("set-cookie");

String cookie = encodeCookie(cookies);

saveCookie(request.url().toString(), request.url().host(), cookie);

}

return response;

}

/**

* 整合cookie为唯一字符串

*/

private String encodeCookie(List cookies) {

StringBuilder sb = new StringBuilder();

Set set = new HashSet<>();

for (String cookie : cookies) {

String[] arr = cookie.split(";");

for (String s : arr) {

if (set.contains(s)) {

continue;

}

set.add(s);

}

}

for (String cookie : set) {

sb.append(cookie).append(";");

}

int last = sb.lastIndexOf(";");

if (sb.length() - 1 == last) {

sb.deleteCharAt(last);

}

return sb.toString();

}

/**

* 保存cookie到本地,这里我们分别为该url和host设置相同的cookie,其中host可选

* 这样能使得该cookie的应用范围更广

*/

private void saveCookie(String url, String domain, String cookies) {

SharedPreferences sp = mContext.getSharedPreferences(COOKIE_PREF, Context.MODE_PRIVATE);

SharedPreferences.Editor editor = sp.edit();

if (TextUtils.isEmpty(url)) {

throw new NullPointerException("url is null.");

} else {

editor.putString(url, cookies);

}

if (!TextUtils.isEmpty(domain)) {

editor.putString(domain, cookies);

}

editor.apply();

}

/**

* 清除本地Cookie

*

* @param context Context

*/

public static void clearCookie(Context context) {

SharedPreferences sp = context.getSharedPreferences(COOKIE_PREF, Context.MODE_PRIVATE);

sp.edit().clear().apply();

}

}

然后定义请求拦截器,如果该请求存在cookie,则为其添加到Header的Cookie中。

public class AddCookiesInterceptor implements Interceptor {

private static final String COOKIE_PREF = "cookies_prefs";

private Context mContext;

public AddCookiesInterceptor(Context context) {

mContext = context;

}

@Override

public Response intercept(Chain chain) throws IOException {

Request request = chain.request();

Request.Builder builder = request.newBuilder();

String cookie = getCookie(request.url().toString(), request.url().host());

if (!TextUtils.isEmpty(cookie)) {

builder.addHeader("Cookie", cookie);

}

return chain.proceed(builder.build());

}

private String getCookie(String url, String domain) {

SharedPreferences sp = mContext.getSharedPreferences(COOKIE_PREF, Context.MODE_PRIVATE);

if (!TextUtils.isEmpty(url) && sp.contains(url) && !TextUtils.isEmpty(sp.getString(url, ""))) {

return sp.getString(url, "");

}

if (!TextUtils.isEmpty(domain) && sp.contains(domain) && !TextUtils.isEmpty(sp.getString(domain, ""))) {

return sp.getString(domain, "");

}

return null;

}

}

最后将这两个拦截器设置到OkHttpClient

OkHttpClient client = builder.addInterceptor(new AddCookiesInterceptor(context))

.addInterceptor(new SaveCookiesInterceptor(context))

.build();

Retrofit retrofit = new Retrofit.Builder()

.baseUrl(Constant.API_BASE)

.addConverterFactory(GsonConverterFactory.create())

.client(client)

.build();

实际中的问题

在登录后保存了Cookie,但是请求我的收藏时,第一次是可以得到的,第二次则提示需要登录。输出保存的Cookie内容才发现其内容改变了。于是,将请求登录时只添加SaveCookiesInterceptor,其他请求只添加AddCookiesInterceptor。解决问题。

完整项目

android自动登录简书,Android 自动登录——持久化Cookie相关推荐

  1. android自动登录简书,Android开发之简单登录界面

    用户界面基础 Android系统的四大组件分别是活动(Activity).服务(Service).广播接收器(Broadcast Receiver).内容提供器(Content Provider). ...

  2. android 读写文件 简书,Android 中的文件操作

    Android 文件操作 概述 Android 中的文件操作主要涉及到两个部分,一个是内部存储的读写,一个是外部存储的读写两者的主要区别如下表: 内部存储 外部存储 始终可用 它并非始终可用,因为用户 ...

  3. android自动登录简书,android 手机号实现登录功能

    先看看效果 image.png 我的这个登录功能是手机号和密码都已经在后台数据库有存储的,所以是直接登录. 重点有三个: 1.账号密码的存储,实现自动登录: 2.网络通信: 3.密码一定要Md5加密之 ...

  4. android 辅助服务 简书,Android AccessibilityService使用

    测试demo主要使用了Android 的无障碍辅助服务(AccessibilityService),主要注意是 1. 开启服务,绑定目标app的监听(demo中根据包命绑定了体积计算的app),需要在 ...

  5. android 存储方式简书,Android的多种数据存储方式

    1. 简介 作为一个完整的应用程序,数据存储操作是必不可少的.现在Android的离线缓存就是通过网络良好状态时将从服务器收到的数据保存到本地.Android系统中主要提供了3种方式进行数据存储,分别 ...

  6. android权限适配 简书,Android动态权限适配

    最近APP里面要添加动态权限,网上找了不少例子并经过一定的测试,基本流程有了一定的认识,需要注意的地方记录下来以备以后查阅. 一 各大手机厂商的适配 依据各大手机Rom的不同表现,可以分为三种不同的模 ...

  7. android运行过程简书,Android系统的启动流程

    Android系统有哪些进程 在Linux系统启动时,会读取init.rc,里面配置了一些需要启动的进程.注意:SystemServer进程不在init.rc里,因为SystemServer进程是由z ...

  8. android 开发环境简书,Android Studio 开发环境快速搭建

    目录 - 1.下载JDK.AS - 1.1 JDK下载 - 1.2 AS下载 - 1.3 百度云资源统一下载 - 2.安装JDK - 3.配置JDK及JAVA的环境 - 3.1 打开系统环境 - 3. ...

  9. android四大组件 简书,android四大组件

    android有四大组件,分别是Activity, Service(服务),Content Provider(内容提供者),BoadcastReceiver广播接收器. Activity 一个Acti ...

最新文章

  1. setup hadoop 1.2.1 on Mac
  2. 解决 vue路由跳转到新页面底部而不是顶部和后退到首页就不让他继续后退了
  3. 重磅!!面试季--最新面试题总结出厂,附题解,后期持续分享!
  4. Windows 8.1 build 9369 简单安装测试了一下
  5. Opencv imshow显示不出来图片
  6. php门面理解,php 门面模式(外观模式)
  7. 鸿蒙OS的指纹储存在哪里,鸿蒙OS发布以后,我们去哪里学习?
  8. ubuntu文件编码转换
  9. 常用集合(ArrayList、Hashset、HashMap)的用法(会一直更新)
  10. SpringCloud之Ribbon源码分析(一)
  11. vb.net 教程 11-1 打印组件 5 PrintPreviewDialog
  12. vue使用echarts全国地图
  13. 手把手教大家搭建微信公众号查题
  14. 【深度学习】目标检测综述
  15. Visual Paradigm 如何清除系统代理设置
  16. 快速清除字符串边上的空格
  17. 我的新版edge插件推荐!!!
  18. 2023最新UI拉拉米抢单发单系统源码/二开带教程/放量功能
  19. 简单聊一聊中国的房地产
  20. 蚂蚁开放平台开发者专场(上海站)欢迎参加!

热门文章

  1. base64模块的b64encode函数
  2. 第一代电子计算机采用的物理器,第一章 计算机基础知识
  3. html画布设计,10个会让你惊叹不已的HTML5画布(canvas)技术应用
  4. 编码、解码、总结大全
  5. Windows 平台部署前后端分离项目
  6. 海思视频和QT的Colorkey显示模式
  7. 电商Banner设计背后的12个人性的秘密
  8. CSS动画 图片或者文字上下来回循环上下移动
  9. 基于SpringBoot开发的商城后台管理系统
  10. msvcp140.dll丢失VCRUNTIME140_.dll丢失的解决办法