Android 自定义Gradle插件(七):关于多渠道打包

公司的SDK项目原来主要是面向Google Play,最近接到了新需求,需要接入两个新的SDK,分别针对韩国和印度,出包时需要有独立的applicationId,并且不同的包要配置不同的依赖项。

这个需求用Android Studio的多渠道配置即可实现,直接在Android Studio中配置的话需要接入方添加,所以我们仍然是在gradle插件中来实现。

实现思路:

  1. 根据接入方的包名从后台获取配置文件。
  2. 根据配置文件来配置渠道参数,例如applicationId
  3. 根据执行的打包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,如下图:

企业微信截图_16483495453293.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享