安卓筆記 - 2020-03-20 - 封裝下載器

下載器封裝,便于開發(fā)跷坝,使用downloadManager〉锏铮可以監(jiān)聽下載進(jìn)度柴钻,監(jiān)聽方法里使用了協(xié)程,也可以使用線程進(jìn)行監(jiān)聽垢粮,同時(shí)使用contentProvider來(lái)獲取全局上下文贴届,所以在使用中無(wú)需傳遞上下文。

此文僅用于本人記錄開發(fā)經(jīng)驗(yàn)所用蜡吧。

```

/**

*@Company NSNTC

*@author Chord.p

*@time 2020/3/20 9:44 AM

*speak softly love

*

* 下載器毫蚓,暫時(shí)無(wú)法管理多下載任務(wù)狀態(tài)

*/

class DownloadHelper {

//下載器

? ? private var downloadManager : DownloadManager = DownloadProvider.mContext.getSystemService(Context.DOWNLOAD_SERVICE)as DownloadManager

//下載時(shí)相關(guān)配置

? ? private var options = DownloadOptions()

//下載開始監(jiān)聽器,回調(diào)參數(shù)為下載id斩跌,可通過(guò)該id對(duì)該下載任務(wù)進(jìn)行管理

? ? var preparListener : DownloadBaseListener? =null

? ? //下載中監(jiān)聽器绍些,回調(diào)參數(shù)為下載進(jìn)度,范圍在0~100

? ? var downloadingListener : DownloadBaseListener? =null

? ? //下載失敗監(jiān)聽器

? ? var downloadFailListener : DownloadNoteListener? =null

? ? //下載延遲監(jiān)聽器

? ? var downloadPenddingListener : DownloadNoteListener? =null

? ? //下載暫停監(jiān)聽器

? ? var downloadPauseListener : DownloadNoteListener? =null

? ? //下載成功監(jiān)聽器耀鸦,回調(diào)參數(shù)為本地存儲(chǔ)路徑

? ? var downloadSuccessListener : DownloadBaseListener? =null

? ? //下載周期監(jiān)聽器

? ? var downloadListener : DownloadListener? =null

? ? //下載id

? ? var id =0L

? ? //下載地址

? ? var path =""

? ? companion object {

val instance : DownloadHelperby lazy(::DownloadHelper)

fun apkDownload(url : String,name : String,deleteIfExists : Boolean =true) {

instance.downloadApk(url, name, deleteIfExists)

}

fun downloadFile(url : String,name : String,deleteIfExists : Boolean =true) {

instance.download(url, name, deleteIfExists)

}

/**

* 請(qǐng)使用DownloadOptions下的常量進(jìn)行設(shè)定

*/

? ? ? ? fun setNetType(type : String) {

instance.options.netType = type

}

fun setDownloadPath(path : String) {

instance.options.downloadPath = File(path)

}

fun setDownloadPath(path : File) {

instance.options.downloadPath = path

}

/**

* 請(qǐng)使用DownloadManager.Request 下的常量進(jìn)行設(shè)定

*/

? ? ? ? fun setShowNotify(showType : Int) {

instance.options.showNotify = showType

}

fun setDownloadListener(listener : DownloadListener) {

instance.downloadListener = listener

}

fun setPrepardListener(listener: DownloadBaseListener) {

instance.preparListener = listener

}

fun setNotifyTitle(title: String) {

instance.options.title = title

}

fun setNotifyDesc(desc : String) {

instance.options.desc = desc

}

}

fun downloadApk(url : String,name : String,deleteIfExists : Boolean =true) {

var request = DownloadManager.Request(Uri.parse(url))

request.setAllowedOverRoaming(false)

when(options.netType) {

DOWNLOAD_ONLY_PHONE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE)

DOWNLOAD_ONLY_WIFI -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)

DOWNLOAD_NO_CARE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)

}

//設(shè)置是否顯示通知欄

? ? ? ? request.setNotificationVisibility(options.showNotify)

//設(shè)置通知欄標(biāo)題

? ? ? ? request.setTitle(options.title)

//設(shè)置通知欄簡(jiǎn)介

? ? ? ? request.setDescription(options.desc)

request.setVisibleInDownloadsUi(true)

//指定下載的文件類型為APK

? ? ? ? request.setMimeType("application/vnd.android.package-archive")

var file = File(options.downloadPath,name)

//若已存在該文件柬批,則刪除

? ? ? ? if (file.exists()) {

if (deleteIfExists) {

file.delete()

}else{

Log.e("download","file is exists")

return

? ? ? ? ? ? }

}

request.setDestinationUri(Uri.fromFile(file))

path = file.absolutePath

? ? ? ? id =downloadManager.enqueue(request)

preparListener?.onNotice?.invoke(id)

downloadListener?.onPrepare(id)

//注冊(cè)廣播啸澡,接收下載任務(wù)廣播

? ? ? ? DownloadProvider.mContext.registerReceiver(receiver,IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))

downloadProgress(id)

}

fun download(url : String,name : String,deleteIfExists : Boolean =true) {

var request = DownloadManager.Request(Uri.parse(url))

request.setAllowedOverRoaming(false)

when(options.netType) {

DOWNLOAD_ONLY_PHONE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE)

DOWNLOAD_ONLY_WIFI -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)

DOWNLOAD_NO_CARE -> request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)

}

//設(shè)置是否顯示通知欄

? ? ? ? request.setNotificationVisibility(options.showNotify)

//設(shè)置通知欄標(biāo)題

? ? ? ? request.setTitle(options.title)

//設(shè)置通知欄簡(jiǎn)介

? ? ? ? request.setDescription(options.desc)

request.setVisibleInDownloadsUi(true)

var file = File(options.downloadPath,name)

//若已存在該文件,則刪除

? ? ? ? if (file.exists()) {

if (deleteIfExists) {

file.delete()

}else{

Log.e("download","file is exists")

return

? ? ? ? ? ? }

}

request.setDestinationUri(Uri.fromFile(file))

path = file.absolutePath

? ? ? ? id =downloadManager.enqueue(request)

preparListener?.onNotice?.invoke(id)

downloadListener?.onPrepare(id)

//注冊(cè)廣播氮帐,接收下載任務(wù)廣播

? ? ? ? DownloadProvider.mContext.registerReceiver(receiver,IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))

downloadProgress(id)

}

//開協(xié)程用于監(jiān)聽下載進(jìn)度

? ? fun downloadProgress(id : Long) {

GlobalScope.launch {

? ? ? ? ? ? var breakFlag =true

? ? ? ? ? ? var query = DownloadManager.Query()

do {

query.setFilterById(id)

var cursor =downloadManager.query(query)

if (cursor.moveToFirst()) {

var bytes_downloaded = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))

var bytes_total = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))

var dl_progress = (bytes_downloaded *100 / bytes_total)

withContext(Dispatchers.Main){

? ? ? ? ? ? ? ? ? ? ? ? downloadingListener?.onNotice?.invoke(dl_progress)

downloadListener?.onDownloading(dl_progress)

}

? ? ? ? ? ? ? ? when {

dl_progress ==100 -> breakFlag =false

? ? ? ? ? ? ? ? ? ? cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL -> breakFlag =false

? ? ? ? ? ? ? ? ? ? cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED -> breakFlag =false

? ? ? ? ? ? ? ? }

}

cursor.close()

delay(200)

}while (breakFlag)

}

? ? }

//廣播接受者嗅虏,接收下載任務(wù)的廣播

? ? private var receiver =object : BroadcastReceiver() {

override fun onReceive(context: Context?, intent: Intent?) {

var query = DownloadManager.Query()

query.setFilterById(id)

var cursor =downloadManager.query(query)

if (cursor.moveToFirst()) {

when(cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) {

//正在下載

? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_RUNNING -> {

}

//下載失敗

? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_FAILED -> {

downloadFailListener?.onNotice?.invoke()

downloadListener?.onFail()

cursor.close()

DownloadProvider.mContext.unregisterReceiver(this)

}

//下載暫停

? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_PAUSED -> {

downloadPauseListener?.onNotice?.invoke()

downloadListener?.onPaused()

}

//下載成功

? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_SUCCESSFUL -> {

downloadSuccessListener?.onNotice?.invoke(path)

downloadListener?.onSuccess(path)

cursor.close()

DownloadProvider.mContext.unregisterReceiver(this)

}

//下載延遲

? ? ? ? ? ? ? ? ? ? DownloadManager.STATUS_PENDING -> {

downloadPenddingListener?.onNotice?.invoke()

downloadListener?.onPending()

}

}

}

}

}


//立即安裝app

fun installApk(path : String) {

DownloadProvider.mContext.startActivity(Intent().apply {

? ? ? ? this.action = Intent.ACTION_VIEW

? ? ? ? this.flags = Intent.FLAG_ACTIVITY_NEW_TASK

? ? ? ? this.setDataAndType(Uri.parse(path),"application/vnd.android.package-archive")

})

}

fun installApk(path : Uri) {

DownloadProvider.mContext.startActivity(Intent().apply {

? ? ? ? this.action = Intent.ACTION_VIEW

? ? ? ? this.flags = Intent.FLAG_ACTIVITY_NEW_TASK

? ? ? ? this.setDataAndType(path,"application/vnd.android.package-archive")

})

}

class DownloadBaseListener (onNotice : (value :T) -> Unit) {var onNotice = onNotice }

class DownloadNoteListener(onNotice : () -> Unit) {var onNotice = onNotice }

interface DownloadListener {

open fun onPrepare(id: Long) {}

open fun onDownloading(progress : Int) {}

open fun onFail() {}

open fun onPaused() {}

open fun onSuccess(path : String) {}

open fun onPending() {}

}

//用于存儲(chǔ)下載時(shí)所需的配置

? ? class DownloadOptions(showNotify : Int = DownloadManager.Request.VISIBILITY_HIDDEN,title : String ="",desc : String ="") {

//是否展示通知欄

? ? ? ? var showNotify = showNotify

//通知欄標(biāo)題

? ? ? ? var title = title

//通知欄簡(jiǎn)介

? ? ? ? var desc = desc

//下載環(huán)境

? ? ? ? var netType =DOWNLOAD_NO_CARE

? ? ? ? //下載存儲(chǔ)地址

? ? ? ? var downloadPath = DownloadProvider.mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)

companion object {

//網(wǎng)絡(luò)環(huán)境

? ? ? ? ? ? const val DOWNLOAD_ONLY_PHONE ="phone"

? ? ? ? ? ? const val DOWNLOAD_ONLY_WIFI ="wifi"

? ? ? ? ? ? const val DOWNLOAD_NO_CARE ="noCare"

? ? ? ? }

}

//用于獲取全局上下文

? ? class DownloadProvider : ContentProvider() {

companion object {

lateinit var mContext : Context

}

override fun insert(uri: Uri, values: ContentValues?): Uri? {

return null

? ? ? ? }

override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? {

return null

? ? ? ? }

override fun onCreate(): Boolean {

mContext =context!!

return false

? ? ? ? }

override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int {

return 0

? ? ? ? }

override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {

return 0

? ? ? ? }

override fun getType(uri: Uri): String? {

return null

? ? ? ? }

}

}

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市上沐,隨后出現(xiàn)的幾起案子皮服,更是在濱河造成了極大的恐慌,老刑警劉巖参咙,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件龄广,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蕴侧,警方通過(guò)查閱死者的電腦和手機(jī)择同,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)净宵,“玉大人敲才,你說(shuō)我怎么就攤上這事≡衿希” “怎么了紧武?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)敏储。 經(jīng)常有香客問(wèn)我阻星,道長(zhǎng),這世上最難降的妖魔是什么虹曙? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任迫横,我火速辦了婚禮嚣潜,結(jié)果婚禮上口猜,老公的妹妹穿的比我還像新娘畅姊。我一直安慰自己,他們只是感情好疏哗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著禾怠,像睡著了一般返奉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吗氏,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天芽偏,我揣著相機(jī)與錄音,去河邊找鬼弦讽。 笑死污尉,一個(gè)胖子當(dāng)著我的面吹牛膀哲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播被碗,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼某宪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了锐朴?” 一聲冷哼從身側(cè)響起兴喂,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎焚志,沒(méi)想到半個(gè)月后衣迷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡酱酬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年蘑险,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岳悟。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡佃迄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贵少,到底是詐尸還是另有隱情呵俏,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布滔灶,位于F島的核電站普碎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏录平。R本人自食惡果不足惜麻车,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斗这。 院中可真熱鬧动猬,春花似錦、人聲如沸表箭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)免钻。三九已至彼水,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間极舔,已是汗流浹背凤覆。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拆魏,地道東北人盯桦。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓澡绩,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親俺附。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肥卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容