为一种产品风味添加 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 因为所有的方法都是基于他的想法。
对于未来的读者,我想留下一些评论我是如何解决项目中的问题的。
- 让
app/src/main
中的 AndroidManifest.xml
保持不变
- 使用此内容在
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>
- 盈利!结果
AndroidManifest.xml
由 gradle
自动合并。我为该项目定制了 Application
class,但效果很好。
这种方法比使用 enabled
选项关闭 receiver
更常见,并允许像往常一样配置 receiver
和 service
。另外我只需要创建一个额外的文件,所以它很简单。
我有两个 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 因为所有的方法都是基于他的想法。
对于未来的读者,我想留下一些评论我是如何解决项目中的问题的。
- 让
app/src/main
中的AndroidManifest.xml
保持不变 - 使用此内容在
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>
- 盈利!结果
AndroidManifest.xml
由gradle
自动合并。我为该项目定制了Application
class,但效果很好。
这种方法比使用 enabled
选项关闭 receiver
更常见,并允许像往常一样配置 receiver
和 service
。另外我只需要创建一个额外的文件,所以它很简单。