我的网站使用 html2pdf(javascript) 从 html 生成 pdf,但在 android webview 上下载有问题:kotlin

问题描述 投票:0回答:1

我的网站使用 html2pdf(javascript) 从 html 生成 pdf,但在 Android 上下载存在问题

webview
:kotlin。当我想在显示我的网站按钮的
webview
中单击下载时,它就会崩溃。我希望你们能经历为什么会发生这种情况以及如何克服这个问题?我还是这个 android studio 开发的初学者。

在网站中(javascript):


function generatePDF(){
    var station_element = document.getElementById('station_content');
    var inspect_element = document.getElementById('inspect_content');
    window.scrollTo(0, 0);
    // Delay execution for 500 milliseconds (adjust as needed)
    setTimeout(function() {
        if (station_element) {
            var opt = {
                margin: 50,
                filename: 'myfile.pdf',
                image: { type: 'jpeg', quality: 1 },
                html2canvas: { scale: 5, width: 1300 },
                jsPDF: { unit: 'pt', format: 'a4', orientation: 'portrait' }
            };
            html2pdf().set(opt).from(station_element).save();
        } else if (inspect_element) {
            var opt = {
                margin: 60,
                filename: 'myfile.pdf',
                image: { type: 'jpeg', quality: 1 },
                html2canvas: { scale: 2 },
                jsPDF: { unit: 'pt', format: 'a4', orientation: 'portrait' }
            };
            html2pdf().set(opt).from(inspect_element).save();
        }
    }, 500); // 500 milliseconds delay
}

Android 工作室:MainActivity.kt

package com.coding.meet.webviewtoapp

import android.app.Dialog
import android.app.DownloadManager
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.util.Log
import android.view.KeyEvent
import android.webkit.CookieManager
import android.webkit.URLUtil
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.LinearLayout
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import com.coding.meet.webviewtoapp.databinding.ActivityMainBinding
import com.google.android.material.snackbar.Snackbar
import java.io.File

class MainActivity : AppCompatActivity() {
    private var webUrl = "https://smartappx.site"
    private val multiplePermissionId = 14
    private val multiplePermissionNameList =
        if (Build.VERSION.SDK_INT >= 33) {
            arrayListOf()
        } else {
            arrayListOf(
                android.Manifest.permission.READ_EXTERNAL_STORAGE,
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
            )
        }

    private var isLoaded = false
    private var doubleBackToExitPressedOnce = false

    private val networkConnectivityObserver: NetworkConnectivityObserver by lazy {
        NetworkConnectivityObserver(this)
    }

    private val loadingDialog: Dialog by lazy { Dialog(this) }

    private val mainBinding: ActivityMainBinding by lazy {
        DataBindingUtil.setContentView(this, R.layout.activity_main)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        loadingDialog.setContentView(R.layout.loading_layout)
        loadingDialog.window!!.setLayout(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        )
        loadingDialog.setCancelable(false)
        loadingDialog.show()

        val setting = mainBinding.webView.settings
        setting.javaScriptEnabled = true
        setting.allowFileAccess = true
        setting.domStorageEnabled = true
        setting.javaScriptCanOpenWindowsAutomatically = true
        setting.supportMultipleWindows()

        val snackbar =
            Snackbar.make(mainBinding.root, "No Internet Connection", Snackbar.LENGTH_INDEFINITE)
                .setAction("Wifi") { startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) }

        networkConnectivityObserver.observe(this) {
            when (it) {
                Status.Available -> {
                    if (snackbar.isShown) {
                        snackbar.dismiss()
                    }
                    mainBinding.swipeRefresh.isEnabled = true
                    if (!isLoaded) loadWebView()
                }
                else -> {
                    showNoInternet()
                    snackbar.show()
                    mainBinding.swipeRefresh.isRefreshing = false
                }
            }
        }

