web-dev-qa-db-ja.com

CookieをHttpURLConnection(Java.net.CookieManager)からWebView(Android.webkit.CookieManager)に渡します

これが古いDefaultHttpClientでどのように機能するかについての回答を見てきましたが、 HttpURLConnectionの良い例はありません

HttpURLConnectionを使用して、Webアプリケーションにリクエストを送信しています。 my Androidアプリケーションの開始時に、CookieHandler.setDefault(new CookieManager())を使用してセッションCookieを自動的に処理します。これは正常に機能しています。

ログイン後のある時点で、WebViewを使用してバックグラウンドでデータをダウンロードするのではなく、HttpURLConnectionを使用してWebアプリケーションからユーザーにライブページを表示します。ただし、以前に確立したのと同じセッションを使用して、ユーザーが再度ログインする必要がないようにします。

セッションを共有できるように、HttpURLConnectionが使用するJava.net.CookieManagerからWebViewが使用するAndroid.webkit.CookieManagerにCookieをコピーするにはどうすればよいですか?

30
quietmint

DefaultHttpClientと比較すると、いくつかの追加手順があります。主な違いは、HTTPURLConnection内の既存のCookieにアクセスする方法です。

  1. CookieHandler.getDefault()を呼び出し、結果を_Java.net.CookieManager_にキャストします。
  2. Cookieマネージャーで、getCookieStore()を呼び出してCookieストアにアクセスします。
  3. Cookieストアで、get()を呼び出して、指定されたURIのCookieのリストにアクセスします。

完全な例を次に示します。

_@Override
protected void onCreate(Bundle savedInstanceState) {
    // Get cookie manager for WebView
    // This must occur before setContentView() instantiates your WebView
    Android.webkit.CookieSyncManager webCookieSync =
        CookieSyncManager.createInstance(this);
    Android.webkit.CookieManager webCookieManager =
        CookieManager.getInstance();
    webCookieManager.setAcceptCookie(true);

    // Get cookie manager for HttpURLConnection
    Java.net.CookieStore rawCookieStore = ((Java.net.CookieManager)
        CookieHandler.getDefault()).getCookieStore();

    // Construct URI
    Java.net.URI baseUri = null;
    try {
        baseUri = new URI("http://www.example.com");
    } catch (URISyntaxException e) {
        // Handle invalid URI
        ...
    }

    // Copy cookies from HttpURLConnection to WebView
    List<HttpCookie> cookies = rawCookieStore.get(baseUri);
    String url = baseUri.toString();
    for (HttpCookie cookie : cookies) {
        String setCookie = new StringBuilder(cookie.toString())
            .append("; domain=").append(cookie.getDomain())
            .append("; path=").append(cookie.getPath())
            .toString();
        webCookieManager.setCookie(url, setCookie);
    }

    // Continue with onCreate
    ...
}
_
17
quietmint

あなたの問題に対するまったく異なるアプローチを提案したいと思います。 Cookieをある場所から別の場所にコピーする(手動同期)の代わりに、HttpURLConnectionとWebViewがsame Cookieストレージを使用するようにします。

これにより、同期の必要が完全になくなります。いずれかで更新されたCookieは、すぐに他方に自動的に反映されます。

これを行うには、すべてのリクエストをWebViewsのWebkit Android.webkit.CookieManagerに転送するJava.net.CookieManagerの独自の実装を作成します。

実装:

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);
    }

    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);
51
talkol

OnCreateの次の1行で、すべてのCookieの問題を魔法のように解決しました。

CookieHandler.setDefault(new CookieManager());

11
Chani