Put feeds colors retrieval in a foreground service

This commit is contained in:
Shinokuni 2019-10-19 18:15:27 +02:00
parent d8196a610a
commit 36dc0cd115
10 changed files with 127 additions and 51 deletions

View File

@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".utils.ReadropsApp"
@ -17,6 +18,8 @@
android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning">
<service android:name=".utils.feedscolors.FeedsColorsIntentService" />
<activity android:name=".activities.SettingsActivity" />
<activity

View File

@ -1,12 +1,10 @@
package com.readrops.app.repositories;
import android.app.Application;
import android.graphics.Bitmap;
import android.util.Patterns;
import android.content.Intent;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.palette.graphics.Palette;
import com.readrops.app.database.Database;
import com.readrops.app.database.entities.Feed;
@ -14,18 +12,17 @@ import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.entities.Item;
import com.readrops.app.database.entities.account.Account;
import com.readrops.app.database.entities.account.AccountType;
import com.readrops.app.utils.feedscolors.FeedsColorsIntentService;
import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.HtmlParser;
import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.Utils;
import com.readrops.app.utils.feedscolors.FeedColorsKt;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
public abstract class ARepository<T> {
@ -93,47 +90,17 @@ public abstract class ARepository<T> {
return database.feedDao().getFeedCount(accountId);
}
protected void setFaviconUtils(List<Feed> feeds) {
Observable.<Feed>create(emitter -> {
for (Feed feed : feeds) {
setFaviconUtils(feed);
emitter.onNext(feed);
}
}).subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.doOnNext(feed1 -> database.feedDao().updateColors(feed1.getId(),
feed1.getTextColor(), feed1.getBackgroundColor()))
.subscribe();
protected void setFeedColors(Feed feed) {
FeedColorsKt.setFeedColors(feed);
database.feedDao().updateColors(feed.getId(),
feed.getTextColor(), feed.getBackgroundColor());
}
protected void setFaviconUtils(Feed feed) throws IOException {
String favUrl;
protected void setFeedsColors(List<Feed> feeds) {
Intent intent = new Intent(application, FeedsColorsIntentService.class);
intent.putParcelableArrayListExtra(FeedsColorsIntentService.FEEDS, new ArrayList<>(feeds));
if (feed.getIconUrl() != null)
favUrl = feed.getIconUrl();
else
favUrl = HtmlParser.getFaviconLink(feed.getSiteUrl());
if (favUrl != null && Patterns.WEB_URL.matcher(favUrl).matches()) {
feed.setIconUrl(favUrl);
setFeedColors(favUrl, feed);
}
}
protected void setFeedColors(String favUrl, Feed feed) {
Bitmap favicon = Utils.getImageFromUrl(favUrl);
if (favicon != null) {
Palette palette = Palette.from(favicon).generate();
if (palette.getDominantSwatch() != null) {
feed.setTextColor(palette.getDominantSwatch().getRgb());
}
if (palette.getMutedSwatch() != null) {
feed.setBackgroundColor(palette.getMutedSwatch().getRgb());
}
}
application.startService(intent);
}
public static ARepository repositoryFactory(Account account, AccountType accountType, Application application) throws Exception {

View File

@ -183,10 +183,8 @@ public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
List<Long> insertedFeedsIds = database.feedDao().feedsUpsert(feeds, account);
List<Feed> insertedFeeds = new ArrayList<>();
if (!insertedFeedsIds.isEmpty()) {
insertedFeeds.addAll(database.feedDao().selectFromIdList(insertedFeedsIds));
setFaviconUtils(insertedFeeds);
setFeedsColors(database.feedDao().selectFromIdList(insertedFeedsIds));
}
}

View File

@ -195,7 +195,7 @@ public class LocalFeedRepository extends ARepository<Void> {
if (database.feedDao().feedExists(dbFeed.getUrl(), account.getId()))
return null; // feed already inserted
setFaviconUtils(dbFeed);
setFeedColors(dbFeed);
dbFeed.setAccountId(account.getId());
// we need empty headers to query the feed just after, without any 304 result

View File

@ -274,7 +274,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
List<Feed> insertedFeeds = new ArrayList<>();
if (!insertedFeedsIds.isEmpty()) {
insertedFeeds.addAll(database.feedDao().selectFromIdList(insertedFeedsIds));
setFaviconUtils(insertedFeeds);
setFeedsColors(insertedFeeds);
}
return insertedFeeds;

View File

@ -1,18 +1,41 @@
package com.readrops.app.utils;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import com.facebook.stetho.Stetho;
import com.readrops.app.BuildConfig;
import com.readrops.app.R;
import io.reactivex.plugins.RxJavaPlugins;
public class ReadropsApp extends Application {
public static final String FEEDS_COLORS_CHANNEL_ID = "feedsColorsChannel";
@Override
public void onCreate() {
super.onCreate();
RxJavaPlugins.setErrorHandler(e -> { });
Stetho.initializeWithDefaults(this);
if (BuildConfig.DEBUG) {
Stetho.initializeWithDefaults(this);
}
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel feedsColorsChannel = new NotificationChannel(FEEDS_COLORS_CHANNEL_ID,
getString(R.string.feeds_colors), NotificationManager.IMPORTANCE_DEFAULT);
feedsColorsChannel.setDescription(getString(R.string.get_feeds_colors));
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(feedsColorsChannel);
}
}
}

View File

@ -0,0 +1,33 @@
package com.readrops.app.utils.feedscolors
import androidx.palette.graphics.Palette
import com.readrops.app.database.entities.Feed
import com.readrops.app.utils.HtmlParser
import com.readrops.app.utils.Utils
fun setFeedColors(feed: Feed) {
getFaviconLink(feed)
if (feed.iconUrl != null) {
val bitmap = Utils.getImageFromUrl(feed.iconUrl)
val palette = Palette.from(bitmap).generate()
val dominantSwatch = palette.dominantSwatch
if (dominantSwatch != null)
feed.textColor = dominantSwatch.rgb
val mutedSwatch = palette.mutedSwatch
if (mutedSwatch != null)
feed.backgroundColor = mutedSwatch.rgb
}
}
fun getFaviconLink(feed: Feed) {
feed.iconUrl = if (feed.iconUrl != null)
feed.iconUrl
else
HtmlParser.getFaviconLink(feed.siteUrl)
}

View File

@ -0,0 +1,48 @@
package com.readrops.app.utils.feedscolors
import android.app.IntentService
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.readrops.app.R
import com.readrops.app.database.Database
import com.readrops.app.database.entities.Feed
import com.readrops.app.utils.ReadropsApp
class FeedsColorsIntentService : IntentService("FeedsColorsIntentService") {
override fun onHandleIntent(intent: Intent?) {
val feeds: List<Feed> = intent!!.getParcelableArrayListExtra(FEEDS)
val database = Database.getInstance(this)
val notificationBuilder = NotificationCompat.Builder(this, ReadropsApp.FEEDS_COLORS_CHANNEL_ID)
.setContentTitle(getString(R.string.get_feeds_colors))
.setProgress(feeds.size, 0, false)
.setSmallIcon(R.drawable.ic_readrops)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setOnlyAlertOnce(true)
startForeground(NOTIFICATION_ID, notificationBuilder.build())
val notificationManager = NotificationManagerCompat.from(this)
var feedsNb = 0
feeds.forEach {
notificationBuilder.setContentText(it.name)
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
setFeedColors(it)
database.feedDao().updateColors(it.id, it.textColor, it.backgroundColor)
notificationBuilder.setProgress(feeds.size, ++feedsNb, false)
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build())
}
stopForeground(true)
}
companion object {
private const val NOTIFICATION_ID = 1
const val FEEDS = "feeds"
}
}

View File

@ -84,5 +84,7 @@
<string name="no_item">Aucun item</string>
<string name="no_feed_found">Aucun flux trouvé</string>
<string name="feed_insertion_error">Erreur pour le flux %1$s</string>
<string name="get_feeds_colors">Récupération des couleurs des flux</string>
<string name="feeds_colors">Couleurs des flux</string>
</resources>

View File

@ -92,4 +92,6 @@
<string name="no_item">No item</string>
<string name="no_feed_found">No feed found</string>
<string name="feed_insertion_error">Error for feed %1$s</string>
<string name="get_feeds_colors">Get feeds colors</string>
<string name="feeds_colors">Feeds Colors</string>
</resources>