        mainBinding.swipeRefresh.setOnRefreshListener {
            if (!isLoaded) {
                loadWebView()
            } else {
                setProgressDialogVisibility(false)
            }
        }
    }

    private fun setProgressDialogVisibility(visible: Boolean) {
        if (visible) {
            loadingDialog.show()
        } else {
            loadingDialog.dismiss()
            mainBinding.swipeRefresh.isRefreshing = false
        }
    }

    private fun showNoInternet() {
        isLoaded = false
        setProgressDialogVisibility(false)
        gone(mainBinding.webView)
        visible(mainBinding.noInternet.noInternetRL)
    }

    private fun loadWebView() {
        gone(mainBinding.noInternet.noInternetRL)
        visible(mainBinding.webView)
        mainBinding.webView.loadUrl(webUrl)
        mainBinding.webView.setDownloadListener {
            url,
            userAgent,
            contentDisposition,
            mimeType,
            contentLength ->
            Log.d("Url", url.trim())
            Log.d("userAgent", userAgent)
            Log.d("contentDisposition", contentDisposition)
            Log.d("mimeType", mimeType)
            Log.d("contentLength", contentLength.toString())
            if (checkMultiplePermission()) {
                download(url.trim(), userAgent, contentDisposition, mimeType, contentLength)
            }
        }
        mainBinding.webView.webViewClient =
            object : WebViewClient() {
                override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                    setProgressDialogVisibility(true)
                    super.onPageStarted(view, url, favicon)
                }

                override fun shouldOverrideUrlLoading(
                    view: WebView?,
                    request: WebResourceRequest?,
                ): Boolean {
                    val url = request?.url.toString()
                    view?.loadUrl(url)
                    return super.shouldOverrideUrlLoading(view, request)
                }

                override fun onPageFinished(view: WebView?, url: String?) {
                    isLoaded = true
                    webUrl = url!!
                    setProgressDialogVisibility(false)
                    super.onPageFinished(view, url)
                }

                override fun onReceivedError(
                    view: WebView?,
                    request: WebResourceRequest?,
                    error: WebResourceError?,
                ) {
                    isLoaded = false
                    setProgressDialogVisibility(false)
                    super.onReceivedError(view, request, error)
                }
            }
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (event.action == KeyEvent.ACTION_DOWN) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                if (mainBinding.webView.canGoBack()) {
                    mainBinding.webView.goBack()
                } else {
                    showToastExit()
                }
                return true
            }
        }

        return super.onKeyDown(keyCode, event)
    }

    private fun showToastExit() {
        when {
            doubleBackToExitPressedOnce -> {
                finish()
            }
            else -> {
                doubleBackToExitPressedOnce = true
                Toast.makeText(this, "Please Click Back Again to Exit", Toast.LENGTH_LONG).show()
                Handler(Looper.getMainLooper())
                    .postDelayed({ doubleBackToExitPressedOnce = false }, 2000)
            }
        }
    }

    private fun download(
        url: String,
        userAgent: String,
        contentDisposition: String,
        mimeType: String,
        contentLength: Long
    ) {
        val folder = File(Environment.getExternalStorageDirectory().toString() + "/Download/Image")
        if (!folder.exists()) {
            folder.mkdirs()
        }
        Toast.makeText(this, "Download Started", Toast.LENGTH_SHORT).show()

        val request = DownloadManager.Request(Uri.parse(url))
        request.setMimeType(mimeType)
        val cookie = CookieManager.getInstance().getCookie(url)
        request.addRequestHeader("cookie", cookie)
        request.addRequestHeader("User-Agent", userAgent)
        request.setAllowedNetworkTypes(
            DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE
        )
        val fileName = URLUtil.guessFileName(url, contentDisposition, mimeType)
        request.setTitle(fileName)
        request.setNotificationVisibility(
            DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
        )
        request.setDestinationInExternalPublicDir(
            Environment.DIRECTORY_DOWNLOADS,
            "Image/$fileName"
        )
        val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
        downloadManager.enqueue(request)
    }

    private fun checkMultiplePermission(): Boolean {
        val listPermissionNeeded = arrayListOf<String>()
        for (permission in multiplePermissionNameList) {
            if (
                ContextCompat.checkSelfPermission(this, permission) !=
                    PackageManager.PERMISSION_GRANTED
            ) {
                listPermissionNeeded.add(permission)
            }
        }
        if (listPermissionNeeded.isNotEmpty()) {
            ActivityCompat.requestPermissions(
                this,
                listPermissionNeeded.toTypedArray(),
                multiplePermissionId
            )
            return false
        }
        return true
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray,
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if (requestCode == multiplePermissionId) {
            if (grantResults.isNotEmpty()) {
                var isGrant = true
                for (element in grantResults) {
                    if (element == PackageManager.PERMISSION_DENIED) {
                        isGrant = false
                    }
                }
                if (isGrant) {
                    // here all permission granted successfully
                    Toast.makeText(this, "all permission granted successfully", Toast.LENGTH_LONG)
                        .show()
                } else {
                    var someDenied = false
                    for (permission in permissions) {
                        if (
                            !ActivityCompat.shouldShowRequestPermissionRationale(this, permission)
                        ) {
                            if (
                                ActivityCompat.checkSelfPermission(this, permission) ==
                                    PackageManager.PERMISSION_DENIED
                            ) {
                                someDenied = true
                            }
                        }
                    }
                    if (someDenied) {
                        // here app Setting open because all permission is not granted
                        // and permanent denied
                        appSettingOpen(this)
                    } else {
                        // here warning permission show
                        warningPermissionDialog(this) { _: DialogInterface, which: Int ->
                            when (which) {
                                DialogInterface.BUTTON_POSITIVE -> checkMultiplePermission()
                            }
                        }
                    }
                }
            }
        }
    }
}

这个代码不是我的,我只是用我的演示网站测试它。

我尝试在android平台上寻找解决方案,但没有找到。

