如何使用服务下载文件

时间:2018-08-25 07:01:26

标签: android kotlin android-service android-file android-download-manager

我的目标是在后台下载带有Service(请建议一个更好的选择)的文件,而无需与应用进行交互,从而可以触发下载( startService ),只要它收到广播,即已将新文本复制到剪贴板并且该文本具有可下载的扩展名。

以下实现使用PR Downloader(库)下载文件,但未下载文件。

我通常会收到一个错误并记录响应。

onError. isServerError = false. isConnectionError = true

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.package.name">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        ...>

        <activity
            android:name=".Activities.MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
            <intent-filter>
                ...
            </intent-filter>
        </activity>

        ...
        <service android:name=".DownloadService" />
    </application>
</manifest>

MainActivity.kt

class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val clipBoard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
            clipBoard.addPrimaryClipChangedListener {
                val primaryClip = clipBoard.primaryClip

                if (primaryClip == null || primaryClip.itemCount > 0 && primaryClip.getItemAt(0).text == null)
                    return@addPrimaryClipChangedListener  
                val serviceIntent = Intent(this, DownloadService::class.java)
                val clip = primaryClip.getItemAt(0).text.toString()
                if (clip.contains(".mp3")) {
                    Log.d("MainActivity","$clip")
                    serviceIntent.putExtra(DOWNLOAD_URL_KEY, clip)
                    serviceIntent.putExtra(DOWNLOAD_FILE_NAME_KEY, getFileName(clip))
                    startService(serviceIntent)
                }
            }
        }
    }

DownloadService.kt

class DownloadService : Service() {
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        val url = intent?.getStringExtra(DOWNLOAD_URL_KEY)
        val fileName = intent?.getStringExtra(DOWNLOAD_FILE_NAME_KEY)
        Log("onStartCommand. FileName = $fileName Download URL = $url")

        if (url != null)
            downoadFile(url, fileName)

        return super.onStartCommand(intent, flags, startId)
    }
    fun downoadFile(download_url: String, fileName: String?) {
        val dirPath ="/Music Downloader/$fileName.mp3"
        val downloadId = PRDownloader.download(download_url, dirPath, fileName)
                .build()
                .setOnStartOrResumeListener {

                }
                .setOnPauseListener {}
                .setOnCancelListener {}
                .setOnProgressListener { progress ->

                    Log("Progress = ${((progress.currentBytes / progress.totalBytes) * 100) as Int}%")
                }
                .start(object : OnDownloadListener {
                    override fun onError(error: com.downloader.Error?) {
                        Log("onError. ServerError = ${error?.isServerError}. ConnectionError = ${error?.isConnectionError}")
                    }

                    override fun onDownloadComplete() {
                        Log("onDownloadComplete")
                    }
                })
        Log("dirPath = $dirPath, download_url = $download_url, Download ID = $downloadId")

    }
}

我也尝试使用Fetch,但结果相同-文件未下载。

但是我注意到获取和解析JSON / Xml文件与VOLLEY(:)兼容,我知道这是2018年。我保证我会改用Retrofit。

请,我在做什么错?如何使用服务下载文件。

更新

我尝试在主活动中运行代码,但仍然无法正常工作。 我正在用android 8.1进行测试,我猜库PR-Downloader出了些问题

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        PRDownloader.initialize(getApplicationContext())
        val download_url = "https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg?cs=srgb&dl=beautiful-bloom-blooming-658687.jpg"
      download(download_url)
}
fun downoad(url: String, fileName: String) {
        val dirPath = "/File Downloader/" + fileName
        val downloadId = PRDownloader.download(url, dirPath, fileName)
                .build()
                .setOnStartOrResumeListener {

                }
                .setOnPauseListener {}
                .setOnCancelListener {}
                .setOnProgressListener { progress ->

                    Log("Progress = ${((progress.currentBytes / progress.totalBytes) * 100) as Int}%")
                }
                .start(object : OnDownloadListener {
                    override fun onError(error: com.downloader.Error?) {
                        Log("onError. isServerError = ${error?.isServerError}. isConnectionError = ${error?.isConnectionError}")
                    }

                    override fun onDownloadComplete() {
                        Log("onDownloadComplete")
                    }
                })
    }

2 个答案:

答案 0 :(得分:0)

原来的问题是您的 download_url ,似乎“ images.pexels.com”不允许连接其照片。我测试了以下代码(这是我实现的纯Java下载器),并且出现了Connection.refused异常。使用https://html.com/wp-content/uploads/flamingo.jpghttps://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg尝试自己的代码,看看会得到什么

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    download().execute("https://images.pexels.com/photos/658687/pexels-photo-658687.jpeg",
            Environment.getExternalStorageDirectory().path+"/myFolder/", "pexels-photo-658687.jpeg")
}

class download : AsyncTask<String, String, String>() {
    override fun doInBackground(vararg p0: String?): String? {
        val url = URL(p0[0])
        val buf = ByteArray(1024)
        var byteRead: Int
        val p = File(p0[1])
        p.mkdirs()
        val f = File(p0[1], p0[2])
        f.createNewFile()
        var outStream = BufferedOutputStream(
                FileOutputStream(p0[1] + p0[2]))

        val conn = url.openConnection()
        var `is` = conn.getInputStream()
        byteRead = `is`!!.read(buf)
        while (byteRead != -1) {
            outStream.write(buf, 0, byteRead)
            byteRead = `is`.read(buf)
        }
        `is`.close()
        outStream.close()
        return null;
    }
}

答案 1 :(得分:0)

使用DownloadManager类:

private var dm: DownloadManager? = null
companion object {
        lateinit var receiver: BroadcastReceiver
    }

在您的onCreate中调用此方法:

private fun initbroadCastReceiver() {

        receiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                val action = intent.action
                if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
                    val downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)
                    val query = Query()
                    query.setFilterById(enqueue)
                    val c = dm!!.query(query)
                    if (c.moveToFirst()) {
                        val columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS)
                        if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
                            isDownload = true
                            downloadImage.setImageResource(R.drawable.icon_download_grey)
                            downloadImage.setBackground(ContextCompat.getDrawable(baseActivity, R.drawable.circle_background_grey))
                            SQLHelper.updateData(bookEntity.id)
                            showToast("Download completed")
                        }
                    }
                }
            }
        }
    }

onClick下载:

downloadImage.setOnClickListener(View.OnClickListener
        {
            if (bookEntity.isDownload == 0 && isDownload == false) {
                if (Misc.isNetworkAvailable(baseActivity)) {
                    dm = baseActivity.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
                    val request = Request(
                            Uri.parse(EnvironmentConstant.BOOK_DOWNLOAD_URL + bookEntity.id))
                            .setTitle(""Title)
                            .setDestinationInExternalFilesDir(baseActivity,path)
                            .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                    enqueue = dm!!.enqueue(request)
                } else {
                    showAlertDialog()
                }
            } else {
                alreadyDownloadAlert()
            }
        })