Merge pull request #4837 from damoasda/localfeed-any-image
Use any image for local folders
This commit is contained in:
commit
41d23fa671
|
@ -6,15 +6,13 @@ import android.media.MediaMetadataRetriever;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -34,6 +32,8 @@ import de.danoeh.antennapod.core.util.DownloadError;
|
||||||
|
|
||||||
public class LocalFeedUpdater {
|
public class LocalFeedUpdater {
|
||||||
|
|
||||||
|
static final String[] PREFERRED_FEED_IMAGE_FILENAMES = { "folder.jpg", "Folder.jpg", "folder.png", "Folder.png" };
|
||||||
|
|
||||||
public static void updateFeed(Feed feed, Context context) {
|
public static void updateFeed(Feed feed, Context context) {
|
||||||
try {
|
try {
|
||||||
tryUpdateFeed(feed, context);
|
tryUpdateFeed(feed, context);
|
||||||
|
@ -97,18 +97,7 @@ public class LocalFeedUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> iconLocations = Arrays.asList("folder.jpg", "Folder.jpg", "folder.png", "Folder.png");
|
feed.setImageUrl(getImageUrl(context, documentFolder));
|
||||||
for (String iconLocation : iconLocations) {
|
|
||||||
DocumentFile image = documentFolder.findFile(iconLocation);
|
|
||||||
if (image != null) {
|
|
||||||
feed.setImageUrl(image.getUri().toString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (StringUtils.isBlank(feed.getImageUrl())) {
|
|
||||||
// set default feed image
|
|
||||||
feed.setImageUrl(getDefaultIconUrl(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
feed.getPreferences().setAutoDownload(false);
|
feed.getPreferences().setAutoDownload(false);
|
||||||
feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
|
feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NO);
|
||||||
|
@ -122,6 +111,31 @@ public class LocalFeedUpdater {
|
||||||
DBTasks.updateFeed(context, feed, removeUnlistedItems);
|
DBTasks.updateFeed(context, feed, removeUnlistedItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the image URL for the local feed.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static String getImageUrl(@NonNull Context context, @NonNull DocumentFile documentFolder) {
|
||||||
|
// look for special file names
|
||||||
|
for (String iconLocation : PREFERRED_FEED_IMAGE_FILENAMES) {
|
||||||
|
DocumentFile image = documentFolder.findFile(iconLocation);
|
||||||
|
if (image != null) {
|
||||||
|
return image.getUri().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the first image in the folder if existing
|
||||||
|
for (DocumentFile file : documentFolder.listFiles()) {
|
||||||
|
String mime = file.getType();
|
||||||
|
if (mime != null && (mime.startsWith("image/jpeg") || mime.startsWith("image/png"))) {
|
||||||
|
return file.getUri().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// use default icon as fallback
|
||||||
|
return getDefaultIconUrl(context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the URL of the default icon for a local feed. The URL refers to an app resource file.
|
* Returns the URL of the default icon for a local feed. The URL refers to an app resource file.
|
||||||
*/
|
*/
|
||||||
|
@ -161,7 +175,7 @@ public class LocalFeedUpdater {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadMetadata(FeedItem item, DocumentFile file, Context context) throws Exception {
|
private static void loadMetadata(FeedItem item, DocumentFile file, Context context) {
|
||||||
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
|
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
|
||||||
mediaMetadataRetriever.setDataSource(context, file.getUri());
|
mediaMetadataRetriever.setDataSource(context, file.getUri());
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.feed;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.MediaMetadataRetriever;
|
import android.media.MediaMetadataRetriever;
|
||||||
|
import android.net.Uri;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
@ -33,8 +34,11 @@ import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.endsWith;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
@ -93,7 +97,7 @@ public class LocalFeedUpdaterTest {
|
||||||
public void testUpdateFeed_AddNewFeed() {
|
public void testUpdateFeed_AddNewFeed() {
|
||||||
// check for empty database
|
// check for empty database
|
||||||
List<Feed> feedListBefore = DBReader.getFeedList();
|
List<Feed> feedListBefore = DBReader.getFeedList();
|
||||||
assertTrue(feedListBefore.isEmpty());
|
assertThat(feedListBefore, is(empty()));
|
||||||
|
|
||||||
callUpdateFeed(LOCAL_FEED_DIR2);
|
callUpdateFeed(LOCAL_FEED_DIR2);
|
||||||
|
|
||||||
|
@ -139,7 +143,7 @@ public class LocalFeedUpdaterTest {
|
||||||
callUpdateFeed(LOCAL_FEED_DIR2);
|
callUpdateFeed(LOCAL_FEED_DIR2);
|
||||||
|
|
||||||
Feed feedAfter = verifySingleFeedInDatabase();
|
Feed feedAfter = verifySingleFeedInDatabase();
|
||||||
assertTrue(feedAfter.getImageUrl().contains("local-feed2/folder.png"));
|
assertThat(feedAfter.getImageUrl(), endsWith("local-feed2/folder.png"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -151,7 +155,7 @@ public class LocalFeedUpdaterTest {
|
||||||
|
|
||||||
Feed feedAfter = verifySingleFeedInDatabase();
|
Feed feedAfter = verifySingleFeedInDatabase();
|
||||||
String resourceEntryName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
String resourceEntryName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
||||||
assertTrue(feedAfter.getImageUrl().contains(resourceEntryName));
|
assertThat(feedAfter.getImageUrl(), endsWith(resourceEntryName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,6 +184,65 @@ public class LocalFeedUpdaterTest {
|
||||||
assertEquals(24, calendar.get(Calendar.SECOND));
|
assertEquals(24, calendar.get(Calendar.SECOND));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_EmptyFolder() {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder();
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
String defaultImageName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
||||||
|
assertThat(imageUrl, endsWith(defaultImageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_NoImageButAudioFiles() {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"));
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
String defaultImageName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
||||||
|
assertThat(imageUrl, endsWith(defaultImageName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_PreferredImagesFilenames() {
|
||||||
|
for (String filename : LocalFeedUpdater.PREFERRED_FEED_IMAGE_FILENAMES) {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
|
mockDocumentFile(filename, "image/jpeg")); // image MIME type doesn't matter
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
assertThat(imageUrl, endsWith(filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_OtherImageFilenameJpg() {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
|
mockDocumentFile("my-image.jpg", "image/jpeg"));
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
assertThat(imageUrl, endsWith("my-image.jpg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_OtherImageFilenameJpeg() {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
|
mockDocumentFile("my-image.jpeg", "image/jpeg"));
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
assertThat(imageUrl, endsWith("my-image.jpeg"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_OtherImageFilenamePng() {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
|
mockDocumentFile("my-image.png", "image/png"));
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
assertThat(imageUrl, endsWith("my-image.png"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetImageUrl_OtherImageFilenameUnsupportedMimeType() {
|
||||||
|
DocumentFile documentFolder = mockDocumentFolder(mockDocumentFile("audio.mp3", "audio/mp3"),
|
||||||
|
mockDocumentFile("my-image.svg", "image/svg+xml"));
|
||||||
|
String imageUrl = LocalFeedUpdater.getImageUrl(context, documentFolder);
|
||||||
|
String defaultImageName = context.getResources().getResourceEntryName(R.raw.local_feed_default_icon);
|
||||||
|
assertThat(imageUrl, endsWith(defaultImageName));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill ShadowMediaMetadataRetriever with dummy duration and title.
|
* Fill ShadowMediaMetadataRetriever with dummy duration and title.
|
||||||
*
|
*
|
||||||
|
@ -238,4 +301,26 @@ public class LocalFeedUpdaterTest {
|
||||||
List<FeedItem> feedItems = DBReader.getFeedItemList(feed);
|
List<FeedItem> feedItems = DBReader.getFeedItemList(feed);
|
||||||
assertEquals(expectedItemCount, feedItems.size());
|
assertEquals(expectedItemCount, feedItems.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a DocumentFile mock object.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private static DocumentFile mockDocumentFile(@NonNull String fileName, @NonNull String mimeType) {
|
||||||
|
DocumentFile file = mock(DocumentFile.class);
|
||||||
|
when(file.getName()).thenReturn(fileName);
|
||||||
|
when(file.getUri()).thenReturn(Uri.parse("file:///path/" + fileName));
|
||||||
|
when(file.getType()).thenReturn(mimeType);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a DocumentFile folder mock object with a list of files.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private static DocumentFile mockDocumentFolder(DocumentFile... files) {
|
||||||
|
DocumentFile documentFolder = mock(DocumentFile.class);
|
||||||
|
when(documentFolder.listFiles()).thenReturn(files);
|
||||||
|
return documentFolder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue