Android 查询程序返回安全异常

Android 查询程序返回安全异常,android,android-contentresolver,android-tv,Android,Android Contentresolver,Android Tv,当我尝试通过通道或程序id以外的任何方式查询程序数据库时,会出现以下异常: java.lang.SecurityException: Selection not allowed for content://android.media.tv/program at android.os.Parcel.readException(Parcel.java:1683) at android.database.DatabaseUtils.readExceptionFromParcel(Dat

当我尝试通过通道或程序id以外的任何方式查询程序数据库时,会出现以下异常:

java.lang.SecurityException: Selection not allowed for content://android.media.tv/program
    at android.os.Parcel.readException(Parcel.java:1683)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
    at android.content.ContentResolver.query(ContentResolver.java:530)
    at android.content.ContentResolver.query(ContentResolver.java:472)
请注意,我可以添加和删除程序,因此我认为在清单文件中正确设置了权限

下面的示例代码尝试按程序标题进行查询,但引发了上述异常

Uri uri = TvContract.Programs.CONTENT_URI;

Cursor cursor = null;
try {
    String mSelectionClause = TvContract.Programs.COLUMN_TITLE + " = ?";
    String[] mSelectionArgs = { "Test title" };
    cursor = resolver.query(uri, Program.PROJECTION, mSelectionClause, mSelectionArgs, null);
    if (cursor == null || cursor.getCount() == 0) {
        Log.d(TAG, "No programs found for 'Test title'");
        return programs;
    }
    Log.d(TAG, cursor.getCount() + " programs found for 'Test tilte'");
} catch (Exception e) {
    Log.w(TAG, "Unable to get programs for 'Test title'", e);
} finally {
    if (cursor != null) {
        cursor.close();
    }
}

无法按任何列进行查询吗?

电视提供商未打开以供选择。您可以添加/更新/删除,但不能创建自定义查询。您需要使用TvContractCompat来构建查询URI并评估结果

context.getContentResolver()
    .query(TvContractCompat.buildChannelUri(channelId), null, null, null, null);
还是为节目

context.getContentResolver()
    .query(TvContractCompat.buildProgramsUriForChannel(channelId), null, null, null, null);
对于一个特定的程序

context.getContentResolver()
    .query(TvContractCompat.buildProgramUri(programId), null, null, null, null);
例如,您应该查询频道中的节目并搜索标题

try (Cursor cursor = context.getContentResolver()
                      .query(
                TvContractCompat.buildProgramsUriForChannel(channelId),
                null, null, null, null)) {
    if (cursor != null && cursor.moveToNext()) {
        Program program = Program.fromCursor(cursor);
        if( "Test Title".equals(program.getTitle()) {
            // Do stuff...
        }
    }
}
参考:

我看到您提供的链接中的文章提到“WHERE子句是不允许的”。为什么呢?这很有限制性。每次你想访问某个特定的节目时,都必须通过所有频道的节目,这是非常缓慢的@vas由于多个应用程序可以在电视提供商中拥有频道,提供商尝试将每个应用程序限制为其自己的数据沙盒。理想情况下,如果您想查询特定的程序,您应该通过标识符而不是标题进行查询。标题可以翻译成不同的语言,并不能成为很好的关键。这就是电视提供商只允许按id查询的原因之一。您可以在查询上设置投影,这样您就不会在结果中返回所有元数据。标题是关键的特定用例是什么?我很想更好地理解。