diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ca5b1e976..648bb7323 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -18,6 +18,7 @@
+
servicePendingIntent(context: Context, action: String): PendingIntent? {
- return PendingIntent.getService(
- context,
- 0,
- Intent(context, T::class.java).apply { this.action = action },
- PendingIntent.FLAG_UPDATE_CURRENT
- )
+ inline fun servicePendingIntent(
+ context: Context,
+ action: String,
+ bundle: Bundle? = null
+ ): PendingIntent? {
+ val intent = Intent(context, T::class.java)
+ intent.action = action
+ bundle?.let {
+ intent.putExtras(bundle)
+ }
+ return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
- inline fun activityPendingIntent(context: Context, action: String): PendingIntent? {
- return PendingIntent.getActivity(
- context,
- 0,
- Intent(context, T::class.java).apply { this.action = action },
- PendingIntent.FLAG_UPDATE_CURRENT
- )
+ inline fun activityPendingIntent(
+ context: Context,
+ action: String,
+ bundle: Bundle? = null
+ ): PendingIntent? {
+ val intent = Intent(context, T::class.java)
+ intent.action = action
+ bundle?.let {
+ intent.putExtras(bundle)
+ }
+ return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/service/DownloadService.kt b/app/src/main/java/io/legado/app/service/DownloadService.kt
index 7a77bb7a5..5b7522869 100644
--- a/app/src/main/java/io/legado/app/service/DownloadService.kt
+++ b/app/src/main/java/io/legado/app/service/DownloadService.kt
@@ -1,46 +1,172 @@
package io.legado.app.service
+import android.app.DownloadManager
+import android.content.BroadcastReceiver
+import android.content.Context
import android.content.Intent
+import android.content.IntentFilter
+import android.os.Handler
import androidx.core.app.NotificationCompat
+import androidx.core.os.bundleOf
import io.legado.app.R
import io.legado.app.base.BaseService
import io.legado.app.constant.AppConst
import io.legado.app.constant.IntentAction
import io.legado.app.help.IntentHelp
+import org.jetbrains.anko.downloadManager
+import org.jetbrains.anko.notificationManager
+
class DownloadService : BaseService() {
- private val notificationBuilder by lazy {
- val builder = NotificationCompat.Builder(this, AppConst.channelIdDownload)
- .setSmallIcon(R.drawable.ic_download)
- .setOngoing(true)
- .setContentTitle(getString(R.string.action_download))
- builder.addAction(
- R.drawable.ic_stop_black_24dp,
- getString(R.string.cancel),
- IntentHelp.servicePendingIntent(this, IntentAction.stop)
- )
- builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
+ private val downloads = hashMapOf()
+ private val completeDownloads = hashSetOf()
+ private val handler = Handler()
+ private val runnable = Runnable {
+ checkDownloadState()
+ }
+
+ private val downloadReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ queryState()
+ }
}
override fun onCreate() {
super.onCreate()
- updateNotification("准备下载")
+ registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
+ }
+
+ override fun onTaskRemoved(rootIntent: Intent?) {
+ super.onTaskRemoved(rootIntent)
+ stopSelf()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ unregisterReceiver(downloadReceiver)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when (intent?.action) {
-
+ IntentAction.start -> startDownload(
+ intent.getLongExtra("downloadId", 0),
+ intent.getStringExtra("fileName") ?: "未知文件"
+ )
+ IntentAction.play -> {
+ val id = intent.getLongExtra("downloadId", 0)
+ if (downloads[id]?.endsWith(".apk") == true) {
+ installApk(id)
+ }
+ }
+ IntentAction.stop -> {
+ val downloadId = intent.getLongExtra("downloadId", 0)
+ if (downloadId > 0) {
+ downloadManager.remove(downloadId)
+ notificationManager.cancel(downloadId.toInt())
+ } else {
+ stopSelf()
+ }
+ }
}
return super.onStartCommand(intent, flags, startId)
}
+ private fun startDownload(downloadId: Long, fileName: String) {
+ if (downloadId > 0) {
+ downloads[downloadId] = fileName
+ queryState()
+ checkDownloadState()
+ }
+ }
+
+ private fun checkDownloadState() {
+ handler.removeCallbacks(runnable)
+ queryState()
+ handler.postDelayed(runnable, 1000)
+ }
+
+ //查询下载进度
+ private fun queryState() {
+ val ids = downloads.keys
+ val query = DownloadManager.Query()
+ query.setFilterById(*ids.toLongArray())
+ val cursor = downloadManager.query(query)
+ if (!cursor.moveToFirst()) return
+ val id = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID))
+ val progress: Int =
+ cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
+ val max: Int =
+ cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
+ val status = when (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))) {
+ DownloadManager.STATUS_PAUSED -> "暂停"
+ DownloadManager.STATUS_PENDING -> "待下载"
+ DownloadManager.STATUS_RUNNING -> "下载中"
+ DownloadManager.STATUS_SUCCESSFUL -> {
+ if (!completeDownloads.contains(id)) {
+ completeDownloads.add(id)
+ if (downloads[id]?.endsWith(".apk") == true) {
+ installApk(id)
+ }
+ }
+ "下载完成"
+ }
+ DownloadManager.STATUS_FAILED -> "下载失败"
+ else -> "未知状态"
+ }
+ updateNotification(id, "${downloads[id]} $status", max, progress)
+ if (!cursor.isClosed) {
+ cursor.close()
+ }
+ }
+
+ private fun installApk(downloadId: Long) {
+ val downloadFileUri = downloadManager.getUriForDownloadedFile(downloadId)
+ downloadFileUri?.let {
+ val install = Intent(Intent.ACTION_VIEW)
+ install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive")
+ install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ startActivity(install)
+ }
+ }
+
/**
* 更新通知
*/
- private fun updateNotification(content: String) {
+ private fun updateNotification(downloadId: Long, content: String, max: Int, progress: Int) {
+ val notificationBuilder = NotificationCompat.Builder(this, AppConst.channelIdDownload)
+ .setSmallIcon(R.drawable.ic_download)
+ .setOngoing(true)
+ .setContentTitle(getString(R.string.action_download))
+ notificationBuilder.setContentIntent(
+ IntentHelp.servicePendingIntent(
+ this,
+ IntentAction.play,
+ bundleOf("downloadId" to downloadId)
+ )
+ )
+ notificationBuilder.addAction(
+ R.drawable.ic_stop_black_24dp,
+ getString(R.string.cancel),
+ IntentHelp.servicePendingIntent(
+ this,
+ IntentAction.stop,
+ bundleOf("downloadId" to downloadId)
+ )
+ )
+ notificationBuilder.setDeleteIntent(
+ IntentHelp.servicePendingIntent(
+ this,
+ IntentAction.stop,
+ bundleOf("downloadId" to downloadId)
+ )
+ )
+ notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
notificationBuilder.setContentText(content)
+ notificationBuilder.setProgress(max, progress, false)
+ notificationBuilder.setAutoCancel(true)
val notification = notificationBuilder.build()
- startForeground(AppConst.notificationIdDownload, notification)
+ startForeground(downloadId.toInt(), notification)
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/service/help/Download.kt b/app/src/main/java/io/legado/app/service/help/Download.kt
new file mode 100644
index 000000000..cddbf59b6
--- /dev/null
+++ b/app/src/main/java/io/legado/app/service/help/Download.kt
@@ -0,0 +1,26 @@
+package io.legado.app.service.help
+
+import android.content.Context
+import android.content.Intent
+import io.legado.app.constant.IntentAction
+import io.legado.app.service.DownloadService
+
+object Download {
+
+ fun start(context: Context, downloadId: Long, fileName: String) {
+ Intent(context, DownloadService::class.java).let {
+ it.action = IntentAction.start
+ it.putExtra("downloadId", downloadId)
+ it.putExtra("fileName", fileName)
+ context.startService(it)
+ }
+ }
+
+ fun stop(context: Context) {
+ Intent(context, DownloadService::class.java).let {
+ it.action = IntentAction.stop
+ context.startService(it)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
index 841a5b9a9..b8d71b515 100644
--- a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
+++ b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
@@ -324,7 +324,9 @@ class BgTextConfigDialog : BaseDialogFragment(), FileChooserDialog.CallBack {
val fontName = FileUtils.getName(config.textFont)
val fontPath =
FileUtils.getPath(requireContext().externalFilesDir, "font", fontName)
- FileUtils.getFile(configDir, fontName).copyTo(File(fontPath))
+ if (!FileUtils.exist(fontPath)) {
+ FileUtils.getFile(configDir, fontName).copyTo(File(fontPath))
+ }
config.textFont = fontPath
}
if (config.bgType() == 2) {
diff --git a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
index e2834e456..c66cad69f 100644
--- a/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
+++ b/app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
@@ -15,12 +15,14 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.lib.theme.DrawableUtils
import io.legado.app.lib.theme.primaryTextColor
+import io.legado.app.service.help.Download
import io.legado.app.ui.filechooser.FileChooserDialog
import io.legado.app.ui.filechooser.FilePicker
import io.legado.app.utils.*
import kotlinx.android.synthetic.main.activity_rss_read.*
import kotlinx.coroutines.launch
import org.apache.commons.text.StringEscapeUtils
+import org.jetbrains.anko.downloadManager
import org.jetbrains.anko.share
import org.jsoup.Jsoup
@@ -160,13 +162,12 @@ class ReadRssActivity : VMBaseActivity(R.layout.activity_rss_r
request.setAllowedOverRoaming(true)
// 允许下载的网路类型
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)
- request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
+ request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)
// 设置下载文件保存的路径和文件名
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
- val downloadManager = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
// 添加一个下载任务
val downloadId = downloadManager.enqueue(request)
- print(downloadId)
+ Download.start(this, downloadId, fileName)
}
}
}