Merge pull request #2258 from MeirSD/develop
Enable support for Android Auto with support for OnPlayFromSearch
This commit is contained in:
commit
7da9e8876b
@ -37,6 +37,8 @@
|
||||
android:backupAgent=".core.backup.OpmlBackupAgent"
|
||||
android:restoreAnyVersion="true"
|
||||
android:logo="@drawable/ic_launcher">
|
||||
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
|
||||
android:resource="@drawable/ic_notification" />
|
||||
<meta-data
|
||||
android:name="com.google.android.backup.api_key"
|
||||
android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/>
|
||||
@ -51,6 +53,13 @@
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name=
|
||||
"android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||
<category android:name=
|
||||
"android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
@ -365,6 +374,10 @@
|
||||
<meta-data
|
||||
android:name="de.danoeh.antennapod.core.glide.ApGlideModule"
|
||||
android:value="GlideModule" />
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
4
app/src/main/res/xml/automotive_app_desc.xml
Normal file
4
app/src/main/res/xml/automotive_app_desc.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses name="media"/>
|
||||
</automotiveApp>
|
@ -15,6 +15,7 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@ -49,9 +50,11 @@ import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.R;
|
||||
import de.danoeh.antennapod.core.event.MessageEvent;
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.MediaType;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
||||
@ -60,6 +63,7 @@ import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.FeedSearcher;
|
||||
import de.danoeh.antennapod.core.util.IntList;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
|
||||
@ -363,6 +367,19 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
|
||||
}
|
||||
|
||||
private MediaBrowserCompat.MediaItem createBrowsableMediaItemForFeed(Feed feed) {
|
||||
MediaDescriptionCompat description = new MediaDescriptionCompat.Builder()
|
||||
.setMediaId("FeedId:" + Long.toString(feed.getId()))
|
||||
.setTitle(feed.getTitle())
|
||||
.setDescription(feed.getDescription())
|
||||
.setIconUri(Uri.parse(feed.getImageLocation()))
|
||||
.setSubtitle(feed.getCustomTitle())
|
||||
.setMediaUri(Uri.parse(feed.getLink()))
|
||||
.build();
|
||||
return new MediaBrowserCompat.MediaItem(description,
|
||||
MediaBrowserCompat.MediaItem.FLAG_BROWSABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadChildren(@NonNull String parentId,
|
||||
@NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
|
||||
@ -371,6 +388,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
if (parentId.equals(getResources().getString(R.string.app_name))) {
|
||||
// Root List
|
||||
mediaItems.add(createBrowsableMediaItemForRoot());
|
||||
List<Feed> feeds = DBReader.getFeedList();
|
||||
for (Feed feed: feeds) {
|
||||
mediaItems.add(createBrowsableMediaItemForFeed(feed));
|
||||
}
|
||||
} else if (parentId.equals(getResources().getString(R.string.queue_label))){
|
||||
// Child List
|
||||
try {
|
||||
@ -380,6 +401,14 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (parentId.startsWith("FeedId:")) {
|
||||
Long feedId = Long.parseLong(parentId.split(":")[1]);
|
||||
List<FeedItem> feedItems = DBReader.getFeedItemList(DBReader.getFeed(feedId));
|
||||
for (FeedItem feedItem: feedItems) {
|
||||
if(feedItem.getMedia() != null && feedItem.getMedia().getMediaItem() != null) {
|
||||
mediaItems.add(feedItem.getMedia().getMediaItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
result.sendResult(mediaItems);
|
||||
}
|
||||
@ -1635,8 +1664,22 @@ public class PlaybackService extends MediaBrowserServiceCompat {
|
||||
|
||||
@Override
|
||||
public void onPlayFromSearch (String query, Bundle extras) {
|
||||
//Until we parse the query just play from queue
|
||||
Log.d(TAG, "onPlayFromSearch query=" + query + " extras=" + extras.toString());
|
||||
|
||||
List<SearchResult> results = FeedSearcher.performSearch(getBaseContext(),query,0);
|
||||
for( SearchResult result : results) {
|
||||
try {
|
||||
FeedMedia p = ((FeedItem)(result.getComponent())).getMedia();
|
||||
mediaPlayer.playMediaObject(p, !p.localFileAvailable(), true, true);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, e.getMessage());
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
onPlay();
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -677,6 +677,54 @@ public final class DBTasks {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the authors of FeedItems of a specific Feed for a given
|
||||
* string.
|
||||
*
|
||||
* @param context Used for accessing the DB.
|
||||
* @param feedID The id of the feed whose items should be searched.
|
||||
* @param query The search string.
|
||||
* @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems.
|
||||
*/
|
||||
public static FutureTask<List<FeedItem>> searchFeedItemAuthor(final Context context,
|
||||
final long feedID, final String query) {
|
||||
return new FutureTask<>(new QueryTask<List<FeedItem>>(context) {
|
||||
@Override
|
||||
public void execute(PodDBAdapter adapter) {
|
||||
Cursor searchResult = adapter.searchItemAuthors(feedID,
|
||||
query);
|
||||
List<FeedItem> items = DBReader.extractItemlistFromCursor(searchResult);
|
||||
DBReader.loadAdditionalFeedItemListData(items);
|
||||
setResult(items);
|
||||
searchResult.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the feed identifiers of FeedItems of a specific Feed for a given
|
||||
* string.
|
||||
*
|
||||
* @param context Used for accessing the DB.
|
||||
* @param feedID The id of the feed whose items should be searched.
|
||||
* @param query The search string.
|
||||
* @return A FutureTask object that executes the search request and returns the search result as a List of FeedItems.
|
||||
*/
|
||||
public static FutureTask<List<FeedItem>> searchFeedItemFeedIdentifier(final Context context,
|
||||
final long feedID, final String query) {
|
||||
return new FutureTask<>(new QueryTask<List<FeedItem>>(context) {
|
||||
@Override
|
||||
public void execute(PodDBAdapter adapter) {
|
||||
Cursor searchResult = adapter.searchItemFeedIdentifiers(feedID,
|
||||
query);
|
||||
List<FeedItem> items = DBReader.extractItemlistFromCursor(searchResult);
|
||||
DBReader.loadAdditionalFeedItemListData(items);
|
||||
setResult(items);
|
||||
searchResult.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the descriptions of FeedItems of a specific Feed for a given
|
||||
* string.
|
||||
|
@ -35,11 +35,13 @@ public class FeedSearcher {
|
||||
*/
|
||||
public static List<SearchResult> performSearch(final Context context,
|
||||
final String query, final long selectedFeed) {
|
||||
final int values[] = {2, 1, 0, 0};
|
||||
final int values[] = {2, 1, 0, 0, 0, 0};
|
||||
final String[] subtitles = {context.getString(R.string.found_in_title_label),
|
||||
context.getString(R.string.found_in_chapters_label),
|
||||
context.getString(R.string.found_in_shownotes_label),
|
||||
context.getString(R.string.found_in_shownotes_label)};
|
||||
context.getString(R.string.found_in_shownotes_label),
|
||||
context.getString(R.string.found_in_authors_label),
|
||||
context.getString(R.string.found_in_feeds_label)};
|
||||
|
||||
List<SearchResult> result = new ArrayList<>();
|
||||
|
||||
@ -48,6 +50,8 @@ public class FeedSearcher {
|
||||
tasks.add(DBTasks.searchFeedItemChapters(context, selectedFeed, query));
|
||||
tasks.add(DBTasks.searchFeedItemDescription(context, selectedFeed, query));
|
||||
tasks.add(DBTasks.searchFeedItemContentEncoded(context, selectedFeed, query));
|
||||
tasks.add(DBTasks.searchFeedItemAuthor(context, selectedFeed, query));
|
||||
tasks.add(DBTasks.searchFeedItemFeedIdentifier(context, selectedFeed, query));
|
||||
|
||||
for (FutureTask<List<FeedItem>> task : tasks) {
|
||||
task.run();
|
||||
|
@ -1589,6 +1589,52 @@ public class PodDBAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor searchItemAuthors(long feedID, String query) {
|
||||
if (feedID != 0) {
|
||||
// search items in specific feed
|
||||
return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS
|
||||
+ " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS+"."+KEY_FEED+"="+TABLE_NAME_FEEDS+"."+KEY_ID
|
||||
+ " WHERE " + KEY_FEED
|
||||
+ "=? AND " + KEY_AUTHOR + " LIKE '%"
|
||||
+ prepareSearchQuery(query) + "%' ORDER BY "
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC",
|
||||
new String[]{String.valueOf(feedID)}
|
||||
);
|
||||
} else {
|
||||
// search through all items
|
||||
return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS
|
||||
+ " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS+"."+KEY_FEED+"="+TABLE_NAME_FEEDS+"."+KEY_ID
|
||||
+ " WHERE " + KEY_AUTHOR + " LIKE '%"
|
||||
+ prepareSearchQuery(query) + "%' ORDER BY "
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC",
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor searchItemFeedIdentifiers(long feedID, String query) {
|
||||
if (feedID != 0) {
|
||||
// search items in specific feed
|
||||
return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS
|
||||
+ " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS+"."+KEY_FEED+"="+TABLE_NAME_FEEDS+"."+KEY_ID
|
||||
+ " WHERE " + KEY_FEED
|
||||
+ "=? AND " + KEY_FEED_IDENTIFIER + " LIKE '%"
|
||||
+ prepareSearchQuery(query) + "%' ORDER BY "
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC",
|
||||
new String[]{String.valueOf(feedID)}
|
||||
);
|
||||
} else {
|
||||
// search through all items
|
||||
return db.rawQuery("SELECT " + TextUtils.join(", ", FEEDITEM_SEL_FI_SMALL) + " FROM " + TABLE_NAME_FEED_ITEMS
|
||||
+ " JOIN " + TABLE_NAME_FEEDS + " ON " + TABLE_NAME_FEED_ITEMS+"."+KEY_FEED+"="+TABLE_NAME_FEEDS+"."+KEY_ID
|
||||
+ " WHERE " + KEY_FEED_IDENTIFIER + " LIKE '%"
|
||||
+ prepareSearchQuery(query) + "%' ORDER BY "
|
||||
+ TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE + " DESC",
|
||||
null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor searchItemChapters(long feedID, String searchQuery) {
|
||||
final String query;
|
||||
if (feedID != 0) {
|
||||
|
@ -436,6 +436,8 @@
|
||||
<string name="search_hint">Search for episodes</string>
|
||||
<string name="found_in_shownotes_label">Found in show notes</string>
|
||||
<string name="found_in_chapters_label">Found in chapters</string>
|
||||
<string name="found_in_authors_label">Found in authors</string>
|
||||
<string name="found_in_feeds_label">Found in feeds</string>
|
||||
<string name="search_status_no_results">No results were found</string>
|
||||
<string name="search_label">Search</string>
|
||||
<string name="found_in_title_label">Found in title</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user