kotlin - 如何在 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 件事:
使用隐藏的 webview 初始化 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)
}
在 webview 中启动项目列表:
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
.但是:当我第一次手动添加一种成分,然后单击购物清单然后返回我的应用程序,并再次加载 webview 时,从这一刻开始一切正常。
因此,似乎通过手动初始化 cookie
有效,但是当我以编程方式执行时,它不会。
解决方案
您还需要将 设置cookieManager
为 Retrofit HTTP 客户端 (OkHttp)。
您可以使用JavaNetCookieJar
from okhttp-urlconnection
package 来执行此操作,这是一个委托给的包装类java.net.CookieHandler
:
implementation "com.squareup.okhttp3:okhttp-urlconnection:4.6.0"
val httpClient = OkHttpClient.Builder()
.cookieJar(JavaNetCookieJar(cookieManager))
.build()
val retrofit = Retrofit.Builder()
.client(httpClient)
.build()
推荐阅读
- java - Android:选中一个复选框会检查同一行中的所有复选框
- reactjs - Redux Form - 使用动态字段名称初始化状态
- android - 在 GradientDrawable Android 上设置描边
- python - 如何在 Django (Saleor) 中将“Chk”参数传递给 dotpay 支付网关
- node.js - 如何使用 Koa.JS 2 上传文件?
- python - 如何从python中的输入中获取方程
- google-cloud-platform - 谷歌云中的物联网数据
- sql-server - SQL Server Windows 用户身份验证
- sql - 如何运行查询以获取过去 12 个月的结果 (BigQuery)
- sql - 删除“列不存在”