Kotlin 如何在Webview和Okhttp3之间共享cookie

Kotlin 如何在Webview和Okhttp3之间共享cookie,kotlin,android-webview,retrofit2,Kotlin,Android Webview,Retrofit2,我有一个包含2个请求的站点: 首先是看到一个包含配料的篮子(无需登录) 第二个是请求在篮子中插入物品。 POST https://www.ah.nl/common/api/basket/v2/add { "items": [{ "quantity": 1, "id": 395948 }] } 在我的应用程序中,我做了3件事: 使用隐藏的Web视图初始化cookie: initializeWebView(binding.webView, "http

我有一个包含2个请求的站点:

首先是看到一个包含配料的篮子(无需登录)

第二个是请求在篮子中插入物品。

POST https://www.ah.nl/common/api/basket/v2/add
{
    "items": [{
        "quantity": 1,
        "id": 395948
    }]
}
在我的应用程序中,我做了3件事:

  • 使用隐藏的Web视图初始化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)
    }
    
    • OkHttp3响应返回200 OK
    • WebView仍为空,0个项目。我希望插入的项目在那里,因为我与
      setAcceptThirdPartyCookies
      共享了我的cookie

    • 但是: 当我第一次手动添加配料时, 然后单击购物列表 然后回到我的应用程序, 然后再次加载webview, 从这一刻起,一切都在运转

    因此,似乎可以通过转到手动初始化cookie

    • 职位

    工作正常,但当我以编程方式执行此操作时,它不会工作。

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

    您可以使用from package完成此操作,from package是一个包装类,委托给:

    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)
    }
    
    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
    }
    }
    
    implementation "com.squareup.okhttp3:okhttp-urlconnection:4.6.0"
    
    val httpClient = OkHttpClient.Builder()
        .cookieJar(JavaNetCookieJar(cookieManager))
        .build()
    val retrofit = Retrofit.Builder()
        .client(httpClient)
        .build()