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)