Использование SUGGEST_COLUMN_ICON_1 SearchManager для отображения локального файла

Я реализую свой собственный SearchRecentSuggestionsProvider, и все работает, кроме одного: я не могу заставить поиск устройств отображать значки для результатов. Я хочу отображать изображения из папки данных моего приложения (расположенной по адресу /{sdcard}/Android/data/package_name/files/)

Согласно документации, это достижимо с помощью SearchManager.SUGGEST_COLUMN_ICON_1, и это по-видимому, поддерживает ряд схем, в том числе ContentResolver.SCHEME_FILE, то есть file. Вот цитата из официальных документов:

Имя столбца для курсора предложений. Необязательно. Если ваш курсор включает этот столбец, все предложения будут предоставлены в формате, который включает место для двух маленьких значков, одного слева и одного справа от каждого предложения. Данные в столбце должны быть идентификатором ресурса drawable или URI в одном из следующих форматов:

содержание (SCHEME_CONTENT)

android.resource (SCHEME_ANDROID_RESOURCE)

файл (SCHEME_FILE)

Я пробовал ряд очевидных вещей, включая ручное создание файла URI и автоматическое создание с использованием Uri.Builder(). Ничего из этого не сработало.

Я также обнаружил, что кто-то еще спрашивает о том же в группах Google, и, к сожалению, на него нет ответа: https://groups.google.com/forum/#!topic/android-developers/MJj7GIaONjc

У кого-нибудь есть опыт заставить поиск устройства отображать локальные изображения с устройства?

ОБНОВЛЕНИЕ (15 декабря): я только что попробовал использовать ContentProvider с SearchView в качестве информации для поиска, и это работает точно так, как ожидалось, включая изображения обложки. Но глобальный поиск его не показывает...


person Michell Bak    schedule 05.11.2013    source источник
comment
Какую структуру файлов URI вы пробовали?   -  person ianhanniballake    schedule 06.11.2013
comment
Я пробовал file://{file_path}, file:/{file_path}, а также {file_path}.   -  person Michell Bak    schedule 06.11.2013
comment
Интересно, возможно, вам придется реализовать свой собственный ContentProvider для отображения изображений в папке data вашего приложения. Вы пробовали это? Может стоит попробовать, тем более, что это не слишком сложно. В качестве альтернативы вы пытались загрузить изображение по схеме file:// из более общедоступного места? Например корень сд карты?   -  person MH.    schedule 15.11.2013
comment
Я бы с удовольствием попробовал, но я только что обновил все свои устройства до Android 4.4, и по какой-то причине это означает, что я больше не могу искать содержимое установленных приложений. Все, что работало раньше, включая Google Play, больше не отображается в части поиска Google для планшетов и телефонов. Странный...   -  person Michell Bak    schedule 15.11.2013
comment
Только что создал вопрос об этой конкретной проблеме: stackoverflow.com/questions/20001979/   -  person Michell Bak    schedule 15.11.2013
comment
Я только что попытался использовать file:// и file:/ для общедоступного файла (папки со скриншотами), и это все равно не сработало. Возможно, придется создать ContentProvider, чтобы он работал - просто странно, когда в документации говорится, что он должен работать.   -  person Michell Bak    schedule 15.11.2013
comment
У меня работает следующее: "'" + uri + "' AS " + SearchManager.SUGGEST_COLUMN_ICON_1 где uri = Uri.fromFile(new File("/path/to/file")). Обратите внимание, что uri необходимо заключать в одинарные кавычки.   -  person Vikram    schedule 16.11.2013
comment
Спасибо, попробую, как только смогу. Не удается заставить работать глобальный поиск на Android 4.4, поэтому мне понадобится телефон друга.   -  person Michell Bak    schedule 16.11.2013
comment
@user2558882 user2558882 Только что попробовал и до сих пор не могу заставить его работать. Можете ли вы добавить решение в качестве ответа с немного большим количеством кода?   -  person Michell Bak    schedule 16.11.2013
comment
Конечно. Вы видите исключение (возможно, молчаливое)? Или это просто не работает?   -  person Vikram    schedule 16.11.2013
comment
Не заметил никаких исключений, но, по общему признанию, я не искал их в выводе Logcat. Он просто отображает значок приложения там, где он должен отображать изображения.   -  person Michell Bak    schedule 16.11.2013


Ответы (2)


У меня была аналогичная проблема, и я не мог заставить работать другие решения. Наконец, я заменил курсор новым, содержащим данные, которые мне нужны в query().

public class RecentQueriesProvider extends SearchRecentSuggestionsProvider {
    public final static String AUTHORITY = "com.package.RecentQueriesProvider";
    public final static int MODE = DATABASE_MODE_QUERIES;

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

