公司的SDK项目原来主要是面向Google Play,最近接到了新需求,需要接入两个新的SDK,分别针对韩国和印度,出包时需要有独立的applicationId
,并且不同的包要配置不同的依赖项。
这个需求用Android Studio的多渠道配置即可实现,直接在Android Studio中配置的话需要接入方添加,所以我们仍然是在gradle插件中来实现。
实现思路:
- 根据接入方的包名从后台获取配置文件。
- 根据配置文件来配置渠道参数,例如
applicationId
。 - 根据执行的打包Task来动态添加依赖项。
获取接入方的包名
项目在之前的需求中其实已经实现了获取接入方的包名功能。接入方的包名来自于AppExtension
,代码如下:
class MyPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
def appExtension = project.extensions.findByType(AppExtension.class)
project.afterEvaluate {
def applicationId = appExtension.defaultConfig.applicationId
}
}
}
复制代码
但是多渠道配置productFlavors
需要在gradle编译完之前就配置好,所以在project.afterEvaluate
中再获取到applicationId
就无法达成我们的目的,即根据配置文件来配置多渠道信息。
所以applicationId
就需要从接入方的项目中直接传入到插件。因此,我想到了通过创建extensions
来配置参数,代码如下:
Class DiyExtension{
String originalApplicationId
}
class MyPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
def diyExtension = project.extensions.create("DiyExtension", DiyExtension)
project.afterEvaluate {
def applicationId = diyExtension.originalApplicationId
}
}
}
//在build.gradle中添加
DiyExtension{
originalApplicationId "com.test.applicationid"
}
复制代码
然而这种方式其实和AppExtension
一样,都需要在project.afterEvaluate
中才能获取到值。
最终决定通过读取文件的方式来实现,即给接入方一个plugin-config.json
文件,放到项目的app目录下,然后我们在插件中通过读取这个文件来获取applicationId
,代码如下:
plugin-config.json 文件内容
{
"original_application_id": "com.test.applicationid"
}
//读取文件类
public class FileUtils {
public static String readFileFromAppFolder(File parentFile, String fileName) {
File readFile = new File(parentFile, fileName);
if (readFile.exists()) {
StringBuilder config = new StringBuilder();
FileInputStream fileInputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
try {
fileInputStream = new FileInputStream(readFile);
inputStreamReader = new InputStreamReader(fileInputStream, StandardCharsets.UTF_8);
reader = new BufferedReader(inputStreamReader);
String configContent;
while ((configContent = reader.readLine()) != null) {
config.append(configContent);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return config.toString();
}
return "";
}
}
class MyPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
def pluginConfigStr = FileUtils.readFileFromAppFolder(project.projectDir, "plugin-config.json")
PluginConfig pluginConfig = new Gson().fromJson(pluginConfigStr, new TypeToken<PluginConfig>() {
}.getType())
def originalApplicationId = pluginConfig.original_application_id
}
}
复制代码
多渠道配置
最总多渠道的配置代码如下:
class MyPlugin implements Plugin<Project> {
def config = null
def isKoreaTask = false
def isIndiaTask = false
@Override
public void apply(Project project) {
def appExtension = project.extensions.findByType(AppExtension.class)
//判断当前执行的task是哪个渠道
checkTask(project)
def pluginConfigStr = FileUtils.readFileFromAppFolder(project.projectDir, "plugin-config.json")
PluginConfig pluginConfig = new Gson().fromJson(pluginConfigStr, new TypeToken<PluginConfig>() {
}.getType())
def originalApplicationId = pluginConfig.original_application_id
//根据包名获取配置文件
getPluginConfigFromNet(originalApplicationId)
if(config != null){
//根据配置文件配置多渠道
if(config.korea.isEnable()||config.india.isEnable()){
//必须配置dimension否则编译会报错
appExtension.getFlavorDimensionList().add("country")
appExtension.productFlavors.register("original", {
dimension "country"
})
if (config.korea.isEnable()) {
appExtension.productFlavors.register("Korea", {
dimension "country"
applicationId config.korea.application_id
})
}
if (config.india.isEnable()) {
appExtension.productFlavors.register("India", {
dimension "country"
applicationId config.india.application_id
})
}
}
}
project.afterEvaluate {
//添加不同的依赖
project.dependencies {
if(isKoreaTask){
implementation("korea lib")
}
if(isIndiaTask){
implementation("india lib")
}
}
}
}
static void getPluginConfigFromNet(String packageName) {
def url = "https://downloadpath/" + packageName + "/config.json"
def okHttpClient = new OkHttpClient.Builder().build();
def request = new Request.Builder()
.url(url)
.build();
def call = client.newCall(request);
try {
Response response = call.execute();
if(response.isSuccessful()){
if (response.body() != null) {
def responseBodyString = responseBody.string()
config = gson.fromJson(responseBodyString, new TypeToken<SdkConfig>() {
}.getType())
}
}
response.close();
} catch (IOException | JsonIOException | JsonSyntaxException e) {
e.printStackTrace();
}
}
private static boolean checkTask(Project project) {
project.gradle.getStartParameter().getTaskNames().each {
isKoreaTask = it.contains("korea")
isIndiaTask = it.contains("india")
}
}
}
复制代码
生成了多渠道之后可以选择相应的build variant
,如下图:
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END