Lak*_*mon 54 buildconfig android-gradle-plugin
我的(gradle 1.10和gradle插件0.8)基于android的项目包含一个大的android-library,它是3个不同的android-app的依赖
在我的图书馆,我希望能够使用这样的结构
if (BuildConfig.SOME_FLAG) {
callToBigLibraries()
}
Run Code Online (Sandbox Code Playgroud)
因为proguard可以根据SOME_FLAG的最终值减小生成的apk的大小
但我无法想象如何用gradle做到:
* the BuildConfig produced by the library doesn't have the same package name than the app
* I have to import the BuildConfig with the library package in the library
* The apk of an apps includes the BuildConfig with the package of the app but not the one with the package of the library.
Run Code Online (Sandbox Code Playgroud)
我尝试使用BuildTypes和类似的东西没有成功
release {
// packageNameSuffix "library"
buildConfigField "boolean", "SOME_FLAG", "true"
}
debug {
//packageNameSuffix "library"
buildConfigField "boolean", "SOME_FLAG", "true"
}
Run Code Online (Sandbox Code Playgroud)
为我的库和我的应用程序构建共享BuildConfig的正确方法是什么,其标志将在应用程序中构建时被覆盖?
Phi*_*hil 42
作为一种变通方法,您可以使用此方法,该方法使用反射从应用程序(而不是库)获取字段值:
/**
* Gets a field from the project's BuildConfig. This is useful when, for example, flavors
* are used at the project level to set custom fields.
* @param context Used to find the correct file
* @param fieldName The name of the field-to-access
* @return The value of the field, or {@code null} if the field is not found.
*/
public static Object getBuildConfigValue(Context context, String fieldName) {
try {
Class<?> clazz = Class.forName(context.getPackageName() + ".BuildConfig");
Field field = clazz.getField(fieldName);
return field.get(null);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
DEBUG例如,要获得该字段,只需从您的Activity:
boolean debug = (Boolean) getBuildConfigValue(this, "DEBUG");
Run Code Online (Sandbox Code Playgroud)
我也在AOSP问题跟踪器上分享了这个解决方案.
All*_*ode 32
以下解决方案/解决方法适用于我.它是由谷歌问题跟踪器中的一些人发布的:
尝试设置publishNonDefault到true在库项目:
android {
...
publishNonDefault true
...
}
Run Code Online (Sandbox Code Playgroud)
并将以下依赖项添加到使用该库的应用程序项目:
dependencies {
releaseCompile project(path: ':library', configuration: 'release')
debugCompile project(path: ':library', configuration: 'debug')
}
Run Code Online (Sandbox Code Playgroud)
这样,使用该库的项目包括库的正确构建类型.
Sco*_*rta 19
你无法做你想做的事,因为BuildConfig.SOME_FLAG它不会被正确地传播到你的图书馆; 构建类型本身不会传播到库 - 它们总是构建为RELEASE.这是错误https://code.google.com/p/android/issues/detail?id=52962
要解决这个问题:如果您可以控制所有库模块,那么您可以确保所有涉及的代码callToBigLibraries()都在可以使用ProGuard完全切割的类和包中,然后使用反射以便您可以访问它们.如果不存在,它们就会存在并优雅地降级.你基本上做了同样的事情,但是你在运行时进行检查而不是编译时间,这有点困难.
如果你在弄清楚如何做到这一点,请告诉我.如果需要,我可以提供样品.
我在应用程序和库中都使用了静态 BuildConfigHelper 类,这样我就可以将 BuildConfig 包设置为库中的最终静态变量。
在应用程序中,放置一个这样的类:
package com.yourbase;
import com.your.application.BuildConfig;
public final class BuildConfigHelper {
public static final boolean DEBUG = BuildConfig.DEBUG;
public static final String APPLICATION_ID = BuildConfig.APPLICATION_ID;
public static final String BUILD_TYPE = BuildConfig.BUILD_TYPE;
public static final String FLAVOR = BuildConfig.FLAVOR;
public static final int VERSION_CODE = BuildConfig.VERSION_CODE;
public static final String VERSION_NAME = BuildConfig.VERSION_NAME;
}
Run Code Online (Sandbox Code Playgroud)
在图书馆:
package com.your.library;
import android.support.annotation.Nullable;
import java.lang.reflect.Field;
public class BuildConfigHelper {
private static final String BUILD_CONFIG = "com.yourbase.BuildConfigHelper";
public static final boolean DEBUG = getDebug();
public static final String APPLICATION_ID = (String) getBuildConfigValue("APPLICATION_ID");
public static final String BUILD_TYPE = (String) getBuildConfigValue("BUILD_TYPE");
public static final String FLAVOR = (String) getBuildConfigValue("FLAVOR");
public static final int VERSION_CODE = getVersionCode();
public static final String VERSION_NAME = (String) getBuildConfigValue("VERSION_NAME");
private static boolean getDebug() {
Object o = getBuildConfigValue("DEBUG");
if (o != null && o instanceof Boolean) {
return (Boolean) o;
} else {
return false;
}
}
private static int getVersionCode() {
Object o = getBuildConfigValue("VERSION_CODE");
if (o != null && o instanceof Integer) {
return (Integer) o;
} else {
return Integer.MIN_VALUE;
}
}
@Nullable
private static Object getBuildConfigValue(String fieldName) {
try {
Class c = Class.forName(BUILD_CONFIG);
Field f = c.getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在您想要检查 BuildConfig.DEBUG 的库中的任何地方,您都可以检查 BuildConfigHelper.DEBUG 并从任何没有上下文的地方访问它,其他属性也是如此。我这样做是为了使库可以与我的所有应用程序一起使用,而无需以其他方式传入上下文或设置包名称,并且应用程序类只需要更改导入行以适应将其添加到新的应用
编辑:我想重申一下,这是从所有应用程序获取要分配给库中最终静态变量的值的最简单(此处仅列出一种)方法,无需上下文或硬编码某处的包名,这几乎和在默认库 BuildConfig 中的值一样好,对于在每个应用程序中更改导入行的最小维护。
For the case where the applicationId is not the same as the package (i.e. multiple applicationIds per project) AND you want to access from a library project:
Use Gradle to store the base package in resources.
In main/AndroidManifest.xml:
android {
applicationId "com.company.myappbase"
// note: using ${applicationId} here will be exactly as above
// and so NOT necessarily the applicationId of the generated APK
resValue "string", "build_config_package", "${applicationId}"
}
Run Code Online (Sandbox Code Playgroud)
In Java:
android {
applicationId "com.company.myappbase"
// note: using ${applicationId} here will be exactly as above
// and so NOT necessarily the applicationId of the generated APK
resValue "string", "build_config_package", "${applicationId}"
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
35126 次 |
| 最近记录: |