I know that I can use debugCompile
to only pull in a dependency
for the debug build
. Is there a good, streamlined way to do the
You have a few options.
Option 1: Include Stetho for all builds (using compile
instead of debugCompile
) and only initialize it in your Application
class for debug builds.
This is pretty easy to do. In your Application
class, check BuildConfig.DEBUG
like so:
if (BuildConfig.DEBUG) {
Stetho.initialize(
Stetho.newInitializerBuilder(this)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(this))
.build()
);
}
Option 2: Only include Stetho for debug builds, and create different Application
classes for debug and release builds.
Thanks to Gradle, applications can have different source sets for different build variants. By default, you have release and debug build types, so you can have three different source sets:
Your application code is likely all currently in the main
source set. You can simply create a new folder called debug
next to the main
folder in your application and mirror the structure of your main
folder for everything you want to add for debug builds.
In this case, you want an Application
class in your main
source set that doesn't reference Stetho at all.
Then you want an Application
class in your debug
source set that initializes Stetho like you normally would.
You can see an example of this setup in the Stetho sample. Specifically, here's the main Application class, and here's the debug Application class. Also note that they set up manifests in each source set that selects which Application class to use.
Using java reflection may be a perferct idea:
private void initStetho() {
if (BuildConfig.DEBUG) {
try {
Class<?> stethoClazz = Class.forName("com.facebook.stetho.Stetho");
Method method = stethoClazz.getMethod("initializeWithDefaults",Context.class);
method.invoke(null, this);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
then we can debug compile stetho:
debugCompile 'com.facebook.stetho:stetho:1.5.0'
Check the @Tanis answer.
Also you can use something like this:
Add the library only on debug version.
dependencies {
debugCompile 'com.facebook.stetho:stetho:1.1.1
}
In your Application you can do :
public class ExampleApplication extends Application {
@Override public void onCreate() {
super.onCreate();
StethoUtils.install(this);
}
}
Then you can create different StethoUtils
class in the debug/release version.
In src/debug/java/
public class StethoUtils{
public static void install(Application application){
Stetho.initialize(
Stetho.newInitializerBuilder(application)
.enableDumpapp(Stetho.defaultDumperPluginsProvider(application))
.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(application))
.build());
}
}
In src/release/java/
public class StethoUtils{
public static void install(Application application){
// do nothing
}
}
There is more cardinal method to connect stetho or any other lib only to debug builds - using reflection:
1) Connect your lib via debugImplementation - debugImplementation 'com.facebook.stetho:stetho:1.5.1'
2) Implement class with only static members - DynamicClassUtils:
public class DynamicClassUtils {
private static final String TAG = "DynamicClassUtils";
public static void safeInvokeStaticMethod(String fullClassName, String methodName, Class<?>[] types, Object... args) {
try {
Class<?> aClass = Class.forName(fullClassName);
Method aMethod = aClass.getMethod(methodName, types);
aMethod.invoke(null, args);
} catch (Throwable e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error when invoking static method, message: " + e.getMessage() + ", class: " + e.getClass());
e.printStackTrace();
}
}
}
public static <T> T safeGetInstance(String fullClassName, Object... args) {
try {
ArrayList<Class<?>> formalParameters = new ArrayList<>();
for (Object arg : args) {
formalParameters.add(arg.getClass());
}
Class<?> aClass = Class.forName(fullClassName);
Constructor<?> ctor = aClass.getConstructor(formalParameters.toArray(new Class<?>[0]));
return (T) ctor.newInstance(args);
} catch (Throwable e) {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error when creating instance, message: " + e.getMessage());
e.printStackTrace();
}
return null;
}
}
3) use that class to init stetho and its network interceptor:
if (BuildConfig.DEBUG) {
Class<?>[] argTypes = new Class<?>[1];
argTypes[0] = Context.class;
DynamicClassUtils.safeInvokeStaticMethod("com.facebook.stetho.Stetho", "initializeWithDefaults", argTypes, this);
}
if (BuildConfig.DEBUG) {
Interceptor interceptor = DynamicClassUtils.safeGetInstance("com.facebook.stetho.okhttp3.StethoInterceptor");
if (interceptor != null) client.addNetworkInterceptor(interceptor);
}