18034727885
2026-08-25 d081165686e520cc06cb87f928ed70d32401c138
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package com.example.mylibrary
 
import android.app.Activity
import android.app.Application
import android.content.ComponentCallbacks
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.webkit.CookieManager
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
import android.webkit.WebStorage
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.TextView
import androidx.activity.SystemBarStyle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
 
//网页支付加载页
class WebPayActivity : AppCompatActivity() {
    companion object {
        //获取跳转此页面intent
        fun getIntent(context: Context, url: String, title: String? = null): Intent {
            return Intent(context, WebPayActivity::class.java).apply {
                putExtra("url", url)
                putExtra("title", title)
            }
        }
    }
 
    //屏幕密度
    private var density = 0f
 
    //缩放屏幕密度
    private var scaledDensity = 0f
 
    private val ua by lazy {
        intent.getStringExtra("ua")
    }
    private val url by lazy {
        intent.getStringExtra("url")
    }
    private val title by lazy {
        intent.getStringExtra("title")
    }
    private val ivClose by lazy {
        findViewById<View>(R.id.iv_close)
    }
 
    private val tvTitle by lazy {
        findViewById<TextView>(R.id.tv_title)
    }
 
    private val webView by lazy {
        findViewById<WebView>(R.id.web)
    }
 
    override fun onCreate(savedInstanceState: Bundle?) {
        setCustomDensity(this, application)
        super.onCreate(savedInstanceState)
        val transparentStyle = SystemBarStyle.light(
            scrim = Color.TRANSPARENT,      // 浅色主题下 scrim
            darkScrim = Color.TRANSPARENT   // 深色主题下 scrim
        )
 
        enableEdgeToEdge(statusBarStyle = transparentStyle, navigationBarStyle = transparentStyle)
        setContentView(R.layout.activity_web)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
        ivClose.setOnClickListener { finish() }
        clearWebViewCache()
        initWebView()
    }
 
    //设置自定义的屏幕密度,解决屏幕适配问题
    private fun setCustomDensity(activity: Activity, application: Application) {
        val displayMetrics = application.resources.displayMetrics
        if (density == 0f) {
            density = displayMetrics.density
            scaledDensity = displayMetrics.scaledDensity
            application.registerComponentCallbacks(object : ComponentCallbacks {
                override fun onConfigurationChanged(newConfig: Configuration) {
                    if (newConfig.fontScale > 0) {
                        scaledDensity = application.resources.displayMetrics.scaledDensity
                    }
                }
 
                @Deprecated("Deprecated in Java")
                override fun onLowMemory() {
 
                }
            })
        }
        val targetDensity: Float = displayMetrics.widthPixels / 375f
        val targetScaledDensity = targetDensity * (scaledDensity / density)
        val targetDensityDpi = (160 * targetDensity).toInt()
        displayMetrics.density = targetDensity
        displayMetrics.scaledDensity = targetScaledDensity
        displayMetrics.densityDpi = targetDensityDpi
        val activityDisplayMetrics = activity.resources.displayMetrics
        activityDisplayMetrics.density = targetDensity
        activityDisplayMetrics.scaledDensity = targetScaledDensity
        activityDisplayMetrics.densityDpi = targetDensityDpi
    }
 
    private fun clearWebViewCache() {
        // 1. 清除资源缓存(HTML、JS、CSS、图片等)
        webView.clearCache(true)
 
        // 2. 清除 DOM 存储(localStorage / sessionStorage)
        //    注意:必须在主线程调用,且 WebView 的 settings 中已开启 domStorageEnabled
        WebStorage.getInstance().deleteAllData()
 
        // 3. 清除 IndexedDB / Web SQL Database(如果 H5 使用了)
        deleteDatabase("webview.db")
        deleteDatabase("webviewCache.db")
 
        // 4. 清除历史记录(非必需,但可以避免回退到旧页面)
        webView.clearHistory()
 
        // 5. 可选:清除 Cookie
        CookieManager.getInstance().removeAllCookies(null)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            CookieManager.getInstance().flush()
        }
    }
 
    private fun initWebView() {
 
        val cookieManager = CookieManager.getInstance()
 
        // 1. 允许 WebView 接受 Cookie(默认其实是 true,但显式声明更安全)
        cookieManager.setAcceptCookie(true)
 
        // 2. 允许第三方 Cookie —— 这是关键!
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            cookieManager.setAcceptThirdPartyCookies(webView, true)
        }
 
        // 3. WebSettings 关键开关
        webView.settings.apply {
            javaScriptEnabled = true //允许js调用
            domStorageEnabled = true //部分 H5 框架把状态存在 DOM Storage
            databaseEnabled = true
            allowContentAccess = true //是否允许在WebView中访问内容URL(Content Url),默认允许
 
            setSupportZoom(true) //支持缩放,默认为true。是下面那个的前提。
            builtInZoomControls = true //设置内置的缩放控件。若为false,则该WebView不可缩放
            displayZoomControls = false //隐藏原生的缩放控件
            javaScriptCanOpenWindowsAutomatically = true //支持通过JS打开新窗口
            loadsImagesAutomatically = true //支持自动加载图片
            defaultTextEncodingName = "utf-8" //设置编码格式
            userAgentString =
                "$userAgentString webchatPay/wx074c1f0cf5a0ecf4 InAppPay Vzan/miniAppPayment vzanApp navigator.userAgent zhiboApp FullScreen"
        }
 
        webView.addJavascriptInterface(this, "android")
        webView.webChromeClient = object : WebChromeClient() {
            override fun onReceivedTitle(view: WebView?, title: String?) {
                super.onReceivedTitle(view, title)
                tvTitle.text = title?.ifEmpty { this@WebPayActivity.title } ?: ""
            }
        }
        webView.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                val cookieManager = CookieManager.getInstance()
                // 获取该域名下的所有 Cookie
                val cookies = cookieManager.getCookie(url)
                Log.d("xxx", "URL: $url")
                Log.d("xxx", "Cookies: $cookies")
            }
        }
        url?.also { webView.loadUrl(it) }
    }
 
    /**
     * 跳转小程序支付
     */
    @JavascriptInterface
    fun jumpToMiniProgramPay(json: String) {
        runOnUiThread {
            Log.d("xxx", json)
            BusinessModule.webPayCallback?.invokeAndKeepAlive(json)
        }
    }
 
    override fun finish() {
        BusinessModule.webPayCallback = null
        super.finish()
    }
}