@@ -29,9 +29,9 @@ import android.net.ConnectivityManager
29
29
import android.net.Uri
30
30
import android.os.Build
31
31
import android.os.Handler
32
- import android.text.Html
33
32
import android.util.Log
34
33
import androidx.core.app.NotificationCompat
34
+ import androidx.core.text.HtmlCompat
35
35
import com.rometools.rome.io.SyndFeedInput
36
36
import com.rometools.rome.io.XmlReader
37
37
import net.dankito.readability4j.extended.Readability4JExtended
@@ -61,6 +61,7 @@ import java.net.CookiePolicy
61
61
import java.util.concurrent.ExecutorCompletionService
62
62
import java.util.concurrent.Executors
63
63
import java.util.concurrent.TimeUnit
64
+ import kotlin.math.max
64
65
65
66
66
67
class FetcherService : IntentService (FetcherService : :class.java.simpleName) {
@@ -73,7 +74,7 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
73
74
74
75
private val HTTP_CLIENT : OkHttpClient = OkHttpClient .Builder ()
75
76
.connectTimeout(10 , TimeUnit .SECONDS )
76
- .readTimeout(10 , TimeUnit .SECONDS )
77
+ .readTimeout(20 , TimeUnit .SECONDS )
77
78
.cookieJar(JavaNetCookieJar (COOKIE_MANAGER ))
78
79
.build()
79
80
@@ -116,14 +117,14 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
116
117
return
117
118
}
118
119
119
- when {
120
- ACTION_MOBILIZE_FEEDS == action -> {
121
- mobilizeAllEntries()
122
- downloadAllImages()
123
- }
124
- ACTION_DOWNLOAD_IMAGES == action -> downloadAllImages()
125
- else -> { // == Constants.ACTION_REFRESH_FEEDS
126
- context.putPrefBoolean(PrefConstants .IS_REFRESHING , true )
120
+ when (action) {
121
+ ACTION_MOBILIZE_FEEDS -> {
122
+ mobilizeAllEntries()
123
+ downloadAllImages()
124
+ }
125
+ ACTION_DOWNLOAD_IMAGES -> downloadAllImages()
126
+ else -> { // == Constants.ACTION_REFRESH_FEEDS
127
+ context.putPrefBoolean(PrefConstants .IS_REFRESHING , true )
127
128
128
129
val readEntriesKeepTime = context.getPrefString(PrefConstants .KEEP_TIME , " 4" )!! .toLong() * 86400000L
129
130
val readEntriesKeepDate = if (readEntriesKeepTime > 0 ) System .currentTimeMillis() - readEntriesKeepTime else 0
@@ -135,21 +136,21 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
135
136
deleteOldEntries(unreadEntriesKeepDate, 0 )
136
137
COOKIE_MANAGER .cookieStore.removeAll() // Cookies are important for some sites, but we clean them each times
137
138
138
- // We need to use the more recent date in order to be sure to not see old entries again
139
- val acceptMinDate = Math . max(readEntriesKeepDate, unreadEntriesKeepDate)
140
-
141
- var newCount = 0
142
- if (feedId == 0L ) {
143
- newCount = refreshFeeds(acceptMinDate)
144
- } else {
145
- App .db.feedDao().findById(feedId)?.let {
146
- try {
147
- newCount = refreshFeed(it, acceptMinDate)
148
- } catch (e: Exception ) {
149
- error(" Can't fetch feed ${it.link} " , e)
150
- }
151
- }
152
- }
139
+ // We need to use the more recent date in order to be sure to not see old entries again
140
+ val acceptMinDate = max(readEntriesKeepDate, unreadEntriesKeepDate)
141
+
142
+ var newCount = 0
143
+ if (feedId == 0L || App .db.feedDao().findById(feedId)?.isGroup == true ) {
144
+ newCount = refreshFeeds(feedId, acceptMinDate)
145
+ } else {
146
+ App .db.feedDao().findById(feedId)?.let {
147
+ try {
148
+ newCount = refreshFeed(it, acceptMinDate)
149
+ } catch (e: Exception ) {
150
+ error(" Can't fetch feed ${it.link} " , e)
151
+ }
152
+ }
153
+ }
153
154
154
155
showRefreshNotification(newCount)
155
156
mobilizeAllEntries()
@@ -209,7 +210,7 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
209
210
.setTicker(text)
210
211
.setWhen(System .currentTimeMillis())
211
212
.setAutoCancel(true )
212
- .setContentTitle(context.getString(R .string.app_name) + " " + context.getString( R .string. flym_feeds))
213
+ .setContentTitle(context.getString(R .string.flym_feeds))
213
214
.setContentText(text)
214
215
215
216
context.notificationManager.notify(0 , notifBuilder.build())
@@ -223,15 +224,14 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
223
224
fun shouldDownloadPictures (): Boolean {
224
225
val fetchPictureMode = context.getPrefString(PrefConstants .PRELOAD_IMAGE_MODE , PrefConstants .PRELOAD_IMAGE_MODE__WIFI_ONLY )
225
226
226
- if (context.getPrefBoolean(PrefConstants .DISPLAY_IMAGES , true )) {
227
- if (PrefConstants .PRELOAD_IMAGE_MODE__ALWAYS == fetchPictureMode) {
228
- return true
229
- } else if (PrefConstants .PRELOAD_IMAGE_MODE__WIFI_ONLY == fetchPictureMode) {
230
- if (App .context.connectivityManager.activeNetworkInfo?.type == ConnectivityManager .TYPE_WIFI ) {
231
- return true
232
- }
233
- }
234
- }
227
+ if (context.getPrefBoolean(PrefConstants .DISPLAY_IMAGES , true )) {
228
+ if (PrefConstants .PRELOAD_IMAGE_MODE__ALWAYS == fetchPictureMode) {
229
+ return true
230
+ } else if (PrefConstants .PRELOAD_IMAGE_MODE__WIFI_ONLY == fetchPictureMode
231
+ && context.connectivityManager.activeNetworkInfo?.type == ConnectivityManager .TYPE_WIFI ) {
232
+ return true
233
+ }
234
+ }
235
235
236
236
return false
237
237
}
@@ -293,19 +293,19 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
293
293
Readability4JExtended (link, Jsoup .parse(input, null , link)).parse().articleContent?.html()?.let {
294
294
val mobilizedHtml = HtmlUtils .improveHtmlContent(it, getBaseUrl(link))
295
295
296
- @Suppress( " DEPRECATION " )
297
- if (entry.description == null || Html .fromHtml(mobilizedHtml).length > Html .fromHtml(entry.description ).length) { // If the retrieved text is smaller than the original one, then we certainly failed...
298
- if (downloadPictures) {
299
- val imagesList = HtmlUtils .getImageURLs(mobilizedHtml)
300
- if (imagesList.isNotEmpty()) {
301
- if (entry.imageLink == null ) {
302
- entry.imageLink = HtmlUtils .getMainImageURL(imagesList)
303
- }
304
- imgUrlsToDownload[entry.id] = imagesList
305
- }
306
- } else if (entry.imageLink == null ) {
307
- entry.imageLink = HtmlUtils .getMainImageURL(mobilizedHtml)
308
- }
296
+ val entryDescription = entry.description
297
+ if (entryDescription == null || HtmlCompat .fromHtml(mobilizedHtml, HtmlCompat . FROM_HTML_MODE_LEGACY ).length > HtmlCompat .fromHtml(entryDescription, HtmlCompat . FROM_HTML_MODE_LEGACY ).length) { // If the retrieved text is smaller than the original one, then we certainly failed...
298
+ if (downloadPictures) {
299
+ val imagesList = HtmlUtils .getImageURLs(mobilizedHtml)
300
+ if (imagesList.isNotEmpty()) {
301
+ if (entry.imageLink == null ) {
302
+ entry.imageLink = HtmlUtils .getMainImageURL(imagesList)
303
+ }
304
+ imgUrlsToDownload[entry.id] = imagesList
305
+ }
306
+ } else if (entry.imageLink == null ) {
307
+ entry.imageLink = HtmlUtils .getMainImageURL(mobilizedHtml)
308
+ }
309
309
310
310
success = true
311
311
@@ -359,7 +359,7 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
359
359
}
360
360
}
361
361
362
- private fun refreshFeeds (acceptMinDate : Long ): Int {
362
+ private fun refreshFeeds (feedId : Long , acceptMinDate : Long ): Int {
363
363
364
364
val executor = Executors .newFixedThreadPool(THREAD_NUMBER ) { r ->
365
365
Thread (r).apply {
@@ -368,29 +368,34 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
368
368
}
369
369
val completionService = ExecutorCompletionService <Int >(executor)
370
370
371
- var globalResult = 0
372
-
373
- val feeds = App .db.feedDao().allNonGroupFeeds
374
- for (feed in feeds) {
375
- completionService.submit {
376
- var result = 0
377
- try {
378
- result = refreshFeed(feed, acceptMinDate)
379
- } catch (e: Exception ) {
380
- error(" Can't fetch feedWithCount ${feed.link} " , e)
381
- }
371
+ var globalResult = 0
372
+ val feeds: List <Feed >
373
+ if (feedId == 0L ) {
374
+ feeds = App .db.feedDao().allNonGroupFeeds
375
+ } else {
376
+ feeds = App .db.feedDao().allFeedsInGroup(feedId)
377
+ }
378
+
379
+ for (feed in feeds) {
380
+ completionService.submit {
381
+ var result = 0
382
+ try {
383
+ result = refreshFeed(feed, acceptMinDate)
384
+ } catch (e: Exception ) {
385
+ error(" Can't fetch feedWithCount ${feed.link} " , e)
386
+ }
382
387
383
388
result
384
389
}
385
390
}
386
391
387
- for (i in 0 until feeds.size ) {
388
- try {
389
- val f = completionService.take()
390
- globalResult + = f.get()
391
- } catch (ignored: Exception ) {
392
- }
393
- }
392
+ for (i in feeds.indices ) {
393
+ try {
394
+ val f = completionService.take()
395
+ globalResult + = f.get()
396
+ } catch (ignored: Exception ) {
397
+ }
398
+ }
394
399
395
400
executor.shutdownNow() // To purge observeAll threads
396
401
@@ -408,7 +413,7 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
408
413
createCall(feed.link).execute().use { response ->
409
414
val input = SyndFeedInput ()
410
415
val romeFeed = input.build(XmlReader (response.body!! .byteStream()))
411
- entries.addAll(romeFeed.entries.asSequence().filter { it.publishedDate?.time ? : Long .MAX_VALUE > acceptMinDate }.map { it.toDbFormat(feed) })
416
+ entries.addAll(romeFeed.entries.asSequence().filter { it.publishedDate?.time ? : Long .MAX_VALUE > acceptMinDate }.map { it.toDbFormat(context, feed) })
412
417
feed.update(romeFeed)
413
418
}
414
419
} catch (t: Throwable ) {
@@ -435,15 +440,16 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
435
440
if (filterKeywordString.isNotBlank()) {
436
441
val keywordLists = filterKeywordString.split(' ,' ).map { it.trim() }
437
442
438
- if (keywordLists.isNotEmpty()) {
439
- entries.removeAll { entry ->
440
- keywordLists.any {
441
- entry.title?.contains(it, true ) == true ||
442
- entry.description?.contains(it, true ) == true
443
- }
444
- }
445
- }
446
- }
443
+ if (keywordLists.isNotEmpty()) {
444
+ entries.removeAll { entry ->
445
+ keywordLists.any {
446
+ entry.title?.contains(it, true ) == true ||
447
+ entry.description?.contains(it, true ) == true ||
448
+ entry.author?.contains(it, true ) == true
449
+ }
450
+ }
451
+ }
452
+ }
447
453
448
454
val feedBaseUrl = getBaseUrl(feed.link)
449
455
var foundExisting = false
@@ -511,9 +517,8 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
511
517
if (! File (tempImgPath).exists() && ! File (finalImgPath).exists()) {
512
518
IMAGE_FOLDER_FILE .mkdir() // create images dir
513
519
514
- // Compute the real URL (without "é", ...)
515
- @Suppress(" DEPRECATION" )
516
- val realUrl = Html .fromHtml(imgUrl).toString()
520
+ // Compute the real URL (without "é", ...)
521
+ val realUrl = HtmlCompat .fromHtml(imgUrl, HtmlCompat .FROM_HTML_MODE_LEGACY ).toString()
517
522
518
523
try {
519
524
createCall(realUrl).execute().use { response ->
@@ -541,14 +546,14 @@ class FetcherService : IntentService(FetcherService::class.java.simpleName) {
541
546
// We need to exclude favorite entries images to this cleanup
542
547
val favoriteIds = App .db.entryDao().favoriteIds
543
548
544
- IMAGE_FOLDER_FILE .listFiles().forEach { file ->
545
- // If old file and not part of a favorite entry
546
- if (file.lastModified() < keepDateBorderTime && ! favoriteIds.any { file.name.startsWith(it + ID_SEPARATOR ) }) {
547
- file.delete()
548
- }
549
- }
550
- }
551
- }
549
+ IMAGE_FOLDER_FILE .listFiles()? .forEach { file ->
550
+ // If old file and not part of a favorite entry
551
+ if (file.lastModified() < keepDateBorderTime && ! favoriteIds.any { file.name.startsWith(it + ID_SEPARATOR ) }) {
552
+ file.delete()
553
+ }
554
+ }
555
+ }
556
+ }
552
557
553
558
private fun getBaseUrl (link : String ): String {
554
559
var baseUrl = link
0 commit comments