残念ながら、Android向けのCookieマネージャーは多数あります。 HttpURLConnection
のCookieは_Java.net.CookieManager
_によって維持され、WebView
のCookieは_Android.webkit.CookieManager
_によって維持されます。これらのCookieリポジトリは独立しており、手動で同期する必要があります。
私のアプリはHttpURLConnections
とWebViews
の両方を使用しています(これはネイティブHTMLハイブリッドです)。当然、両方にすべてのCookieを共有させたいので、全体で透過的なセッションを行います。
具体的に:
簡単に言えば、私は双方向同期を探しています。または、両方が同じcookieリポジトリを使用するようにすることもできます。両方が同時にアクティブであると想定できます(異なるタブ上など)。
質問:
両方が同じcookieリポジトリを使用する方法はありますか?
そうでない場合、手動同期を行うために推奨される方法は何ですか?正確に同期するタイミングと方法は?
関連質問:これは 質問 で同様の問題に対処していますが、一方向の同期(HttpURLConnection- > WebView)。
これまでの私の最高のアイデア:手動での同期は避けたいので、両方に同じリポジトリを使用させる方法を考えてみました。多分私は_Java.net.CookieManager
_を拡張する独自のコアハンドラーを作成できます。 Java.net.CookieHandler.setDefault()
を使用して、コアCookieハンドラーとして設定します。その実装は、_Android.webkit.CookieManager
_ハンドラーインスタンスのプロキシになります(すべての関数について、Webkitマネージャーにアクセスします)。
私は自分のアイデアを実装しました。それは実際にはかなりクールです。すべてのリクエストをWebViewsのWebkit Java.net.CookieManager
に転送するAndroid.webkit.CookieManager
の独自の実装を作成しました。つまり、同期は不要で、HttpURLConnectionはsameCookieストレージをWebViewとして使用します。
クラスWebkitCookieManagerProxy:
import Java.io.IOException;
import Java.net.CookieManager;
import Java.net.CookiePolicy;
import Java.net.CookieStore;
import Java.net.URI;
import Java.util.Arrays;
import Java.util.List;
import Java.util.Map;
public class WebkitCookieManagerProxy extends CookieManager
{
private Android.webkit.CookieManager webkitCookieManager;
public WebkitCookieManagerProxy()
{
this(null, null);
}
public WebkitCookieManagerProxy(CookieStore store, CookiePolicy cookiePolicy)
{
super(null, cookiePolicy);
this.webkitCookieManager = Android.webkit.CookieManager.getInstance();
}
@Override
public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException
{
// make sure our args are valid
if ((uri == null) || (responseHeaders == null)) return;
// save our url once
String url = uri.toString();
// go over the headers
for (String headerKey : responseHeaders.keySet())
{
// ignore headers which aren't cookie related
if ((headerKey == null) || !(headerKey.equalsIgnoreCase("Set-Cookie2") || headerKey.equalsIgnoreCase("Set-Cookie"))) continue;
// process each of the headers
for (String headerValue : responseHeaders.get(headerKey))
{
this.webkitCookieManager.setCookie(url, headerValue);
}
}
}
@Override
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException
{
// make sure our args are valid
if ((uri == null) || (requestHeaders == null)) throw new IllegalArgumentException("Argument is null");
// save our url once
String url = uri.toString();
// prepare our response
Map<String, List<String>> res = new Java.util.HashMap<String, List<String>>();
// get the cookie
String cookie = this.webkitCookieManager.getCookie(url);
// return it
if (cookie != null) res.put("Cookie", Arrays.asList(cookie));
return res;
}
@Override
public CookieStore getCookieStore()
{
// we don't want anyone to work with this cookie store directly
throw new UnsupportedOperationException();
}
}
アプリケーションの初期化時にこれを実行して使用:
Android.webkit.CookieSyncManager.createInstance(appContext);
// unrelated, just make sure cookies are generally allowed
Android.webkit.CookieManager.getInstance().setAcceptCookie(true);
// magic starts here
WebkitCookieManagerProxy coreCookieManager = new WebkitCookieManagerProxy(null, Java.net.CookiePolicy.ACCEPT_ALL);
Java.net.CookieHandler.setDefault(coreCookieManager);
テスト
私の最初のテストは、これがうまく機能していることを示しています。 WebViewsとHttpURLConnectionの間で共有されるCookieを確認します。問題が発生しないことを願っています。これを試して問題を見つけたら、コメントしてください。