问题三:无法设置debug编译类型
在lib工程中无论怎么设置编译类型,最后生成的aar包中始终都是release版本,该问题见google反馈。既然不可设置编译类型,我们可以在aar包代码中通过反射来获取应用的编译类型:
private 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;
}
//使用
String buildType = getBuildConfigValue(ctx,"BUILD_TYPE").toString();
if (!TextUtils.isEmpty(buildType) && buildType.equals("debug")) { // debug
...
} else { // release
...
}
但是,这里面还有一个坑,系统版本在4.4以下的设备中,该方法无法获得包名,会抛空指针错误。以下我们给出完整的解决方案:
public class BuildConfigProvider {
private static Context sContext;
private static String packageName;
public static String getBuildType() {
String buildType = (String) getBuildConfigValue("BUILD_TYPE");
if ("debug".equals(buildType)) {
buildType = "debug";
}
if ("release".equals(buildType)) {
buildType = "release";
}
return buildType;
}
public static final boolean isDebug() {
return BuildConfig.DEBUG;
}
/**
* 通过反射获取ApplicationContext
*
* @return
*/
private static Context getContext() {
if (sContext == null) {
try {
final Class> activityThreadClass = Class.forName("android.app.ActivityThread");
final Method currentActivityThread = activityThreadClass.getDeclaredMethod("currentActivityThread");
final Object activityThread = currentActivityThread.invoke(null);
final Method getApplication = activityThreadClass.getDeclaredMethod("getApplication");
final Application application = (Application) getApplication.invoke(activityThread);
sContext = application.getApplicationContext();
} catch (Exception e) {
e.printStackTrace();
}
}
return sContext;
}
/**
* 通过反射获取包名
*
* @return
*/
private static String getPackageName() {
if (packageName == null) {
try {
final Class> activityThreadClass = Class.forName("android.app.ActivityThread");
final Method currentPackageName = activityThreadClass.getDeclaredMethod("currentPackageName");
packageName = (String) currentPackageName.invoke(null);
} catch (Exception e) {
packageName = getContext().getPackageName();
}
}
return packageName;
}
public static Object getBuildConfigValue(String fieldName) {
try {
Class> clazz = Class.forName(packageName + ".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();
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
return "";
}
}
当然,有人可能会说,既然可以通过反射得到ApplicationContext,就没必要再去反射获得包名了,这里只是提供不同的解决方案以作参考。