/* This file is part of Subsonic. Subsonic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Subsonic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Subsonic. If not, see . Copyright 2010 (C) Sindre Mehus */ package net.nullsum.audinaut.provider; import android.app.SearchManager; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.SearchCritera; import net.nullsum.audinaut.domain.SearchResult; import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.service.MusicServiceFactory; import net.nullsum.audinaut.util.Util; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Provides search suggestions based on recent searches. * * @author Sindre Mehus */ public class AudinautSearchProvider extends ContentProvider { private static final String RESOURCE_PREFIX = "android.resource://net.nullsum.audinaut/"; private static final String[] COLUMNS = {"_id", SearchManager.SUGGEST_COLUMN_TEXT_1, SearchManager.SUGGEST_COLUMN_TEXT_2, SearchManager.SUGGEST_COLUMN_INTENT_DATA, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA, SearchManager.SUGGEST_COLUMN_ICON_1}; @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if (selectionArgs[0].isEmpty()) { return null; } String query = selectionArgs[0] + "*"; SearchResult searchResult = search(query); return createCursor(selectionArgs[0], searchResult); } private SearchResult search(String query) { MusicService musicService = MusicServiceFactory.getMusicService(getContext()); if (musicService == null) { return null; } try { return musicService.search(new SearchCritera(query, 5, 10, 10), getContext(), null); } catch (Exception e) { return null; } } private Cursor createCursor(String query, SearchResult searchResult) { MatrixCursor cursor = new MatrixCursor(COLUMNS); if (searchResult == null) { return cursor; } // Add all results into one pot List results = new ArrayList<>(); results.addAll(searchResult.getArtists()); results.addAll(searchResult.getAlbums()); results.addAll(searchResult.getSongs()); // For each, calculate its string distance to the query for (Object obj : results) { if (obj instanceof Artist) { Artist artist = (Artist) obj; artist.setCloseness(Util.getStringDistance(query, artist.getName())); } else { MusicDirectory.Entry entry = (MusicDirectory.Entry) obj; entry.setCloseness(Util.getStringDistance(query, entry.getTitle())); } } // Sort based on the closeness paramater Collections.sort(results, (lhs, rhs) -> { // Get the closeness of the two objects int left, right; boolean leftArtist = lhs instanceof Artist; boolean rightArtist = rhs instanceof Artist; if (leftArtist) { left = ((Artist) lhs).getCloseness(); } else { left = ((MusicDirectory.Entry) lhs).getCloseness(); } if (rightArtist) { right = ((Artist) rhs).getCloseness(); } else { right = ((MusicDirectory.Entry) rhs).getCloseness(); } if (left == right) { if (leftArtist && rightArtist) { return 0; } else if (leftArtist) { return -1; } else if (rightArtist) { return 1; } else { return 0; } } else if (left > right) { return 1; } else { return -1; } }); // Done sorting, add results to cursor for (Object obj : results) { if (obj instanceof Artist) { Artist artist = (Artist) obj; String icon = RESOURCE_PREFIX + R.drawable.ic_action_artist; cursor.addRow(new Object[]{artist.getId().hashCode(), artist.getName(), null, "ar-" + artist.getId(), artist.getName(), icon}); } else { MusicDirectory.Entry entry = (MusicDirectory.Entry) obj; if (entry.isDirectory()) { String icon = RESOURCE_PREFIX + R.drawable.ic_action_album; cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), entry.getArtist(), entry.getId(), entry.getTitle(), icon}); } else { String icon = RESOURCE_PREFIX + R.drawable.ic_action_song; String id; id = entry.getAlbumId(); String artistDisplay; if (entry.getArtist() == null) { if (entry.getAlbum() != null) { artistDisplay = entry.getAlbumDisplay(); } else { artistDisplay = ""; } } else if (entry.getAlbum() != null) { artistDisplay = entry.getArtist() + " - " + entry.getAlbumDisplay(); } else { artistDisplay = entry.getArtist(); } cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), artistDisplay, "so-" + id, entry.getTitle(), icon}); } } } return cursor; } @Override public boolean onCreate() { return false; } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues contentValues) { return null; } @Override public int delete(Uri uri, String s, String[] strings) { return 0; } @Override public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { return 0; } }