我终于找到了一个我很满意的解决方案。基本上,我将 cookie 保存在 Shared Preferences 中并从那里获取它们。
这是我对解决方案的建议(扩展 AdvancedWebView 的视图类,也可以是标准的 webview):
public class PersistentCookiesWebView extends AdvancedWebView {
private static String url = "PersistentCookiesWebView";
private static String cookieKey = "";
private static final String COOKIE_STORAGE_KEY_PREFIX = "cskp_";
private static final long COOKIE_MAX_STORAGE_BYTES = 500000;
public PersistentCookiesWebView(Context context) {
super(context);
}
public PersistentCookiesWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PersistentCookiesWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void loadUrl(final String url, String cookieKey) {
this.url = url;
this.cookieKey = cookieKey;
initializeWebView(new WebViewListener() {
@Override
public void onWebViewReady() {
PersistentCookiesWebView.super.loadUrl(url);
}
});
}
@Override
public void loadUrl(final String url) {
this.url = url;
this.cookieKey = getHostName();
initializeWebView(new WebViewListener() {
@Override
public void onWebViewReady() {
PersistentCookiesWebView.super.loadUrl(url);
}
});
}
@Override
public void loadUrl(final String url, final Map<String, String> additionalHttpHeaders) {
this.url = url;
this.cookieKey = getHostName();
initializeWebView(new WebViewListener() {
@Override
public void onWebViewReady() {
PersistentCookiesWebView.super.loadUrl(url, additionalHttpHeaders);
}
});
}
@Override
public void loadUrl(final String url, final boolean preventCaching) {
this.url = url;
this.cookieKey = getHostName();
initializeWebView(new WebViewListener() {
@Override
public void onWebViewReady() {
PersistentCookiesWebView.super.loadUrl(url, preventCaching);
}
});
}
@Override
public void loadUrl(final String url, final boolean preventCaching, final Map<String, String> additionalHttpHeaders) {
this.url = url;
this.cookieKey = getHostName();
initializeWebView(new WebViewListener() {
@Override
public void onWebViewReady() {
PersistentCookiesWebView.super.loadUrl(url, preventCaching, additionalHttpHeaders);
}
});
}
protected void initializeWebView(final WebViewListener webViewListener) {
setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
CookieManager.getInstance().flush();
}
});
setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
saveCookies(null);
return false;
}
});
fetchCookies(new CookieFetchListener() {
@Override
public void onCookiesFetched() {
webViewListener.onWebViewReady();
}
});
}
public void saveCookies(CookieSaveListener cookieSaveListener) {
String storageKey = COOKIE_STORAGE_KEY_PREFIX + cookieKey;
String currentCookieString = CookieManager.getInstance().getCookie(url) + "";
ArrayList<String> currentCookieList = new ArrayList<String>(Arrays.asList(currentCookieString.split(";")));
long cookieBytes = 0;
String newCookies = "";
for(int i = currentCookieList.size() - 1; i >= 0; i--) {
String cookie = currentCookieList.get(i);
try {
cookieBytes = cookieBytes + cookie.getBytes().length;
} catch (Exception e) {
e.printStackTrace();
}
if (cookieBytes < COOKIE_MAX_STORAGE_BYTES) {
newCookies = cookie + ";" + newCookies;
} else {
break;
}
}
PreferencesManager.putString(getContext(), storageKey, newCookies);
if (cookieSaveListener != null) {
cookieSaveListener.onCookiesSaved();
}
}
private void fetchCookies(final CookieFetchListener cookieFetchListener) {
String storageKey = COOKIE_STORAGE_KEY_PREFIX + cookieKey;
String currentCookieString = CookieManager.getInstance().getCookie(url) + "";
String storedCookiesString = PreferencesManager.getString(getContext(), storageKey) + "";
ArrayList<String> storedCookiesList = new ArrayList<String>(Arrays.asList(storedCookiesString.split(";")));
for (String storedCookie : storedCookiesList) {
if(!currentCookieString.contains(storedCookie)) {
CookieManager.getInstance().setCookie(url, storedCookie);
CookieManager.getInstance().setCookie(cookieKey, storedCookie);
}
}
cookieFetchListener.onCookiesFetched();
saveCookies(null);
}
private String getHostName() {
try {
URL aURL = new URL(url);
return aURL.getHost() + "";
} catch (MalformedURLException e) {
e.printStackTrace();
return "";
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.d(getClass().getSimpleName(), "Cookies attempting to save...");
saveCookies(new CookieSaveListener() {
@Override
public void onCookiesSaved() {
Log.d(getClass().getSimpleName(), "Cookies saved!");
}
});
}
interface CookieFetchListener {
void onCookiesFetched();
}
interface CookieSaveListener {
void onCookiesSaved();
}
interface WebViewListener {
void onWebViewReady();
}
}
我希望这对其他人也有用。