【问题标题】:How to pass BuildConfig values to dependency module?如何将 BuildConfig 值传递给依赖模块?
【发布时间】:2017-08-07 07:28:20
【问题描述】:

我在 App 模块的 BuildConfig 中有一些配置值。我想将这些值传递给 MyLib 的 BuildConfig,它是 App 模块的依赖项。有可能吗?

【问题讨论】:

  • 可能没有,你的库不依赖于应用模块

标签: android react-native gradle android-gradle-plugin


【解决方案1】:

最简单的方法是创建第三个模块(库),并将此模块添加到您的库模块和应用模块的依赖项中。

然后将共享的构建配置放到共享的第三个模块中。

app module <------------------ library module
    ^                                ^
    |                                |
    | dependency                     |dependency
     ------------ third module -------

【讨论】:

    【解决方案2】:

    这就是我与库/模块 BuildConfig 共享应用程序版本代码和版本名称的方式:

    在项目级别的 gradle 文件中定义版本代码和名称:

    ext {
            appVersionCode = 1
            appVersionName = '1.0.1' 
    }
    

    现在在您的应用程序 gradle 中:

    defaultConfig {
        ....
        versionCode $rootProject.appVersionCode
        versionName $rootProject.appVersionName
    

    在你的库/模块 gradle 中:

    defaultConfig {
        ....
        def appVersionCode = $rootProject.appVersionCode
        def appVersionName = '\"' + $rootProject.appVersionName +'\"'
    
        versionCode appVersionCode
        versionName appVersionName
    
        //This part to get version code and name in library/module BuildConfig file 
    
        buildConfigField 'int', 'APP_VERSION_CODE', "$appVersionCode"
        buildConfigField 'String', 'APP_VERSION_NAME', appVersionName
    

    一个解释如何与多个模块共享 gradle buildConfigField 变量的简单项目:https://github.com/Noddy20/Multi-Module-Gradle-Config

    【讨论】:

    • 在模块 gradle 中添加 buildConfigField 时出现此错误:产品风味“库”包含自定义 BuildConfig 字段,但该功能已禁用。你有同样的问题吗?我知道是一个旧帖子,但也许你还记得
    • 不,我没有。在我的一些项目中,我仍然使用相同的过程。你能在你使用这个的地方分享你的gradle代码吗?
    • 谢谢,在评论中分享这个很难,我用我的 gradle 发了一个问题:stackoverflow.com/questions/71146959/… 你能在那里检查一下吗?
    【解决方案3】:

    不,我们不能那样做。依赖模块无法访问App模块的BuildConfig文件。

    解决您的问题的唯一替代方案是您需要将相同的属性添加到您的依赖项 BuildConfig 文件中。

    【讨论】:

    • 可以通过将类引用传递给依赖模块并将值读入 HashMap 来通过反射完成。
    【解决方案4】:

    一般来说,BuildConfig 有静态成员。所以我建议反射将您的 BuildConfig 传输为包含字段/值的模型列表

    我们需要一个模型来包含所有类成员的字段和值。让我们称之为BuildConfigItem(我建议将这个类放在目标模块中):

     public class BuildConfigItem {
            public final Field field;
            public final Object object;
    
            public BuildConfigItem(Field field, Object object) {
                this.field = field;
                this.object = object;
            }
        }
    

    现在您可以使用此方法获取 BuildConfig 的所有类成员。想法是将它们转换为可以在其他模块上独立检索的可移植阶段,即使不知道 BuildConfig 有什么:

    public static ArrayList<BuildConfigItem> getBuildConfigField() {
        ArrayList<BuildConfigItem> list = new ArrayList<>();
        Field[] declaredFields = BuildConfig.class.getDeclaredFields();
        BuildConfig buildConfig=new BuildConfig();
        for (Field field : declaredFields) {
            if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
                try {
                    BuildConfigItem buildConfigItem = new BuildConfigItem(field, field.get(buildConfig));
                    list.add(buildConfigItem);
                } catch (IllegalAccessException e) {
                    Log.e(TAG, "error during assigning fields: ", e);
                }
            }
        }
        return list;
    }
    

    获取BuildConfigItem 的列表:

    ArrayList<BuildConfigItem> buildConfigItemArrayList = getBuildConfigField();
    

    然后将其传递给您的模块。这是如何迭代该列表以获取值的简单方法: for (BuildConfigItem buildConfigItem : buildConfigItemArrayList) { Log.d(TAG,buildConfigItem.field.getName() + ":" + buildConfigItem.object); }

    以下是列出所有值和转换常见类型的方法:

    for (BuildConfigItem buildConfigItem : buildConfigItemArrayList) {
        if (buildConfigItem.field.getType() == String.class) {
            String value = (String) buildConfigItem.object;
            Log.d(TAG, "String:" + buildConfigItem.field.getName() + ":" + value);
        } else if (buildConfigItem.field.getType() == int.class) {
            Integer value = (Integer) buildConfigItem.object;
            Log.d(TAG, "integer:" + buildConfigItem.field.getName() + ":" + value);
        } else if (buildConfigItem.field.getType() == boolean.class) {
            Boolean value = (Boolean) buildConfigItem.object;
            Log.d(TAG, "boolean:" + buildConfigItem.field.getName() + ":" + value);
        } else {
            Log.d(TAG, "Other:" + buildConfigItem.field.getName() + ":" + buildConfigItem.object);
        }
    }
    

    就是这样?

    如果您在 BuildConfig 中定义自定义类型的字段,则需要调整此代码。即日期或更复杂的类型。

    还要注意目标模块应该具有 BuildConfig 类型的所有依赖项。 (如果您在 BuildConfig 中定义字段时使用自己的对象)

    祝你好运,'。

    【讨论】:

      【解决方案5】:

      这就是我这样做的原因,因为我不想为不同的 RN 模块维护多个 BuildConfig。

      注意:我使用的是 react-native,但这应该与普通的 Android\Java 相关。

      MainApplication.java

      我将 BuildConfig.class 传递给依赖构造函数。

      @Override
          protected List<ReactPackage> getPackages() {
              List<ReactPackage> array =null;
              try {
                  array= Arrays.asList(new MainReactPackage(),
                        new RNCustomPackageWithBuildConfig(BuildConfig.class));
              } catch (IllegalAccessException e) {
                  Log.e(LOG_TAG,e.getMessage(),e.getCause());
              }
      
              return  array;
          }
      

      RNCustomPackageWithBuildConfig.java(构造函数接受类参数)

      public class RNCustomPackageWithBuildConfig implements ReactPackage {
          public static HashMap<String,Object> MainBuildConfig;
          public RNCustomPackageWithBuildConfig(Class mainBuildConfig) throws IllegalAccessException {
              MainBuildConfig= (HashMap<String, Object>) ObjectHelpers.getClassProperties(mainBuildConfig);
          }
      }
      

      getClassProperties 辅助方法

      public class ObjectHelpers {
      
          public static Map<String, Object> getClassProperties(final Class inClass) throws IllegalAccessException {
              Map<String, Object> returnVal = new HashMap<>();
              for (Field field : inClass.getDeclaredFields()) {
                  field.setAccessible(true); // You might want to set modifier to public first.
                  Object value = field.get(inClass);
                  if (value != null) {
                      returnVal.put(field.getName(),value);
                  }
              }
              return returnVal;
          }
      }
      

      在我的 Android RN 模块中

      private void handleIntent(Intent intent) throws Exception {
      
              // insert business
              String action = intent.getAction();
              String type = intent.getType();
      
              Log.d(LOG_TAG, "handleIntent => Type:" + type + " Action:" + action);
      
              if (Intent.ACTION_VIEW.equals(action)) {
                 //access public static MainBuildConfig field from RNCustomPackageWithBuildConfig 
                  String someBuildConfigField= RNCustomPackageWithBuildConfig .MainBuildConfig.get("SOME_BUILDCONFIG_FIELD").toString();
      
      }
      

      【讨论】:

        猜你喜欢
        • 2016-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-19
        • 1970-01-01
        • 2023-04-03
        • 2019-07-26
        • 1970-01-01
        相关资源
        最近更新 更多