100
多位经验丰富的开发者参与,在 Github 上得到了近1000
个star
的全栈全平台开源项目想了解或参与吗?
项目地址:https://github.com/cachecats/coderivercss
其实同步登陆状态就是把登陆后服务器返回的 token
、userId
等登陆信息传给H5网页,在发送请求时将必要的校验信息带上。只不过纯H5开发是本身有一个登陆页,登陆以后保存在 Cookie 或其余地方;混合开发中H5网页本身不维护登陆页,而是由原生维护,打开 webview 时将登陆信息传给网页。html
实现的方法有不少,能够用原生与 JS 的通讯机制把登陆信息发送给H5,关于原生与 JS 双向通讯,我以前写了一篇详解文章,不熟悉的同窗能够看看:前端
Android webview 与 js(Vue) 交互vue
这里咱们用另外一种更简单的方法,经过安卓的 CookieManager
把 cookie
直接写入 webview 中。java
这是安卓开发须要作的。android
先说一下步骤:git
UserInfo
,用来接收服务端返回的数据。UserInfo
格式化为 json 字符串存入 SharedPreferences
中。SharedPreferences
取出上一步保存的 UserInfo
。Map
将 UserInfo
以键值对的格式保存起来,便于下一步保存为 cookie。UserInfo
中的信息经过 CookieManager
保存到 cookie 中。看似步骤不少,其实就是获得服务端返回的数据,再经过 CookieManager
保存到 cookie 中这么简单,只不过中间须要作几回数据转换。程序员
咱们按照上面的步骤一步步看代码。UserInfo
对象就不贴了,都是些基本的信息。github
登陆接口请求成功后,会拿到 UserInfo
对象。在成功回调里经过下面一行代码保存 UserInfo
到 SharedPreferences
。web
//将UserData存储到SP SPUtils.putUserData(context, result.getData());
SPUtils 是操做 SharedPreferences 的工具类,代码以下。
包含了保存和取出 UserInfo
的方法(代码中对象名是 UserData),保存时经过 Gson 将对象格式化为 json 字符串,取出时经过 Gson 将 json 字符串格式化为对象。
public class SPUtils { /** * 保存在手机里面的文件名 */ public static final String FILE_NAME = "share_data"; /** * 存储用户信息 * * @param context * @param userData */ public static void putUserData(Context context, UserData userData) { SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); Gson gson = new Gson(); String json = gson.toJson(userData, UserData.class); editor.putString(SPConstants.USER_DATA, json); SharedPreferencesCompat.apply(editor); } /** * 获取用户数据 * * @param context * @return */ public static UserData getUserData(Context context) { SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); String json = sp.getString(SPConstants.USER_DATA, ""); Gson gson = new Gson(); UserData userData = gson.fromJson(json, UserData.class); return userData; } }
这里封装了一个带进度条的 ProgressWebviewActivity
,调用时直接打开这个 Activity 并将网页的 url 地址传入便可。在 Activity 的 onResume
生命周期方法中执行同步 cookie 的逻辑。为何在 onResume
中执行?防止App 从后台切到前台 webview
从新加载没有拿到 cookie,可能放在 onCreate
大多数状况下也没有问题,但放到 onResume
最保险。
@Override protected void onResume() { super.onResume(); Logger.d("onResume " + url); //同步 cookie 到 webview syncCookie(url); webSettings.setJavaScriptEnabled(true); } /** * 同步 webview 的Cookie */ private void syncCookie(String url) { boolean b = CookieUtils.syncCookie(url); Logger.d("设置 cookie 结果: " + b); }
同步操做封装到了 CookieUtils
工具类中,下面是 CookieUtils
的代码:
这个工具类中一共干了三件事,从 SharedPreferences
中取出 UserInfo
,将 UserInfo
封装到 Map 中,遍历 Map 依次存入 cookie。
public class CookieUtils { /** * 将cookie同步到WebView * * @param url WebView要加载的url * @return true 同步cookie成功,false同步cookie失败 * @Author JPH */ public static boolean syncCookie(String url) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { CookieSyncManager.createInstance(MyApplication.getAppContext()); } CookieManager cookieManager = CookieManager.getInstance(); Map<String, String> cookieMap = getCookieMap(); for (Map.Entry<String, String> entry : cookieMap.entrySet()) { String cookieStr = makeCookie(entry.getKey(), entry.getValue()); cookieManager.setCookie(url, cookieStr); } String newCookie = cookieManager.getCookie(url); return TextUtils.isEmpty(newCookie) ? false : true; } /** * 组装 Cookie 里须要的值 * * @return */ public static Map<String, String> getCookieMap() { UserData userData = SPUtils.getUserData(MyApplication.getAppContext()); String accessToken = userData.getAccessToken(); Map<String, String> headerMap = new HashMap<>(); headerMap.put("access_token", accessToken); headerMap.put("login_name", userData.getLoginName()); headerMap.put("refresh_token", userData.getRefreshToken()); headerMap.put("remove_token", userData.getRemoveToken()); headerMap.put("unitId", userData.getUnitId()); headerMap.put("unitType", userData.getUnitType() + ""); headerMap.put("userId", userData.getUserId()); return headerMap; } /** * 拼接 Cookie 字符串 * * @param key * @param value * @return */ private static String makeCookie(String key, String value) { Date date = new Date(); date.setTime(date.getTime() + 3 * 24 * 60 * 60 * 1000)