从 DownloadManager 打开下载的文件时如何修复 CursorIndexOutOfBoundsException? [复制]

Posted

技术标签:

【中文标题】从 DownloadManager 打开下载的文件时如何修复 CursorIndexOutOfBoundsException? [复制]【英文标题】:How to fix the CursorIndexOutOfBoundsException when opening a downloaded file from DownloadManager? [duplicate] 【发布时间】:2019-12-06 12:38:24 【问题描述】:

我正在制作一个下载 APK 文件然后打开它的功能。下载后,onDownloadComplete 中的 downloadId 看起来正常(正整数)。但是,我收到“光标索引超出范围”错误。

2019-07-29 15:44:26.030 7391-7391/dev.thematrix.tvhk E/androidRuntime: FATAL EXCEPTION: main
    Process: dev.thematrix.tvhk, PID: 7391
    java.lang.RuntimeException: Error receiving broadcast Intent  act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=dev.thematrix.tvhk (has extras)  in dev.thematrix.tvhk.MainActivity$onDownloadComplete@bc11337
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1132)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
        at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
        at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
        at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:74)
        at android.database.CursorWrapper.getLong(CursorWrapper.java:127)
        at android.database.CursorWrapper.getLong(CursorWrapper.java:127)
        at android.app.DownloadManager$CursorTranslator.getLong(DownloadManager.java:1487)
        at android.app.DownloadManager$CursorTranslator.getLocalUri(DownloadManager.java:1509)
        at android.app.DownloadManager$CursorTranslator.getString(DownloadManager.java:1496)
        at dev.thematrix.tvhk.MainActivity$onDownloadComplete.onReceive(MainActivity.kt:180)
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:1122)
        at android.os.Handler.handleCallback(Handler.java:751) 
        at android.os.Handler.dispatchMessage(Handler.java:95) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
2019-07-29 15:44:26.557 1338-1338/? E/EGL_emulation: tid 1338: eglCreateSyncKHR(2050): error 0x3004 (EGL_BAD_ATTRIBUTE)
2019-07-29 15:44:26.696 1338-2407/? E/BufferQueueProducer: [com.google.android.leanbacklauncher/com.google.android.leanbacklauncher.MainActivity] cancelBuffer: BufferQueue has been abandoned

下面是我的代码 sn-p。

class MainActivity : Activity() 
    //...

    private fun downloadUpdate() 
        registerReceiver(onDownloadComplete(), IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))

        val request = DownloadManager
            .Request(Uri.parse("https://somewhere.com/app-release.apk"))
            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
            .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-release.apk")

        downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
        downloadId = downloadManager.enqueue(request)
    

    private class onDownloadComplete: BroadcastReceiver() 
        override fun onReceive(context: Context, intent: Intent) 
            Log.d("__DEBUG__", "Download completed")

            val c = downloadManager.query(DownloadManager.Query().setFilterById(downloadId))
            val fileUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
            val mFile = File(Uri.parse(fileUri).path!!)
            val fileName = mFile.absolutePath

            context.unregisterReceiver(this)

            val intent = Intent(Intent.ACTION_VIEW)
            intent.setDataAndType(Uri.fromFile(File(fileName)), "application/vnd.android.package-archive")
            startActivity(ctx, intent, null)
        
    

    companion object 
        //...
        private lateinit var downloadManager: DownloadManager
        private var downloadId: Long = -1
    

c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI) 导致出站错误吗?我可以知道出了什么问题吗?

【问题讨论】:

首先你应该调用c.moveToFirst(),然后再从游标中获取数据。 @HiI'mFrogatto 一条简单的线已经解决了这个问题。非常感谢! 【参考方案1】:

首先你应该在从游标获取数据之前调用c.moveToFirst()

【讨论】:

以上是关于从 DownloadManager 打开下载的文件时如何修复 CursorIndexOutOfBoundsException? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

FileProvider - 从下载目录打开文件

Downloadmanager实现app实现的升级下载使用

Android中的文件下载——DownLoadManager

如何使用 DownloadManager 将下载的文件存储到应用程序分配的文件目录中?

在不使用 DownloadManager 的情况下更新 Android“下载”文件夹

Android DownloadManager 获取文件名