无法使用下载管理器在 android webview 中下载 excel

Posted

技术标签:

【中文标题】无法使用下载管理器在 android webview 中下载 excel【英文标题】:can't download excel in android webview using Download Manager 【发布时间】:2021-12-29 22:26:31 【问题描述】:

我在 android webview 中显示 web url。然后在网上有一个下载报告菜单(.xls)

我尝试使用下载管理器,以便可以通过我创建的 web 视图下载它。但结果总是失败。

如果需要,这是我的代码

webview.setDownloadListener(object : DownloadListener 
            override fun onDownloadStart(url: String, userAgent: String, contentDisposition: String, mimetype: String, contentLength: Long) 
                val request = DownloadManager.Request(Uri.parse(url))
                request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimetype))
                request.setDescription("Downloading file...")
                request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(url, contentDisposition, mimetype))
                val dm = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
                dm.enqueue(request)
                Toast.makeText(applicationContext, "Downloading...", Toast.LENGTH_SHORT).show()
                registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
            


            var onComplete: BroadcastReceiver = object : BroadcastReceiver() 
                override fun onReceive(context: Context, intent: Intent) 
                    Toast.makeText(applicationContext, "Downloading Complete", Toast.LENGTH_SHORT).show()
                
            
        )

我没有其他想法,提前非常感谢您的所有帮助^^

【问题讨论】:

是因为.xls吗?尝试下载 .jpg 文件作为测试。 @blackapps 我尝试下载该图像,并且成功了。我应该检查什么才能下载生成的 excel 文件? 【参考方案1】:

在开始请求之前,您是否已请求 WRITE_EXTERNAL_STORAGE权限?如果是,请尝试将这些添加到您的请求中(我无法在 Kotlin 中为您提供帮助,但这是我的 Java 等价物):

String cookie= CookieManager.getInstance().getCookie(url);
//Add cookie and User-Agent to request
request.addRequestHeader("Cookie",cookie);
request.addRequestHeader("User-Agent",userAgent);
//file scanned by MediaScanner
request.allowScanningByMediaScanner();

如果您没有请求权限,请尝试在 onDownload start 上执行此操作(注意我写的 cmets,它们应该会有所帮助):

//Declare these on top of your class
private String durl, duserAgent, dcontentDisposition, dmimetype;


webView.setDownloadListener(new DownloadListener() 
@Override
   public void onDownloadStart(final String url, final String userAgent, String 
   contentDisposition, String mimetype, long contentLength) 

                //Hold the onDownloadStart parameters to fields so that you can
                //use them inside onRequestPermissionsResult to call the 
                //download method
                durl = url;
                duserAgent = userAgent;
                dcontentDisposition = contentDisposition;
                dmimetype = mimetype;


                //Checking runtime permission for devices above Marshmallow.
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 

                    if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) 
                        showRationaleDialog(url, userAgent, contentDisposition, mimetype);
                     else 
                        AskForPemission(url, userAgent, contentDisposition, mimetype);
                    
                 else 
                    //Code for devices below API 23 or Marshmallow
                    //Log.v(TAG,"Permission is granted");
                    downloadDialog(url, userAgent, contentDisposition, mimetype);
                
            
   );

public void showRationaleDialog(final String url, final String userAgent, final String contentDisposition, final String mimetype)
        AlertDialog.Builder builder = new AlertDialog.Builder(Program_file_webview.this);
        builder.setIcon(R.drawable.icon_attention);
        builder.setTitle("Permission Needed");
        builder.setMessage("You have to grant permission to the app, in order to download the desired file");
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener()
        
            @Override
            public void onClick(DialogInterface dialog, int which)
            
                AskForPemission(url,userAgent,contentDisposition,mimetype);
            
        );
        builder.create().show();
    

public void AskForPemission(String url, String userAgent, String contentDisposition, String mimetype)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) 
                //Log.v(TAG,"Permission is granted");
                downloadDialog(url,userAgent,contentDisposition,mimetype);
             else 
                //Log.v(TAG,"Permission is revoked");
                //requesting permissions.
                ActivityCompat.requestPermissions(Program_file_webview.this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, WRITE_EXT_STORAGE);

            
        

    

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           String[] permissions, int[] grantResults) 
        switch (requestCode) 
            case WRITE_EXT_STORAGE: 
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) 
                    downloadDialog(durl,duserAgent,dcontentDisposition,dmimetype);
                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                 else 
                    Toast.makeText(Program_file_webview.this, "You need to grant permission in order to download the file. Please allow it and try again.", Toast.LENGTH_SHORT).show();
                    mywebView.loadUrl(cmp_url);
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                
                return;
            

            // other 'case' lines to check for other
            // permissions this app might request.
        
    

downloadDialog 是一种方法,在该方法中我只显示“你想保存文件”对话框,如果用户积极响应,我会使用你在 onDownloadStart 中创建的请求 + 行中所写的内容在我的答案的顶部。当然,如果您愿意,您可以跳过对话框部分,也可以使用我在下载开始时保存的参数字段,而不是将参数直接传递给 showRationaleDialog、AskForPemission 和 downloadDialog

总而言之,您所做的是:

根据SDK级别检查是否需要请求权限 检查您是否已获得许可,否则用户应该会看到一条消息,说明您为什么需要他的许可 如果需要,请请求许可 调用下载函数

我希望它对逻辑有所帮助,即使它是在 Java 中而不是 Kotlin 中!

【讨论】:

DownloadManager 不需要这些权限。 我关注了,结果还是下载不成功

以上是关于无法使用下载管理器在 android webview 中下载 excel的主要内容,如果未能解决你的问题,请参考以下文章

Android SDK 管理器在选择存储库时出现“无法获取 URL https://dl-ssl.google.com/android/repository/repository.xml”错误

android studio 4.0 中的 AVD 管理器在哪里

我可以使用 Android Studio Avd 管理器在 Windows 上运行 iOS 模拟器吗?

使用 Android 帐户管理器在我的服务器上验证使用 FB 登录的用户

使用 Android 帐户管理器在我的服务器上验证使用 FB 登录的用户

Android Studios:Android 设备管理器在文件资源管理器中未显示 Nougat 7.0 的文件