由于公司业务需要,app需要上国内的应用市场和google应用市场,同一个项目,只是有部分功能有区别,比如支付。大陆版用微信,支付宝。而国际版用FirstData
由于大部分功能都是相同,只有部分功能不同,引用的sdk不同。这时候就可以利用productFlavors来把不同的功能分出来,打包成不同的应用
好处是不用弄两个分支来维护,而且资源文件,引用的sdk都可以区分开构建
官方文档:https://developer.android.google.cn/studio/build#module-level
例:
1.打开app级的buid.gradle
2.在buildTypes中代码如下
buildTypes {
getByName("release") {
signingConfig signingConfigs.release
minifyEnabled = true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
getByName("debug") {
applicationIdSuffix = ".debug"
debuggable = true
}
}
3.打开project structure,如下图
选中Build Variants,选择Flavors. 先点击+,先添加Add Flavor Dimension,再添加Add Product Flavor,在Application ID Suffix中添加拼接Application Id的内容,这样应用id就变成defaultConfig中的applicationId + “.haha”
点击apply,再点击ok,回到build.gradle中,android {}代码块中就添加了如下的代码
此时已经可以打出不同applicationId的apk了,接下来继续为同一功能的不同实现添加代码集
4.为不同的product添加不同的sdk,如下代码,为buildTest01添加glide,为buildTest02添加eventbus
buildTest01Implementation("com.github.bumptech.glide:glide:4.11.0")
buildTest02Implementation("org.greenrobot:eventbus:3.0.0")
//所有产品都需要的sdk继续用 implementation
这样构建完buildTest01时,buildTest01中就不会有eventbus sdk
5.Build -> Select Build Variant… 可以选择buildTest01Debug
6.为同一功能的不同实现添加代码,资源,将项目目录结构改为project,选中src -> new -> Directory -> 选择需要buildTest01/java ;buildTest01/res,添加buildTest02的代码集时需要重复第5步,选择buildTest02Debug,才能选择到buildTest02/java;buildTest02/res选择
添加完后项目结构如下图
看图,在Build Variants中现在是选择buildTest01,所以buildTest02的图标跟buildTest01和main的不一样,此时如果是在buildTest02中编写代码,是不会有代码提示及错误提示的,此时只需要重复第5步选择buildTest02即可
7.添加代码,资源
我这里在buildTest01/02中分别添加一个MainActivity,用相同的布局文件显示不同的内容,添加完项目结构如下图
AndroidManifest.xml的代码如下
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.build_test">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.BuildTest">
<activity
android:name="build_test.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
main中MainActivity代码如下
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val tvPackageName = findViewById<TextView>(R.id.tv_packageName)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val pmInfo: PackageInfo = packageManager.getPackageInfo(packageName,PackageManager.GET_CONFIGURATIONS)
tvPackageName.text = "main versionName ${pmInfo.versionName} \n packageName = ${pmInfo.packageName}"
}
}
}
buildTest01中MainActivity代码如下
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvPackage = findViewById(R.id.tv_packageName);
try {
tvPackage.setText("哈哈哈哈哈哈 " + getPackageName() + "\n" + getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES).versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Glide.with(this);
}
}
buildTest02中MainActivity代码如下
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tvPackage = findViewById(R.id.tv_packageName);
try {
tvPackage.setText("嘻嘻嘻嘻" + getPackageName() + "\n" + getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES).versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Glide.with(this);
}
}
添加不同的资源
在buildTest01/02 的res下添加values,各自添加string.xml
buildTest01的string.xml添加<string name="app_name">BuildTest1</string>
buildTest02的string.xml添加<string name="app_name">BuildTest2</string>
分别运行后,模拟器上分别安装了BuildTest1和BuildTest2两个应用
这是BuildTest1运行的页面
BuildTest2运行的页面