未调用内容提供商查询()(Android 电视)

Content provider query() not being called (Android TV)

我正在尝试将我的应用程序包含到 Android TV 全局搜索中,根据 documentation 我必须创建以下内容:

当然还要将它们包含在清单中。 这就是我所做的,我的内容提供者非常简单。它没有 return 任何数据,但是当它收到 query() 调用时,它会在日志中打印一些它尚未完成的行。

public class VideoContentProvider extends ContentProvider {
private static String TAG = "VideoContentProvider";
public static String AUTHORITY = "test.tvsearch";

// UriMatcher stuff
private static final int SEARCH_SUGGEST = 0;
private static final int REFRESH_SHORTCUT = 1;
private static final UriMatcher URI_MATCHER = buildUriMatcher();

//private VideoDatabase mVideoDatabase;

/**
 * Builds up a UriMatcher for search suggestion and shortcut refresh queries.
 */
private static UriMatcher buildUriMatcher() {
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    // to get suggestions...
    Log.d(TAG, "suggest_uri_path_query: " + SearchManager.SUGGEST_URI_PATH_QUERY);
    matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
    matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
    return matcher;
}

@Override
public boolean onCreate() {
    Log.d(TAG, "onCreate");
    //mVideoDatabase = new VideoDatabase(getContext());
    return true;
}

/**
 * Handles all the video searches and suggestion queries from the Search Manager.
 * When requesting a specific word, the uri alone is required.
 * When searching all of the video for matches, the selectionArgs argument must carry
 * the search query as the first element.
 * All other arguments are ignored.
 */
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                    String sortOrder) {
    // Use the UriMatcher to see what kind of query we have and format the db query accordingly
    switch (URI_MATCHER.match(uri)) {
        case SEARCH_SUGGEST:
            Log.d(TAG, "search suggest: " + selectionArgs[0] + " URI: " + uri);
            if (selectionArgs == null) {
                throw new IllegalArgumentException(
                        "selectionArgs must be provided for the Uri: " + uri);
            }
            Log.i("...", "WORKED");
            return null;
        default:
            throw new IllegalArgumentException("Unknown Uri: " + uri);
    }
}

/**
 * This method is required in order to query the supported types.
 * It's also useful in our own query() method to determine the type of Uri received.
 */
@Override
public String getType(Uri uri) {
    switch (URI_MATCHER.match(uri)) {
        case SEARCH_SUGGEST:
            return SearchManager.SUGGEST_MIME_TYPE;
        case REFRESH_SHORTCUT:
            return SearchManager.SHORTCUT_MIME_TYPE;
        default:
            throw new IllegalArgumentException("Unknown URL " + uri);
    }
}

// Other required implementations...

@Override
public Uri insert(Uri uri, ContentValues values) {
    throw new UnsupportedOperationException();
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    throw new UnsupportedOperationException();
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    throw new UnsupportedOperationException();
}

}

Searchable.xml:

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="test leanback api demo"
    android:hint="searching for videos test"
    android:searchSettingsDescription="settings text desc"
    android:searchSuggestAuthority="test.tvsearch"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestSelection=" ?"
    android:searchSuggestThreshold="1"
    android:includeInGlobalSearch="true"
    >

此代码几乎直接来自 Android TV leanback 示例,我提取了这部分,因为它是处理全局搜索的唯一部分。

我也在清单中包括了 searchable.xml 的提供程序和意图过滤器:

<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.LEANBACK_LAUNCHER" />

            <action android:name="android.intent.action.SEARCH" />

        </intent-filter>

        <!-- Points to searchable meta data. -->
        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/searchable" />

    </activity>

    <provider
        android:name=".VideoContentProvider"
        android:authorities="test.tvsearch"
        android:exported="true" >...

正如我所见,ContentProvider 确实收到了 onCreate 调用,因此它在清单中是正确的。然而,问题是 Android 电视在搜索时没有通过我的应用程序,查询方法没有被调用。

我还看到该应用程序未在 Android 电视设置 > 首选项 > 搜索 > 可搜索应用程序中列出,我认为这真的很奇怪,因为在 searchable.xml 中它是据说将提供者包括在全局搜索中。因为这段代码几乎是从 leanback 示例中复制的,所以我没有想法,该示例运行完美,并且在复制时立即中断。

任何帮助将不胜感激!

如果你打开 this 你会看到 android:labelandroid:hint 都必须是 "string resource" (@string/something) 我认为构建系统(或 lint 工具或其他工具)现在可以捕捉到这些情况(我在三四年前的确切问题上花了几个小时),但不,似乎开发人员甚至现在都在拔头发,所以只需更换:

android:label="test leanback api demo"
android:hint="searching for videos test"

与:

android:label="@string/search_label"
android:hint="@string/search_hint"

我不确定 android:searchSettingsDescription,因为在一个地方它说:"string resource" 但在详细描述中它很简单 "string"

对于其他苦苦挣扎的人,Google 在他们的教程中没有包括的是您必须在设备设置中启用您的应用程序可搜索。否则,您的内容提供者会被创建但从未被查询过。在 searchable configuration 中找到这个:

android:includeInGlobalSearch Boolean. (Required to provide search suggestions in Quick Search Box.) Set to "true" if you want your suggestions to be included in the globally accessible Quick Search Box. The user must still enable your application as a searchable item in the system search settings before your suggestions will appear in Quick Search Box.

重要的是在清单中的下一个代码中包含您的活动,它对我有帮助:

<intent-filter>
            <action android:name="android.intent.action.SEARCH"/>

 <meta-data
                android:name="android.app.searchable"
                android:resource="@xml/searchable"/>