[如何在Webview和Retrofit2 Okhttp3之间共享cookie

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[如何在Webview和Retrofit2 Okhttp3之间共享cookie相关的知识,希望对你有一定的参考价值。

我有一个有2个请求的网站:

首先是要看到装有配料的篮子(无需登录)

GET https://www.ah.nl/mijnlijst2

第二个是将商品插入购物篮的请求。

POST https://www.ah.nl/common/api/basket/v2/add
{
    "items": [{
        "quantity": 1,
        "id": 395948
    }]
}

在我的应用程序中,我已完成3件事:

  1. 使用隐藏的网络视图初始化cookie:

    initializeWebView(binding.webView, "https://www.ah.nl/mijnlijst2")
    
    var myCookie = ""
    
    @SuppressLint("javascriptInterface", "SetJavaScriptEnabled")
    fun initializeWebView(webView: WebView, url: String?) {
        val settings = webView.settings
        settings.javaScriptEnabled = true
        settings.builtInZoomControls = false
        settings.setGeolocationEnabled(true)
        settings.setAppCacheEnabled(false)
        settings.loadsImagesAutomatically = true
        webView.webViewClient = WebViewClient()
        webView.loadUrl(url)
    
        webView.webViewClient = object : WebViewClient() {
    
            override fun onPageFinished(webView: WebView?, url: String) {
                super.onPageFinished(webView, url)
    
                val syncManager =
                    CookieSyncManager.createInstance(webView?.context)
                val cookieManager: CookieManager = CookieManager.getInstance()
                cookieManager.setAcceptThirdPartyCookies(webView,true)
    
                if (cookieManager.getCookie(url)!= null) {
                    val cookie: String = cookieManager.getCookie(url)
                    myCookie = cookie
                    Timber.d("Cookie = $myCookie")
                }
    
                syncManager.sync()
            }
        }
    
        webView.loadUrl(url)
    }
    

2:插入成分:

val response = api.insertIngredient(WebViewManager.myCookie, ingredients).execute()

interface AHApi {

    @Headers(
        "content-type: application/json; charset=utf-8",
        "accept-encoding: gzip, deflate, br"
    )
    @POST("common/api/basket/v2/add")
    fun insertIngredient(
        @Header("cookie") cookie: String,
        @Body ingredients: AhIngredientRequest
    ): Call<ResponseBody>
}

data class AhIngredientRequest(

    @Expose
    @SerializedName("items")
    val items: List<AhItem>
)

data class AhItem(

    @SerializedName("id")
    var id: Long = 0L,

    @SerializedName("quantity")
    var quantity: Long = 1L
)

@Provides
@Singleton
fun provideAHApi(context: Context): AHApi{
    val interceptor = HttpLoggingInterceptor()
    if (BuildConfig.DEBUG) {
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
    } else {
        interceptor.setLevel(HttpLoggingInterceptor.Level.NONE)
    }

    val timeout = 30L
    val client: OkHttpClient = OkHttpClient.Builder()
        .readTimeout(timeout, TimeUnit.SECONDS)
        .writeTimeout(timeout, TimeUnit.SECONDS)
        .connectTimeout(timeout, TimeUnit.SECONDS)
        .followRedirects(false)
        .build()

    val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(context.getString(R.string.ah_api))
        .addConverterFactory(MoshiConverterFactory.create().asLenient())
        .client(client)
        .build()
    return retrofit.create(AHApi::class.java)
}
  1. 启动Web视图中的项目列表:

    class WebviewFragment : Fragment() {
    
    private lateinit var binding: FragmentWebviewBinding
    
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val rootView = inflater.inflate(R.layout.fragment_webview, container, false)
        binding = DataBindingUtil.bind(rootView)!!
    
        WebViewManager.initializeWebView(binding.webView, "https://www.ah.nl/mijnlijst2")
    
        return rootView
    }
    }
    
    • OkHttp3响应返回200 OK。
    • WebView保持为空,0个项目。我希望插入的项目在其中,因为我与setAcceptThirdPartyCookies共享了我的cookie。

    • 但是:当我第一次手动添加成分时,然后点击购物清单然后回到我的应用并再次加载webview,从这一刻开始一切正常。

  2. 因此看来,通过转到]手动初始化cookie>

您还需要将cookieManager设置为Retrofit HTTP客户端(OkHttp)。

[您可以使用JavaNetCookieJar程序包中的JavaNetCookieJar进行此操作,该程序包是委派给okhttp-urlconnection的包装类:

okhttp-urlconnection
答案

您还需要将cookieManager设置为Retrofit HTTP客户端(OkHttp)。

以上是关于[如何在Webview和Retrofit2 Okhttp3之间共享cookie的主要内容,如果未能解决你的问题,请参考以下文章

使用 RxJava2 和 Retrofit2 时如何访问响应头?

Retrofit2源码解读

如何使用 Retrofit2 和 GSON 转换器解决“古怪”的 JSON API

如何在对象 Gson/Retrofit2 中获取字符串

Retrofit2:如何在具有不同字段名称的对象中接收 JSON 响应?

如何在Android上通过retrofit2调用带有Cognito Credentials的API网关?