Вопрос или проблема
Я разрабатываю приложение, которое открывает 2 веб-вью бок о бок, и это работает. Но я хочу, чтобы куки не делились друг с другом, то есть контекст должен быть независимым.
Пожалуйста, найдите ниже фрагмент кода, я пробовал разные подходы с помощью ChatGPT :), не сработало … Я новичок в разработке для Android … подскажите, как решить эту проблему
package com.example.twowebviews
import android.content.Context
import android.os.Bundle
import android.webkit.CookieManager
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Button
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ContextThemeWrapper
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
class MainActivity : AppCompatActivity() {
lateinit var webView1: WebView
lateinit var webView2: WebView
lateinit var swipeRefresh1: SwipeRefreshLayout
lateinit var swipeRefresh2: SwipeRefreshLayout
lateinit var urlBar1: EditText
lateinit var urlBar2: EditText
lateinit var refreshButton1: Button
lateinit var refreshButton2: Button
private val cookieManager1 = CookieManager.getInstance()
private val cookieManager2 = CookieManager.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Инициализация WebViews и UI компонентов
webView1 = findViewById(R.id.webview_1)
webView2 = findViewById(R.id.webview_2)
swipeRefresh1 = findViewById(R.id.swipe_refresh_1)
swipeRefresh2 = findViewById(R.id.swipe_refresh_2)
urlBar1 = findViewById(R.id.url_bar_1)
urlBar2 = findViewById(R.id.url_bar_2)
refreshButton1 = findViewById(R.id.refresh_button_1)
refreshButton2 = findViewById(R.id.refresh_button_2)
// Настройка параметров WebView
configureWebView(webView1)
configureWebView(webView2)
// Установка начальных URL
loadUrlInWebView(webView1, "https://platform.dev.testurl.com")
loadUrlInWebView(webView2, "https://platform.dev.testurl.com")
// Обработка pull-to-refresh
swipeRefresh1.setOnRefreshListener {
webView1.reload()
swipeRefresh1.isRefreshing = false
}
swipeRefresh2.setOnRefreshListener {
webView2.reload()
swipeRefresh2.isRefreshing = false
}
// Обработка кликов по кнопкам обновления
refreshButton1.setOnClickListener {
webView1.reload()
}
refreshButton2.setOnClickListener {
webView2.reload()
}
// Обработка изменений URL
urlBar1.setOnEditorActionListener { _, _, _ ->
loadUrlInWebView(webView1, urlBar1.text.toString())
true
}
urlBar2.setOnEditorActionListener { _, _, _ ->
loadUrlInWebView(webView2, urlBar2.text.toString())
true
}
}
private fun createCustomContext(base: Context, themeResId: Int): Context {
return ContextThemeWrapper(base, themeResId)
}
private fun configureWebView(webView: WebView) {
// Создание нового экземпляра CookieManager
val cookieManager = CookieManager.getInstance()
cookieManager.removeAllCookies(null) // Очистка куков для начала с нуля
cookieManager.setAcceptCookie(true)
cookieManager.setAcceptThirdPartyCookies(webView, true)
webView.webViewClient = WebViewClient() // Обеспечивает открытие ссылок внутри WebView
webView.settings.javaScriptEnabled = true // Включить поддержку JavaScript, если это необходимо
// Включить localStorage
webView.settings.domStorageEnabled = true
// val webSettings: WebSettings = webView.settings
webView.settings.cacheMode = WebSettings.LOAD_DEFAULT // Включить режим кэширования по умолчанию
// Очистить существующий кэш и куки
webView.clearCache(true)
webView.clearHistory()
}
private fun loadUrlInWebView(webView: WebView, url: String) {
if (!url.startsWith("http://") && !url.startsWith("https://")) {
webView.loadUrl("https://$url")
} else {
webView.loadUrl(url)
}
}
override fun onDestroy() {
super.onDestroy()
// Очистка WebViews
webView1.destroy()
webView2.destroy()
}
}
Ответ или решение
Для решения задачи изолирования кукисов между двумя WebView в приложении на Android, вам необходимо учесть, что по умолчанию используется общий CookieManager, что приводит к обмену данными кукисов между WebView. Чтобы сделать кукисы независимыми и не делиться ими, вам необходимо реализовать кастомный CookieManager для каждого WebView.
Шаги для изоляции кукисов в нескольких WebView:
-
Создание собственного CookieManager: Для каждого WebView создаем свой экземпляр CookieManager, который будет хранить свои кукисы.
-
Использование
set Cookie
для каждого запроса: При загрузке URL необходимо явно устанавливать кукисы, связанные только с конкретным WebView.
Вот пример реализации:
package com.example.twowebviews
import android.os.Bundle
import android.webkit.CookieManager
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import android.widget.Button
import android.widget.EditText
class MainActivity : AppCompatActivity() {
private lateinit var webView1: WebView
private lateinit var webView2: WebView
private lateinit var swipeRefresh1: SwipeRefreshLayout
private lateinit var swipeRefresh2: SwipeRefreshLayout
private lateinit var urlBar1: EditText
private lateinit var urlBar2: EditText
private lateinit var refreshButton1: Button
private lateinit var refreshButton2: Button
private val cookieManager1 = CookieManager.getInstance()
private val cookieManager2 = CookieManager.getInstance()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Инициализация WebView и интерфейса
webView1 = findViewById(R.id.webview_1)
webView2 = findViewById(R.id.webview_2)
swipeRefresh1 = findViewById(R.id.swipe_refresh_1)
swipeRefresh2 = findViewById(R.id.swipe_refresh_2)
urlBar1 = findViewById(R.id.url_bar_1)
urlBar2 = findViewById(R.id.url_bar_2)
refreshButton1 = findViewById(R.id.refresh_button_1)
refreshButton2 = findViewById(R.id.refresh_button_2)
// Конфигурация WebView
configureWebView(webView1, cookieManager1)
configureWebView(webView2, cookieManager2)
// Загрузка начальных URL
loadUrlInWebView(webView1, "https://platform.dev.testurl.com")
loadUrlInWebView(webView2, "https://platform.dev.testurl.com")
// Обработка нажатий кнопок
swipeRefresh1.setOnRefreshListener {
webView1.reload()
swipeRefresh1.isRefreshing = false
}
swipeRefresh2.setOnRefreshListener {
webView2.reload()
swipeRefresh2.isRefreshing = false
}
// Обработка событий клика на кнопки обновления
refreshButton1.setOnClickListener {
webView1.reload()
}
refreshButton2.setOnClickListener {
webView2.reload()
}
// Обработка изменений URL
urlBar1.setOnEditorActionListener { _, _, _ ->
loadUrlInWebView(webView1, urlBar1.text.toString())
true
}
urlBar2.setOnEditorActionListener { _, _, _ ->
loadUrlInWebView(webView2, urlBar2.text.toString())
true
}
}
private fun configureWebView(webView: WebView, cookieManager: CookieManager) {
webView.webViewClient = WebViewClient()
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.settings.cacheMode = WebSettings.LOAD_DEFAULT
// Очистка кеша и истории для нового WebView
webView.clearCache(true)
webView.clearHistory()
}
private fun loadUrlInWebView(webView: WebView, url: String) {
if (!url.startsWith("http://") && !url.startsWith("https://")) {
webView.loadUrl("https://$url")
} else {
webView.loadUrl(url)
}
}
override fun onDestroy() {
super.onDestroy()
webView1.destroy()
webView2.destroy()
}
}
Ключевые моменты реализации:
-
Кастомизация CookieManager: Приведите в порядок использование CookieManager. Возможно, вам нужно создать класс обертку для CookieManager, который будет пригоден для манипуляций с куками, сохраняя их независимыми для каждого WebView.
-
Необходимость в двух экземплярах WebView: Каждый WebView должен иметь полностью независимые настройки, что позволяет избежать совпадения кукисов.
-
Загрузка URL: Убедитесь, что ваши функции загрузки URL предполагают добавление или изменение кукисов на основе пользовательского ввода.
Заключение
Создание двух независимых WebView с отдельными кукисами является неотъемлемой частью для сохранения приватности и защиты данных пользователя. Приведенный выше код помогает вам настроить это поведение, используя кастомные конфигурации для каждого WebView, используя Kotlin. Если у вас есть еще вопросы, не стесняйтесь спрашивать!