修复bug, 添加订阅下载完自动安装

pull/375/head
gedoor 4 years ago
parent cd8615075c
commit e55227a2a9
  1. 1
      app/src/main/AndroidManifest.xml
  2. 37
      app/src/main/java/io/legado/app/help/IntentHelp.kt
  3. 156
      app/src/main/java/io/legado/app/service/DownloadService.kt
  4. 26
      app/src/main/java/io/legado/app/service/help/Download.kt
  5. 4
      app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
  6. 7
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt

@ -18,6 +18,7 @@
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<application
android:name=".App"

@ -3,6 +3,7 @@ package io.legado.app.help
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Bundle
import io.legado.app.R
import org.jetbrains.anko.toast
@ -32,21 +33,29 @@ object IntentHelp {
}
}
inline fun <reified T> 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 <reified T> 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 <reified T> 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 <reified T> 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)
}
}

@ -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<DownloadService>(this, IntentAction.stop)
)
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
private val downloads = hashMapOf<Long, String>()
private val completeDownloads = hashSetOf<Long>()
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<DownloadService>(
this,
IntentAction.play,
bundleOf("downloadId" to downloadId)
)
)
notificationBuilder.addAction(
R.drawable.ic_stop_black_24dp,
getString(R.string.cancel),
IntentHelp.servicePendingIntent<DownloadService>(
this,
IntentAction.stop,
bundleOf("downloadId" to downloadId)
)
)
notificationBuilder.setDeleteIntent(
IntentHelp.servicePendingIntent<DownloadService>(
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)
}
}

@ -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)
}
}
}

@ -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) {

@ -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<ReadRssViewModel>(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)
}
}
}

Loading…
Cancel
Save