为一种产品风味添加 Android AppWidget

Adding Android AppWidget just for one Product Flavor

我有两个 gradle product flavors:用于产品和阶段服务器。

productFlavors {
        stage {
            // stage specific stuff
        }
        production {
            // production only
        }
    }

我还有一个 AppWidget 现在必须只能用于舞台。我想我应该在清单中隐藏我的 AppWidgetProvider

<receiver
    android:name=".appwidget.AppWidgetProvider"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
       android:name="android.appwidget.provider"
       android:resource="@xml/appwidget_info" />
</receiver>

但是我怎么能只为了产品风味呢?或者这里有别的方法吗?

因此,我们将在 gradle 产品口味中为您的生产和暂存构建提供如下示例包。

productFlavors {
        production {
            packageName "x(path).x(path).gradleexample"
        }

        staging {
            packageName "x(path).x(path).gradleexample.staging"
        }
    }

这是您的文件夹结构的一个示例,其中一些可能适用于您的项目,也可能不适用于您的项目,但应该会给您一个 运行 需要的内容。

├── main
│   ├── AndroidManifest.xml
│   ├── ic_launcher-web.png
│   ├── java
│   │   └── x(path)
│   │       └── x(path)
│   │           └── gradlebuildexample
│   │               └── MainActivity.java
│   └── res
│       ├── drawable-hdpi
│       │   └── ic_launcher.png
│       ├── drawable-mdpi
│       │   └── ic_launcher.png
│       ├── drawable-xhdpi
│       │   └── ic_launcher.png
│       ├── drawable-xxhdpi
│       │   └── ic_launcher.png
│       ├── layout
│       │   └── activity_main.xml
│       ├── menu
│       │   └── main.xml
│       ├── values
│       │   ├── dimens.xml
│       │   ├── strings.xml
│       │   └── styles.xml
│       ├── values-v11
│       │   └── styles.xml
│       └── values-v14
│           └── styles.xml
├── production
│   └── java
│       └── x(path)
│           └── x(path)
│               └── gradlebuildexample
│                   └── Constants.java
└── staging
    ├── java
    │   └── x(path)
    │       └── x(path)
    │           └── gradlebuildexample
    │               └── Constants.java
    └── res
        ├── drawable-hdpi
        │   └── ic_launcher.png
        ├── drawable-mdpi
        │   └── ic_launcher.png
        ├── drawable-xhdpi
        │   └── ic_launcher.png
        ├── drawable-xxhdpi
        │   └── ic_launcher.png
        └── values
            └── string.xml

现在要清楚您的字符串结果集 xml 在生产和暂存中,在值 -> string.xml 中,必须包含以下适用于清单的值以下。

所以像下面这样

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="receiver">false</string>
</resources>

根据我目前对你的清单的理解,它看起来像这样

<receiver
    android:name=".appwidget.AppWidgetProvider"
    android:label="@string/app_name"
    android:enabled="@string/receiver">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
       android:name="android.appwidget.provider"
       android:resource="@xml/appwidget_info" />
</receiver>

所以这可行,但如果您从我的第三条评论中看到,更好和更简单的解决方案是为每个构建阶段使用不同的清单,因为您可能需要更多更改,而不仅仅是一个。因此,下面我将提供解决方法,您可以根据我提供的内容进行推断。

在 gradle 中使用 source set 您可以为每个清单指定不同的构建路径,如下所示

sourceSets {

        main {
            manifest.srcFile 'src/main/AndroidManifest.xml'
            res.srcDirs = ['src/main/res']
        }

        debug {
            manifest.srcFile 'src/main/debug/AndroidManifest.xml'
            res.srcDirs = ['src/main/debug/res']
        }

        release {
            manifest.srcFile 'src/main/release/AndroidManifest.xml'
            res.srcDirs = ['src/main/release/res']
        }
}

基于@kev2316 的另一个答案,这里有一个更简单的方法来实现:

<meta-data
    android:name="android.appwidget.provider"
    android:resource="@xml"
    android:enabled="@bool/widget_enabled"/>

在你的build.gradle中:

productFlavors {
    production {
        resValue "bool", "widget_enabled", "true"
    }
    staging {
        resValue "bool", "widget_enabled", "false"
    }
}

好的,我尝试了所有的方法,它们都有效:) 我奖励@kev2316 因为所有的方法都是基于他的想法。

对于未来的读者,我想留下一些评论我是如何解决项目中的问题的。

  1. app/src/main 中的 AndroidManifest.xml 保持不变
  2. 使用此内容在 app/src/stage 中创建 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="my.package" >
<application>
<!-- Declarations for the widget -->
    <receiver
        android:name=".appwidget.AppWidgetProvider"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/appwidget_info" />
    </receiver>
    <service
        android:name=".appwidget.AppWidgetRefreshService"
        android:permission="android.permission.BIND_REMOTEVIEWS"
        android:exported="false" />
</application>
</manifest>
  1. 盈利!结果 AndroidManifest.xmlgradle 自动合并。我为该项目定制了 Application class,但效果很好。

这种方法比使用 enabled 选项关闭 receiver 更常见,并允许像往常一样配置 receiverservice。另外我只需要创建一个额外的文件,所以它很简单。