Android Studio 两种风格,具有不同的清单文件
Android Studio two flavors with different manifest files
我在 Android Studio 中为我的风格定义两个不同的清单文件时遇到问题。这是我当前的项目结构:
free
风味中的 AndroidManifest.xml
如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.example.package">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest>
main
风格中的 AndroidManifest.xml
没有使用权限,但包含所有风格之间共享的清单代码的其余部分。
pro
风味中的 AndroidManifest.xml
如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.example.package">
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
</manifest>
build.gradle 像
定义了两种风格
productFlavors {
free {
applicationId 'se.example.package.free'
minSdkVersion 14
targetSdkVersion 21
versionCode 1
versionName '1.0'
}
pro {
minSdkVersion 14
applicationId 'se.example.package.pro'
targetSdkVersion 21
versionCode 2
versionName '1.1'
}
}
我期待的结果是不同的风格定义了不同的使用权限。 事实并非如此。结果是目前两种版本都只定义了<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
,如AndroidManifest.xml
中定义的pro版本。
我试过:
- 清理项目
- 重建项目
- 重新启动 Android Studio
- 同步gradle
但是没有成功。我该如何解决这个问题?感谢任何帮助。
编辑 1
我将每个 AndroidManifest.xml
文件的位置从每个 res
文件夹更改为 free
和 pro
文件夹。结果:
- 专业版按预期显示许可权限。
- 免费口味显示来自两者的权限
AndroidManifest.xml
文件、许可证和网络权限(应该只有网络)
这感觉像是项目结构的问题。这是怎么回事?
编辑 2
我按照 Commonsware 的提示提取了合并报告,这些是关于 uses-permissions
的报告
免费:
uses-permission#com.android.vending.CHECK_LICENSE
ADDED from qwknoteGIT:licencing-library:unspecified:26:5
android:name
ADDED from qwknoteGIT:licencing-library:unspecified:26:22
亲:
uses-permission#com.android.vending.CHECK_LICENSE
MERGED from qwknoteGIT:licencing-library:unspecified:26:5
技术背景:
在此 link 上解释了可用于清单合并的技术和参数:https://developer.android.com/studio/build/manage-manifests#merge_rule_markers
具体的一个是 tools:node
,它指出清单上的某些 XML 节点在合并时应该如何表现。
解法:
要在一个清单中获得一些权限而在其他清单中获得不同的权限,请将您需要的所有权限添加到 main
并在风味清单中删除不需要的权限,如下例所示:
free
删除检查许可证
<uses-permission
android:name="com.android.vending.CHECK_LICENSE"
tools:node="remove"/>
您的问题来自图书馆,而不是您的口味。具体来说,qwknoteGIT:licencing-library
正在请求 CHECK_LICENSE
。
如果您没有在所有风格中使用该库,请使用风格 compile
语句(例如,proCompile
)仅在该风格中使用该库。
如果您正在为所有风格使用该库,但确信您不需要一种风格的许可,那么可以在风格的清单中使用 tools:node
属性来阻止该许可由图书馆提供。
清单合并报告是您的朋友。 :-)
这至少应该可以解决问题。我发现它有助于指定用于每个变体的确切清单。干杯!它明确指向每个变体文件夹下的清单文件。
android {
productFlavors {
prod {
manifest.srcFile "prod/AndroidManifest.xml"
}
dev {
manifest.srcFile "dev/AndroidManifest.xml"
}
}
...
}
您应该更改您的代码:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.example.package">
用于:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.your.appid">
在您的应用中,在 sourceSets 下专门指定您的清单 build.gradle
android {
productFlavors {
bizdartFlavourNoCallLog {
minSdkVersion 16
applicationIdSuffix '.bizdart'
targetSdkVersion 26
dimension "tier"
sourceSets {
main {
manifest.srcFile "src/bizdartFlavourNoCallLog/AndroidManifest.xml"
}
}
copy {
from 'src/bizdartFlavourNoCallLog/'
include '*.json'
into '.'
}
}
}
}
参见 https://developer.android.com/studio/build/manifest-merge 参数 tools:node="merge"
高优先级清单(免费):
<activity android:name="com.example.ActivityOne"
android:screenOrientation="portrait"
tools:node="merge">
</activity>
低优先级清单(主要):
<activity android:name="com.example.ActivityOne"
android:windowSoftInputMode="stateUnchanged">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
合并清单结果:
<activity android:name="com.example.ActivityOne"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateUnchanged">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
我也遇到了同样的问题,后来发现是因为我把"pro"和"tree"flavor文件夹放到了lib项目下,把flavors文件夹移到下面就解决了应用项目
我在 Android Studio 中为我的风格定义两个不同的清单文件时遇到问题。这是我当前的项目结构:
free
风味中的 AndroidManifest.xml
如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.example.package">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest>
main
风格中的 AndroidManifest.xml
没有使用权限,但包含所有风格之间共享的清单代码的其余部分。
pro
风味中的 AndroidManifest.xml
如下所示:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.example.package">
<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
</manifest>
build.gradle 像
定义了两种风格productFlavors {
free {
applicationId 'se.example.package.free'
minSdkVersion 14
targetSdkVersion 21
versionCode 1
versionName '1.0'
}
pro {
minSdkVersion 14
applicationId 'se.example.package.pro'
targetSdkVersion 21
versionCode 2
versionName '1.1'
}
}
我期待的结果是不同的风格定义了不同的使用权限。 事实并非如此。结果是目前两种版本都只定义了<uses-permission android:name="com.android.vending.CHECK_LICENSE" />
,如AndroidManifest.xml
中定义的pro版本。
我试过:
- 清理项目
- 重建项目
- 重新启动 Android Studio
- 同步gradle
但是没有成功。我该如何解决这个问题?感谢任何帮助。
编辑 1
我将每个 AndroidManifest.xml
文件的位置从每个 res
文件夹更改为 free
和 pro
文件夹。结果:
- 专业版按预期显示许可权限。
- 免费口味显示来自两者的权限
AndroidManifest.xml
文件、许可证和网络权限(应该只有网络)
这感觉像是项目结构的问题。这是怎么回事?
编辑 2
我按照 Commonsware 的提示提取了合并报告,这些是关于 uses-permissions
免费:
uses-permission#com.android.vending.CHECK_LICENSE
ADDED from qwknoteGIT:licencing-library:unspecified:26:5
android:name
ADDED from qwknoteGIT:licencing-library:unspecified:26:22
亲:
uses-permission#com.android.vending.CHECK_LICENSE
MERGED from qwknoteGIT:licencing-library:unspecified:26:5
技术背景:
在此 link 上解释了可用于清单合并的技术和参数:https://developer.android.com/studio/build/manage-manifests#merge_rule_markers
具体的一个是 tools:node
,它指出清单上的某些 XML 节点在合并时应该如何表现。
解法:
要在一个清单中获得一些权限而在其他清单中获得不同的权限,请将您需要的所有权限添加到 main
并在风味清单中删除不需要的权限,如下例所示:
free
删除检查许可证
<uses-permission
android:name="com.android.vending.CHECK_LICENSE"
tools:node="remove"/>
您的问题来自图书馆,而不是您的口味。具体来说,qwknoteGIT:licencing-library
正在请求 CHECK_LICENSE
。
如果您没有在所有风格中使用该库,请使用风格 compile
语句(例如,proCompile
)仅在该风格中使用该库。
如果您正在为所有风格使用该库,但确信您不需要一种风格的许可,那么可以在风格的清单中使用 tools:node
属性来阻止该许可由图书馆提供。
清单合并报告是您的朋友。 :-)
这至少应该可以解决问题。我发现它有助于指定用于每个变体的确切清单。干杯!它明确指向每个变体文件夹下的清单文件。
android {
productFlavors {
prod {
manifest.srcFile "prod/AndroidManifest.xml"
}
dev {
manifest.srcFile "dev/AndroidManifest.xml"
}
}
...
}
您应该更改您的代码:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="se.example.package">
用于:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.your.appid">
在您的应用中,在 sourceSets 下专门指定您的清单 build.gradle
android {
productFlavors {
bizdartFlavourNoCallLog {
minSdkVersion 16
applicationIdSuffix '.bizdart'
targetSdkVersion 26
dimension "tier"
sourceSets {
main {
manifest.srcFile "src/bizdartFlavourNoCallLog/AndroidManifest.xml"
}
}
copy {
from 'src/bizdartFlavourNoCallLog/'
include '*.json'
into '.'
}
}
}
}
参见 https://developer.android.com/studio/build/manifest-merge 参数 tools:node="merge"
高优先级清单(免费):
<activity android:name="com.example.ActivityOne"
android:screenOrientation="portrait"
tools:node="merge">
</activity>
低优先级清单(主要):
<activity android:name="com.example.ActivityOne"
android:windowSoftInputMode="stateUnchanged">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
合并清单结果:
<activity android:name="com.example.ActivityOne"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateUnchanged">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
我也遇到了同样的问题,后来发现是因为我把"pro"和"tree"flavor文件夹放到了lib项目下,把flavors文件夹移到下面就解决了应用项目