    // We override query() to replace the history icon in the recent searches suggestions. We create a new cursor
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor superCursor = super.query(uri, projection, selection, selectionArgs, sortOrder);
        Uri iconUri = Uri.parse("android.resource://" + getContext().getPackageName() + "/drawable/ic_action_time");
        MatrixCursor newCursor = new MatrixCursor(superCursor.getColumnNames());
        superCursor.moveToFirst();
        while (superCursor.moveToNext()){
            newCursor.addRow(new Object[]{
                    superCursor.getInt(superCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT)),
                    iconUri,
                    superCursor.getString(superCursor.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1)),
                    superCursor.getString(superCursor.getColumnIndex("suggest_intent_query")),
                    superCursor.getInt(superCursor.getColumnIndex("_id"))
            });
        }
       return newCursor;
    }
}
person znat    schedule 16.05.2014

Один из способов — скопировать исходный код из android.content.SearchRecentSuggestionsProvider, поместить его в свой класс, расширяющий ContentProvider, и настроить setupSuggestions(String, int). В частности, вы бы изменили это:

Uri uriFile = Uri.fromFile(new File("path/to/file"));

mSuggestionProjection = new String [] {
        "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,

        // Here, you would return a file uri: 'uriFile'
        "'android.resource://system/"
                + com.android.internal.R.drawable.ic_menu_recent_history + "' AS "
                        + SearchManager.SUGGEST_COLUMN_ICON_1,
        "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
        "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
        "_id"
};

Хотя я предпочитаю следующее. Расширьте SearchRecentSuggestionsProvider и переопределите метод query(...). Здесь перехватите SearchManager.SUGGEST_URI_PATH_QUERY и верните курсор.

public class SearchSuggestionProvider extends SearchRecentSuggestionsProvider {

    private UriMatcher matcher;

    private static final int URI_MATCH_SUGGEST = 1;

    public SearchSuggestionProvider() {
        super();

        matcher = new UriMatcher(UriMatcher.NO_MATCH);

        // Add uri to return URI_MATCH_SUGGEST
        matcher.addURI(SearchSuggestionProvider.class.getName(), 
                         SearchManager.SUGGEST_URI_PATH_QUERY, URI_MATCH_SUGGEST);

        setupSuggestions(SearchSuggestionProvider.class.getName(), 
                                                           DATABASE_MODE_QUERIES);
    }

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

        // special case for actual suggestions (from search manager)
        if (matcher.match(uri) == URI_MATCH_SUGGEST) {

            // File to use
            File f = new File("/path/to/file");

            Uri uriFile = Uri.fromFile(f);

            final String[] PROJECTION = new String[] {
                "_id", 
                "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,                
                "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
                "'" + uriFile + "'" + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1,
            };

            final Uri URI = Uri.parse("content://" + 
                        SearchSuggestionProvider.class.getName() + "/suggestions");

            // return cursor
            return getContext().getContentResolver().query(
                URI, 
                PROJECTION, 
                "display1 LIKE ?", 
                new String[] {selectionArgs[0] + "%"}, 
                "date DESC");          
        }

        // Let super method handle the query if the check fails
        return super.query(uri, projection, selection, selectionArgs, sortOrder);
    }
}
person Vikram    schedule 16.11.2013
comment
Возможно, я был немного расплывчатым в своем первоначальном вопросе. Если это так, извините. Вот скриншот того, чего я достиг: mizuu.tv/wp -content/uploads/2013/11/miz_global_search.jpg - person Michell Bak; 16.11.2013
comment
Результаты поступают из базы данных SQLite, которую я запрашиваю в переопределенном методе query(...). Я бы хотел, чтобы рядом с каждым результатом отображалось изображение обложки. Это решение кажется полезным для показа только одного изображения, если я не ошибаюсь. - person Michell Bak; 16.11.2013
comment
@MichellBak Прежде всего, приложение выглядит потрясающе, отличная работа! Я (отчасти) понимаю, что вы пытаетесь сделать. И я буду честен, я не думаю, что знаю ответ на этот вопрос. Что может сработать: добавьте в таблицу еще один столбец для хранения изображения Uri. Добавьте еще один элемент в массив PROJECTION: "iconuri AS " + SearchManager.SUGGEST_COLUMN_ICON_1. - person Vikram; 17.11.2013
comment
Большое спасибо! По возможности попробую. Не похоже, что есть какие-либо другие предложения от людей — кроме создания поставщика контента и проверки того, работает ли он — поэтому я награжу вас наградой, так как срок ее действия истекает, и пока оставлю вопрос без ответа. - person Michell Bak; 17.11.2013
comment
@MichellBak Нет, спасибо за щедрость, хотя я не сильно помог. Я попробую снова в ближайшие выходные и отпишусь, если найду способ. - person Vikram; 18.11.2013
comment
Спасибо, я ценю это! :-) Это досадная проблема, особенно если вы не можете проверить это самостоятельно, потому что все ваши устройства работают под управлением 4.4 :-( - person Michell Bak; 18.11.2013