Приложение Android Не делиться куками/сессией между двумя веб-представлениями, приложение разработано на Kotlin

Вопрос или проблема

Я разрабатываю приложение, которое открывает 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:

  1. Создание собственного CookieManager: Для каждого WebView создаем свой экземпляр CookieManager, который будет хранить свои кукисы.

  2. Использование 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()
    }
}

Ключевые моменты реализации:

  1. Кастомизация CookieManager: Приведите в порядок использование CookieManager. Возможно, вам нужно создать класс обертку для CookieManager, который будет пригоден для манипуляций с куками, сохраняя их независимыми для каждого WebView.

  2. Необходимость в двух экземплярах WebView: Каждый WebView должен иметь полностью независимые настройки, что позволяет избежать совпадения кукисов.

  3. Загрузка URL: Убедитесь, что ваши функции загрузки URL предполагают добавление или изменение кукисов на основе пользовательского ввода.

Заключение

Создание двух независимых WebView с отдельными кукисами является неотъемлемой частью для сохранения приватности и защиты данных пользователя. Приведенный выше код помогает вам настроить это поведение, используя кастомные конфигурации для каждого WebView, используя Kotlin. Если у вас есть еще вопросы, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...