Android R Settings搜索框功能流程

Settings 搜索是调用的 SettingsIntelligence 应用的 SearchActivity,路径:android/packages/apps/SettingsIntelligence

流程图如下

在 PreIndexDataCollector.java 中的最后 get*** 函数中创建 ContentResolver 来查询获取数据。

而数据的来源就是 Settings 中 SettingsSearchIndexablesProvider ,  SettingsSearchIndexablesProvider 继承自 android.provider.SearchIndexablesProvider.java ,

        <provider
            android:name=".search.SettingsSearchIndexablesProvider"
            android:authorities="com.android.settings"
            android:multiprocess="false"
            android:grantUriPermissions="true"
            android:permission="android.permission.READ_SEARCH_INDEXABLES"
            android:exported="true">
            <intent-filter>
                <action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
            </intent-filter>
        </provider>

 SearchIndexablesProvider 中只有一个 query 是有作用的,其他几个 insert delete update 操作都是抛出异常。 query 中对上面 PreIndexDataCollector 中的请求进行具体处理如下。

//SearchIndexablesProvider.java

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder) {
        try {
            switch (mMatcher.match(uri)) {
                case MATCH_RES_CODE:
                    return queryXmlResources(null);
                case MATCH_RAW_CODE:
                    return queryRawData(null);
                case MATCH_NON_INDEXABLE_KEYS_CODE:
                    return queryNonIndexableKeys(null);
                case MATCH_SITE_MAP_PAIRS_CODE:
                    return querySiteMapPairs();
                case MATCH_SLICE_URI_PAIRS_CODE:
                    return querySliceUriPairs();
                case MATCH_DYNAMIC_RAW_CODE:
                    return queryDynamicRawData(null);
                default:
                    throw new UnsupportedOperationException("Unknown Uri " + uri);
            }
        } catch (UnsupportedOperationException e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "Provider querying exception:", e);
            return null;
        }
    }

queryXmlResources 等几个操作具体实现就回到 Settings 应用模块中了,在 SettingsSearchIndexablesProvider 中进行实现,以 queryXmlResources 为例

//SettingsSearchIndexablesProvider.java
    
    @Override
    public Cursor queryXmlResources(String[] projection) {
        final MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
        final List<SearchIndexableResource> resources =
                getSearchIndexableResourcesFromProvider(getContext());
        for (SearchIndexableResource val : resources) {
            final Object[] ref = new Object[INDEXABLES_XML_RES_COLUMNS.length];
            ref[COLUMN_INDEX_XML_RES_RANK] = val.rank;
            ref[COLUMN_INDEX_XML_RES_RESID] = val.xmlResId;
            ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = val.className;
            ref[COLUMN_INDEX_XML_RES_ICON_RESID] = val.iconResId;
            ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = val.intentAction;
            ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = val.intentTargetPackage;
            ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = null; // intent target class
            cursor.addRow(ref);
        }

        return cursor;
    }

    ... ... 

    private List<SearchIndexableResource> getSearchIndexableResourcesFromProvider(Context context) {
        final Collection<SearchIndexableData> bundles = FeatureFactory.getFactory(context)
                .getSearchFeatureProvider().getSearchIndexableResources().getProviderValues();
        List<SearchIndexableResource> resourceList = new ArrayList<>();

        for (SearchIndexableData bundle : bundles) {
            Indexable.SearchIndexProvider provider = bundle.getSearchIndexProvider();
            final List<SearchIndexableResource> resList =
                    provider.getXmlResourcesToIndex(context, true);

            if (resList == null) {
                continue;
            }

            for (SearchIndexableResource item : resList) {
                item.className = TextUtils.isEmpty(item.className)
                        ? bundle.getTargetClass().getName()
                        : item.className;
            }

            resourceList.addAll(resList);
        }

        return resourceList;
    }

最终通过 getProviderValues() 获取所有的带 @SearchIndexable 注释的类。再获取里面的 Indexable.SearchIndexProvider 内部类,所有的相关类里面的这个内部类都是一样的命名,好找

    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
            new BaseSearchIndexProvider(R.xml.display_settings) {

                @Override
                public List<String> getNonIndexableKeys(Context context) {
                    final List<String> keys = super.getNonIndexableKeys(context);
                    keys.add("auto_brightness_entry");
                    return keys;
                }

                @Override
                protected boolean isPageSearchEnabled(Context context) {
                    return true;
                }
            };

这里面重要的几个方法功能大致介绍下。首先构造函数中的 R.xml.display_settings ,这可以看下 BaseSearchIndexProvider 类中,其实就是给定 getXmlResourcesToIndex 方法的xml参数。添加xml中所有 key 的搜索项目。

getNonIndexableKeys 这个方法中返回就是无需搜索的,从搜索列表中移除的 key 的集合。

isPageSearchEnabled 这个返回 false 则表示这个 display_settings  xml 中所有的 key 都不需要的搜索,全部移除。具体使用是在 BaseSearchIndexProvider 中。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值