Xamarin.FormのWebViewのクッキー取扱について

新規プロジェクトの作成方法について

 

Xamarin.FormのWebViewについて

Androidはクッキー(cookie)の取得が出来たりできなかったり不安定です。

webview.Cookies = new CookieContainer();

この行があるだけで挙動が不安定でクッキーが取れたり取れなかったりします。
Androidはこの行を処理しないようにする必要が有ります。

iPhoneの場合は通常の通りクッキーを取得できます。次のソースコードをtest.csにコピーします。

using System;
using System.Net;
using Xamarin.Forms;
namespace test
{
    //iPhone・Androidのプラットフォームからクッキーを取得する。
    public interface PfCookies
    {
        CookieContainer CurCookies(string url);
    }
    public class MainPage : ContentPage
    {
        public MainPage()
        {
            WebView webview = new WebView()
            {
                Source = new Uri("https://www.yahoo.co.jp"),
                VerticalOptions = LayoutOptions.FillAndExpand
            };
            //iPhonen & macはクッキーをセットする。
            switch (Device.RuntimePlatform)
            {
                case Device.iOS:
                    webview.Cookies = new CookieContainer();
                    break;
                case Device.macOS:
                    webview.Cookies = new CookieContainer();
                    break;
            }
            webview.Navigated += (s, e) => {
                CookieContainer cookies = new CookieContainer();
                switch (Device.RuntimePlatform)
                {
                    case Device.iOS:
                        //iPhonen & macはWebViewのクッキーを取得する。
                        cookies = webview.Cookies;
                        break;
                    case Device.Android:
                        //Androidは直接はinterfaceよりクッキーを取得する。
                        cookies = DependencyService.Get<PfCookies>().CurCookies(e.Url);
                        break;
                }
                //クッキーをコンソールに列挙する。
                foreach (Cookie c in cookies.GetCookies(new Uri(e.Url)))
                    Console.WriteLine(c.Name + "=" + c.Value);
            };
            Content = webview;
        }
    }
}

cookie Main

次にAndroidのプラットフォームにinterfaceを追加します。
空のクラスを追加します。ファイル名はPfCookies.csとでもしておきましょう。

using System;
using System.Linq;
using System.Net;
using Xamarin.Forms;
using Android.Webkit;
[assembly: Dependency(typeof(test.Droid.DroidCookieStore))]
namespace test.Droid
{
    class DroidCookieStore : PfCookies
    {
        private readonly object _refreshLock = new object();
        public CookieContainer CurCookies(string url)
        {
            return RefreshCookies(url);
        }
        private CookieContainer RefreshCookies(string _url)
        {
            lock (_refreshLock)
            {
                CookieContainer cookies = new CookieContainer();
                //クッキーの取得
                var allCookiesForUrl = CookieManager.Instance.GetCookie(_url);
                if (!string.IsNullOrWhiteSpace(allCookiesForUrl))
                {
                    var cookiePairs = allCookiesForUrl.Split(' ');
                    foreach (var cookiePair in cookiePairs.Where(cp => cp.Contains("=")))
                    {
                        int con = cookiePair.IndexOf("=");
                        cookies.Add(new Uri(_url), new Cookie(cookiePair.Substring(0, con), cookiePair.Substring(con + 1, cookiePair.Length - con - 2)));
                    }
                }
                return cookies;
            }
        }
    }
}

cookie android

これでAndroidとiPhoneそれぞれクッキーを取得できるWebViewが完成しました。

iPhone用のinterfaceは不要ですね!ソースがすっきりしていい感じになりました。