У меня здесь другой подход, отличающийся от других, и этот подход гарантированно работает, не имея отношения к CookieSyncManager (где вы находитесь во власти семантики, такой как «Обратите внимание, что даже sync () происходит асинхронно»).
По сути, мы переходим к правильному домену, затем выполняем javascript из контекста страницы, чтобы установить куки для этого домена (так же, как и сама страница). Два недостатка этого метода заключаются в том, что может потребоваться дополнительное время приема-передачи из-за дополнительного http-запроса, который вы должны сделать; и если на вашем сайте нет эквивалента пустой страницы, он может высветить любой URL-адрес, который вы загрузили, прежде чем направить вас в нужное место.
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.http.cookie.Cookie;
import android.annotation.SuppressLint;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebViewFragment {
private static final String BLANK_PAGE = "/blank.html"
private CookieSyncManager mSyncManager;
private CookieManager mCookieManager;
private String mTargetUrl;
private boolean mInitializedCookies;
private List<Cookie> mAllCookies;
public WebViewFragment(Context ctx) {
// We are still required to create an instance of Cookie/SyncManager.
mSyncManager = CookieSyncManager.createInstance(ctx);
mCookieManager = CookieManager.getInstance();
}
@SuppressLint("SetJavaScriptEnabled") public void loadWebView(
String url, List<Cookie> cookies, String domain) {
final WebView webView = ...
webView.setWebViewClient(new CookeWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
mInitializedCookies = false;
mTargetUrl = url;
mAllCookies = cookies;
// This is where the hack starts.
// Instead of loading the url, we load a blank page.
webView.loadUrl("http://" + domain + BLANK_PAGE);
}
public static String buildCookieString(final Cookie cookie) {
// You may want to add the secure flag for https:
// + "; secure"
// In case you wish to convert session cookies to have an expiration:
// + "; expires=Thu, 01-Jan-2037 00:00:10 GMT"
// Note that you cannot set the HttpOnly flag as we are using
// javascript to set the cookies.
return cookie.getName() + "=" + cookie.getValue()
+ "; path=" + cookie.getPath()
+ "; domain=" + cookie.getDomain()
};
public synchronized String generateCookieJavascript() {
StringBuilder javascriptCode = new StringBuilder();
javascriptCode.append("javascript:(function(){");
for (final Cookie cookie : mAllCookies) {
String cookieString = buildCookieString(cookie);
javascriptCode.append("document.cookie=\"");
javascriptCode.append(
StringEscapeUtils.escapeJavascriptString(cookieString));
javascriptCode.append("\";");
}
// We use javascript to load the next url because we do not
// receive an onPageFinished event when this code finishes.
javascriptCode.append("document.location=\"");
javascriptCode.append(
StringEscapeUtils.escapeJavascriptString(mTargetUrl));
javascriptCode.append("\";})();");
return javascriptCode.toString();
}
private class CookieWebViewClient extends WebViewClient {
@Override public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (!mInitializedCookies) {
mInitializedCookies = true;
// Run our javascript code now that the temp page is loaded.
view.loadUrl(generateCookieJavascript());
return;
}
}
}
}
Если вы доверяете домену, из которого отправляются файлы cookie, вы можете обойтись без Apache Commons, но вы должны понимать, что это может представлять риск XSS, если вы не будете осторожны.