Search code examples
androidurlurisearch-suggestionandroid-searchmanager

Using a web URL for SUGGEST_COLUMN_ICON_1 for Search Suggestions


I have a SearchManager setup where a suggestions dropdown will display as the user types. The results are from my server (http). I would like to display an icon with each option (if the file in fact does exist).

Looking at the docs, I see the options for the constant column SUGGEST_COLUMN_ICON_1 allows for these options:

Column name for suggestions cursor. Optional. If your cursor includes this column, then all suggestions will be provided in a format that includes space for two small icons, one at the left and one at the right of each suggestion. The data in the column must be a resource ID of a drawable, or a URI in one of the following formats:

content (SCHEME_CONTENT)
android.resource (SCHEME_ANDROID_RESOURCE)
file (SCHEME_FILE) 

All I have is a URL. Which option would work best for me?

Here is the class where I am doing this:

public class MyCustomSuggestionProvider extends SearchRecentSuggestionsProvider {

    public static final String AUTHORITY = "---.MyCustomSuggestionProvider";
    public static final int MODE = DATABASE_MODE_QUERIES;
    private final static String[] COLUMN_NAMES = {BaseColumns._ID,
            SearchManager.SUGGEST_COLUMN_TEXT_1,
            SearchManager.SUGGEST_COLUMN_TEXT_2,
            SearchManager.SUGGEST_COLUMN_QUERY,
            SearchManager.SUGGEST_COLUMN_INTENT_DATA,
            SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
            SearchManager.SUGGEST_COLUMN_ICON_1,
            SearchManager.SUGGEST_COLUMN_INTENT_ACTION};

    public MyCustomSuggestionProvider() {
        setupSuggestions(AUTHORITY, MODE);
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {

        Cursor recentCursor = super.query(uri, projection, selection,
                selectionArgs, sortOrder);

        String query = selectionArgs[0];
        if (query == null || query.length() < 3) {
            return recentCursor;
        }

        final MatrixCursor customCursor = new MatrixCursor(COLUMN_NAMES);

        // Get web results from Retrofit Library
        List<TheProfile> suggestions = RestClient.get().getCustomSearch(query, MyApp.getUserId());

        for (TheProfile suggestion : suggestions) {


            Uri searchIconUri = Uri.parse("http:/---/profile_images/" + String.valueOf(suggestion.id) + ".png");
            try {
                customCursor.addRow(new Object[]{
                        suggestion.id, suggestion.profile, suggestion.subcategory, suggestion.profile, suggestion.profile, suggestion.subcategory, searchIconUri, "android.intent.action.SEARCH"});
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return customCursor;
    }
}

Solution

  • For those, who's still looking the answer for this question, like I did. It's pretty similar to my code, so I decided to share it. I spent hours putting this all together. Maybe, I'll save some time for someone. First of all, you'll need the Glide library.

    Add it to your app's build.gradle file:

    repositories {
        mavenCentral() // jcenter() works as well because it pulls from Maven Central
    }
    
    dependencies {
        compile 'com.github.bumptech.glide:glide:3.7.0'
        compile 'com.android.support:support-v4:19.1.0'
    }
    

    Now let's make some changes to the code from the question (in MyCustomSuggestionProvider class): Put it inside your for (TheProfile suggestion : suggestions) {

    FutureTarget<File> futureTarget  = Glide
            .with(getContext().getApplicationContext())
            .load(searchIcon)
            .downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
    
    File cacheFile = futureTarget.get();
    Uri searchIconUri = Uri.fromFile(cacheFile);
    

    Pay attention to this line of code: .with(getContext().getApplicationContext()) That's very important to get Application Context, not just Context, since we're not going to show bmp in ImageView. Official Glide documentation for this type of Glide usage.

    And after all you can call:

    // do things with bitmap and then release when finished:
    Glide.clear(futureTarget);