繁体   English   中英

Android 数据库在线下载

[英]Android Database download online

您好,我是 Android 开发的新手,我的应用程序完全面向数据库。 在我的应用程序中,我正在使用从资产文件夹复制数据库文件的方法。 它会增加apk的大小。

我想在我的应用程序第一次在手机上运行时从 inte.net 复制它。

如何将数据库文件下载到我的应用程序数据库文件夹中。

我就是这样做的:

我有一个处理下载数据库的DownloadManager实现。 在我的例子中,数据库非常大,因此 DownloadManager 是有效处理大量下载的好选择。

实现 DownloadManager 时需要注意的一件事; 建议您先将文件下载为临时文件,然后将它们移动到最终位置。 这是为了避免我在这样做时遇到奇怪的安全问题。 此外,下载通知可见性可能会影响所需的权限,如果您决定根本没有通知,则需要添加DOWNLOAD_WITHOUT_NOTIFICATION

所需权限:

<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE " />

下载管理器实现

/**
 * Manages all DB retrieval and file level validation.
 *
 */

class DataBaseInitializationRepository(private val app: Application, private val dbHelper: DatabaseFileHelper) {


fun initiateDB( callback: DownloadCompleteCallback){

    val dbUrl = dbHelper.getDbUrl()
    val tempDbFile = dbHelper.getTempDbFile()
    val permanentDbFile = dbHelper.getPermanentDbFile()

    if (!permanentDbFile.exists() && tempDbFile.length() <= 0) {

        val downloadManager = app.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
        val downLoadDBRequest = DownloadManager.Request(Uri.parse( dbUrl ))
            .setTitle( app.getString( R.string.download_db_title ) )
            .setDescription(app.getString( R.string.download_db_description ))
            .setDestinationInExternalFilesDir( app,
                    null,
                    tempDbFile.path
            )
            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)

        val downloadId = downloadManager.enqueue( downLoadDBRequest )

        registerReceiver( callback, downloadId )

    }else{
        callback.onComplete(0L)
    }

}

private fun registerReceiver(callback: DownloadCompleteCallback, downloadId: Long){
    val receiver = object: BroadcastReceiver(){
        override fun onReceive(context: Context?, intent: Intent?) {
            val id = intent?.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
            if (id == downloadId){

                //Move index reads to reusable function

                val downloadManager = app.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
                val query = DownloadManager.Query()
                query.setFilterById( downloadId )

                val data = downloadManager.query( query )

                if(data.moveToFirst() && data.count > 0){
                    val statusIndex = data.getColumnIndex(DownloadManager.COLUMN_STATUS)
                    val status = data.getInt( statusIndex )
                    if(status == DownloadManager.STATUS_SUCCESSFUL){

                        val localUriIndex = data.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
                        val localFile = File(
                            data.getString( localUriIndex )
                                .replace("file://","" )
                        )

                        if(localFile.exists()){
                            permanentlyStoreDb(localFile)
                            callback.onComplete(id)
                        }else{
                            callback.onFail("Initial Database Download Failed - File not found")
                        }
                    }else if(status == DownloadManager.STATUS_FAILED){

                        val reasonIndex = data.getColumnIndex(DownloadManager.COLUMN_REASON)
                        val reason = data.getInt( reasonIndex )
                        if(reason == DownloadManager.ERROR_FILE_ALREADY_EXISTS){
                            callback.onComplete(id)
                        }else{
                            callback.onFail("Initial Database Download Failed: $reason")
                        }
                    }

                }else{
                    callback.onFail("Initial Database Download Failed - Unable to read download metadata")
                }

            }
        }

    }

    app.registerReceiver( receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) )
}


private fun permanentlyStoreDb(tempFile: File): File {
    val permanentDbFile = dbHelper.getPermanentDbFile()

    try {
        if(tempFile.exists()) {
            tempFile.copyTo(
                permanentDbFile,
                true,
                1024
            )

            tempFile.delete()

        }else{
            throw IOException("Temporal DB file doesn't exist")
        }

    }catch (ioex: IOException) {
        throw IOException("Unable to copy DB to permanent storage:", ioex)
    }

    return permanentDbFile
}

/**
 * Allows download completion to be notified back to the calling view model
 */
interface DownloadCompleteCallback{
    fun onComplete(downloadId: Long)
    fun onFail(message: String)
}

}

DatabaseFileHelper 包含确定临时文件、永久数据库位置和下载将发生的数据库 URL 的逻辑。 这是我用于临时文件的逻辑:

fun getTempDbFile(): File {
    return File.createTempFile(<FILE-LOCATION>, null, app.cacheDir)
}

因此,如果您想通知正在运行的 Activity/Fragment,您只需将DownloadCompleteCallback实现传递给该组件即可获取它。

如果您使用的是 Room,只需确保您的 RoomDatabase 实现在您的getInstance方法中使用以下内容

 .createFromFile( dbFileHelper.getPermanentDbFile() )

只需从网络复制它,而不是复制表单资产。 暗示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM