How to query SearchProviders like android's QSB?

285 Views Asked by At

I'm attempting to query all available search providers similar to how the Quick Search Box does it, to get a list of search suggestions. I'm ignoring ones I don't have permissions to read. Now, everything works for providers which return results immediately.

However, for ones which go away and get results from the web, I can't get any results. An example of one of these is the IMDB app. Often I get a cursor returned of null, other times I get some cached results which are not correct.

Anyone know how best to do this?

In example below, (which runs in a thread), I simply wait for a while to ensure any network stuff is complete. I await callbacks in ChangeObserver and MyDataObserver but I get nothing. I've tried using LoaderManager instead too, but no difference. I've looked at source for Android's quick search box but can't find any clues.

SearchManager searchManager = (SearchManager)ProgDialog.this.getContext().getApplicationContext().getSystemService(Context.SEARCH_SERVICE);
List<SearchableInfo> searchables = searchManager.getSearchablesInGlobalSearch();

for(SearchableInfo si : searchables)
{
    if(si.getSuggestPackage() == null) continue;

    String query = title;
    Uri.Builder uriBuilder = new Uri.Builder();
    uriBuilder.authority(si.getSuggestAuthority());
    uriBuilder.scheme(ContentResolver.SCHEME_CONTENT);
    if(si.getSuggestPath() != null)
    {
        uriBuilder.appendEncodedPath(si.getSuggestPath());
    }
    uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);

    // get the query selection, may be null
    String selection = si.getSuggestSelection();

    // inject query, either as selection args or inline
    String[] selArgs = null;
    if (selection != null) {    // use selection if provided
        selArgs = new String[] { query };
    } else {                    // no selection, use REST pattern
        uriBuilder.appendPath(query);
    }

    Uri uri = uriBuilder.build();

    if(!canRead(uri))
    {
        continue;
    }
    c = context.getApplicationContext().getContentResolver().query(uri, null,
             selection, selArgs, null);
    if(c != null)
    {

       c.registerContentObserver(new ChangeObserver(c));
       c.registerDataSetObserver(new MyDataSetObserver(si.getSuggestPackage(), c));
       c.setNotificationUri(context.getContentResolver(), uri);
       Thread.sleep(8000);
1

There are 1 best solutions below

0
On

I adapted your code a little bit and now it works (for me). Keep in mind to set permissions to access data (Contacts, Bookmarks,...).

        if (searchableInfo.getSuggestPackage() == null)
            continue;

        Uri.Builder uriBuilder = new Uri.Builder();
        uriBuilder.authority(searchableInfo.getSuggestAuthority());
        uriBuilder.scheme(ContentResolver.SCHEME_CONTENT);

        String path = searchableInfo.getSuggestPath();
        if (path != null)
            uriBuilder.appendEncodedPath(path);
        else
            uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY);

        // get the query selection, may be null
        String selection = searchableInfo.getSuggestSelection();

        // inject query, either as selection args or inline
        String[] selArgs = null;
        if (selection != null)
            // use selection if provided
            selArgs = new String[] { query };
        else
            // no selection, use REST pattern
            uriBuilder.appendPath(query);

        Uri uri = uriBuilder.build();