Android:在 Gradle 构建脚本中使用 packageNameSuffix 时,SearchableInfo 为 null

标签 android gradle build.gradle searchable

如果我在项目的 Gradle 构建脚本中使用 packageNameSuffix,我遇到 getSearchableInfo 方法在 SearchView 初始化期间总是返回 null。

SearchView 初始化:

final SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
SearchableInfo info = searchManager.getSearchableInfo(componentName);
mSearchView.setSearchableInfo(info);

项目的build.gradle:

android {
    [...]
    buildTypes {
        debug {
            packageNameSuffix ".debug"
            versionNameSuffix "-debug"
            signingConfig signingConfigs.debug
        }
        [...]
    }
}

如果不使用包后缀,给定的componentNameComponentInfo{com.example.android/com.example.android.MapActivity} SearchView 及其关联的 SuggestionsProvider 工作正常。

但如果 packageNameSuffix 设置为 ".debug",则给定的 componentNameComponentInfo{com.example.android. debug/com.example.android.MapActivity}SearchManager 返回 null,而不是返回相应的 SearchableInfo 对象。

有谁知道如何从 SearchManager 获得正确的 SearchableInfo?谢谢!

[编辑]

Eugen Martinov 在评论中提到,此行为可能与不正确或缺失的权限重命名有关。但我还配置了一个依赖构建类型的权限命名,为了简单起见,我在最初的帖子中省略了这一点。

项目的build.gradle:

android {
    [...]
    sourceSets {
        debug {
            java.srcDirs = [
                'src/main/java'
            ]
            java.srcDirs = [
                'src/debug/res',
                'src/main/res'
            ]
        }
        release {
            java.srcDirs = [
                'src/main/java'
            ]
            java.srcDirs = [
                'src/release/res',
                'src/main/res'
            ]
        }
        [...]
    }
}

src/debug/res/values/build-config.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="cfg_app_name">App - Debug</string>
    <string name="cfg_authorities">com.example.debug.SuggestionsProvider</string>
    <string name="cfg_maps_key"><!-- some key --></string>
</resources>

src/release/res/values/build-config.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="cfg_app_name">App</string>
    <string name="cfg_authorities">com.example.SuggestionsProvider</string>
    <string name="cfg_maps_key"><!-- some other key --></string>
</resources>

src/main/res/xml/searchable.xml:

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:hint="@string/action_search_hint"
    android:label="@string/cfg_app_name"
    android:includeInGlobalSearch="false"
    android:queryAfterZeroResults="true"
    android:searchSuggestAuthority="@string/cfg_authorities"
    android:searchSuggestIntentAction="android.intent.action.VIEW"
    android:searchSuggestThreshold="3" />

在同一台设备上同时安装调试(使用 packageNameSuffix 选项)和发布 apk。我没有收到类似 Failure [INSTALL_FAILED_CONFLICTING_PROVIDER] 的错误...但是正如已经说过的那样,SearchableInfonull

在没有 packageNameSuffix 选项的情况下安装这两个 apk 会导致以下错误:失败 [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES] - 安装失败,因为设备已经有一个具有相同包但签名不同的应用程序。

还是我在这里遗漏了什么?

[/EDIT]

最佳答案

我正在使用完全改变包装名称的产品口味。我发现通过使用 ComponentName(Context pkg, Class<?> cls)我的搜索 Activity 的构造函数我得到一个有效的 SearchableInfo。

SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchableInfo searchableInfo = searchManager.getSearchableInfo(new ComponentName(this, SearchActivity.class));

我还必须调整我的提供者以使用不同的包,以便我的可搜索 xml 位于每个 flavor 目录中,并且提供者也列在每个 flavor 的 list 中。 这是我的目录结构:

src
  main
    AndoridManifest.xml
  flavor1
    res
      xml
        search.xml
    AndroidManifest.xml
  flavor2
    res
      xml
        search.xml
    AndroidManifest.xml

主/AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:logo="@drawable/actionbar_icon"
    android:label="@string/app_name"
    android:name=".App"
    android:allowBackup="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".ui.MainActivity"
        android:launchMode="singleTask">
        <meta-data
            android:name="android.app.default_searchable"
            android:value=".ui.activity.SearchActivity"/>
    </activity>
    <activity android:name=".ui.SearchActivity" android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data
            android:name="android.app.searchable"
            android:resource="@xml/search"/>
    </activity>

    <provider
        android:authorities=".provider.SuggestionProvider"
        android:name="com.example.main.provider.SuggestionProvider"
        android:exported="false"
        android:enabled="true"
        />
</applicaiton

flavor1/AndroidManifest.xml

<application>
    <provider
        tools:replace="android:authorities"
        android:authorities="com.example.flavor1.provider.SuggestionProvider"
        android:name="com.example.main.provider.SuggestionProvider"
        android:exported="false"
        android:enabled="true"
        />
</application>

flavor1/res/xml/search.xml

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:includeInGlobalSearch="false"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
    android:searchMode="queryRewriteFromText"
    android:searchSuggestAuthority="com.example.flavor1.provider.SuggestionProvider"
    android:searchSuggestSelection="title LIKE ?"
    android:searchSuggestThreshold="0"
    >
</searchable>

flavor2/AndroidManifest.xml

<application>
    <provider
        tools:replace="android:authorities"
        android:authorities="com.example.flavor2.provider.SuggestionProvider"
        android:name="com.example.main.provider.SuggestionProvider"
        android:exported="false"
        android:enabled="true"
        />
</application>

flavor2/res/xml/search.xml

<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:includeInGlobalSearch="false"
    android:voiceSearchMode="showVoiceSearchButton|launchRecognizer"
    android:searchMode="queryRewriteFromText"
    android:searchSuggestAuthority="com.example.flavor2.provider.SuggestionProvider"
    android:searchSuggestSelection="title LIKE ?"
    android:searchSuggestThreshold="0"
    >
</searchable>

关于Android:在 Gradle 构建脚本中使用 packageNameSuffix 时,SearchableInfo 为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20825949/

相关文章:

java - 在后台发送电子邮件 - Android

android - 编译 appcompat v7 :26. + 为融合位置提供者添加播放服务时出错

groovy - Gradle 提示 "No such file or directory"

android - Gradle 依赖排除

java - 测试应用程序时出错 - Firebase 测试实验室

java - 在android中以编程方式将apk文件推送到assets文件夹中

java - 如何以编程方式设置具有透明背景颜色的按钮的不透明度

java - STS - Gradle - Java Home 与众不同

java - 如何让 jar 任务在 gradle 中包含单个依赖项

android - 执行任务 : [:app:generateDebugSources] in project