这是android logcat

Logcat IllegalArgumentException:

024-06-03 17:28:30.668  1264-2123  AlarmManager            com.google.android.gms.persistent    W  alarm window unlikely to be respected [CONTEXT service_id=231 ] (Ask Gemini)
    java.lang.IllegalArgumentException: alarm "NetworkLocationLocator" has short window length
        at bngl.b(:com.google.android.gms@[email protected] (190800-633713831):52)
        at efni.f(:com.google.android.gms@[email protected] (190800-633713831):119)
        at efjs.r(:com.google.android.gms@[email protected] (190800-633713831):107)
        at efjs.f(:com.google.android.gms@[email protected] (190800-633713831):27)
        at efjp.apply(:com.google.android.gms@[email protected] (190800-633713831):19)
        at esdc.d(:com.google.android.gms@[email protected] (190800-633713831):3)
        at esdd.run(:com.google.android.gms@[email protected] (190800-633713831):42)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at bomx.nL(:com.google.android.gms@[email protected] (190800-633713831):1)
        at bomx.dispatchMessage(:com.google.android.gms@[email protected] (190800-633713831):138)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.os.HandlerThread.run(HandlerThread.java:67)
--------- beginning of crash
2024-06-03 17:36:43.011  1639-1639  AndroidRuntime          com.coding.meet.webviewtoapp         E  FATAL EXCEPTION: main (Ask Gemini)
    Process: com.coding.meet.webviewtoapp, PID: 1639
    java.lang.IllegalArgumentException: Can only download HTTP/HTTPS URIs: blob:https://smartappx.site/ac776f6d-9ba9-4d15-ab60-2249b485853b
        at android.app.DownloadManager$Request.<init>(DownloadManager.java:468)
        at com.coding.meet.webviewtoapp.MainActivity.download(MainActivity.kt:236)
        at com.coding.meet.webviewtoapp.MainActivity.loadWebView$lambda$2(MainActivity.kt:148)
        at com.coding.meet.webviewtoapp.MainActivity.$r8$lambda$17rajA2X3B1OvSyO9osdba9FNsQ(Unknown Source:0)
        at com.coding.meet.webviewtoapp.MainActivity$$ExternalSyntheticLambda1.onDownloadStart(Unknown Source:7)
        at g9.handleMessage(chromium-TrichromeWebViewGoogle6432.apk-stable-447211487:145)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7839)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
2024-06-03 17:39:19.433  1264-2123  AlarmManager            com.google.android.gms.persistent    W  alarm window unlikely to be respected [CONTEXT service_id=231 ] (Ask Gemini)
    java.lang.IllegalArgumentException: alarm "NetworkLocationLocator" has short window length
        at bngl.b(:com.google.android.gms@[email protected] (190800-633713831):52)
        at efni.f(:com.google.android.gms@[email protected] (190800-633713831):119)
        at efjs.r(:com.google.android.gms@[email protected] (190800-633713831):107)
        at efjs.f(:com.google.android.gms@[email protected] (190800-633713831):27)
        at efjp.apply(:com.google.android.gms@[email protected] (190800-633713831):19)
        at esdc.d(:com.google.android.gms@[email protected] (190800-633713831):3)
        at esdd.run(:com.google.android.gms@[email protected] (190800-633713831):42)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at bomx.nL(:com.google.android.gms@[email protected] (190800-633713831):1)
        at bomx.dispatchMessage(:com.google.android.gms@[email protected] (190800-633713831):138)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.os.HandlerThread.run(HandlerThread.java:67)
php android webview runtime-error html2pdf
1个回答
0
投票

我遇到了类似的问题,

onDownloadStart
参数网址附加了
blob
。它只是在网址中,所以我删除了它,一切正常。

private fun download(
        url: String,
        userAgent: String,
        contentDisposition: String,
        mimeType: String,
        contentLength: Long
    ) {
        val folder = File(Environment.getExternalStorageDirectory().toString() + "/Download/Image")
        if (!folder.exists()) {
            folder.mkdirs()
        }
        Toast.makeText(this, "Download Started", Toast.LENGTH_SHORT).show()

        val request = DownloadManager.Request(Uri.parse(url))
        request.setMimeType(mimeType)
        val cookie = CookieManager.getInstance().getCookie(url)
        request.addRequestHeader("cookie", cookie)
        request.addRequestHeader("User-Agent", userAgent)
        request.setAllowedNetworkTypes(
            DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE
        )
        val fileName = URLUtil.guessFileName(url, contentDisposition, mimeType)
        request.setTitle(fileName)
        request.setNotificationVisibility(
            DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
        )
        request.setDestinationInExternalPublicDir(
            Environment.DIRECTORY_DOWNLOADS,
            "Image/$fileName"
        )
        val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
        downloadManager.enqueue(request)
    }
© www.soinside.com 2019 - 2024. All rights reserved.