Skip to content

Instantly share code, notes, and snippets.

@daj
Forked from xrigau/AndroidManifest.xml
Last active December 20, 2018 09:44
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save daj/7b48f1b8a92abf960e7b to your computer and use it in GitHub Desktop.
Save daj/7b48f1b8a92abf960e7b to your computer and use it in GitHub Desktop.
The set of changes required to disable animations any time Espresso tests run. These instructions will only work on emulators and on rooted devices. This is based on the instructions in: https://code.google.com/p/android-test-kit/wiki/DisablingAnimations
<?xml version="1.0" encoding="utf-8"?>
<!-- Put this file in the "debug" folder so it only gets merged into debug builds -->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cookbrite">
<!-- Disable animations on debug builds so that the animations do not interfere with Espresso
tests. Adding this permission to the manifest is not sufficient - you must also grant the
permission over adb! -->
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
</manifest>
public abstract class BaseStatelessBlackBoxEspressoTest<T extends Activity> extends ActivityInstrumentationTestCase2<T> {
private SystemAnimations mSystemAnimations;
public BaseStatelessBlackBoxEspressoTest(Class clazz) {
super(clazz);
}
@Override
protected void setUp() throws Exception {
super.setUp();
mSystemAnimations = new SystemAnimations(getInstrumentation().getContext());
mSystemAnimations.disableAll();
getActivity();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
// If you want to test this entire Gist is working, comment out this line and
// run a test. Then check these options in Settings -> Developer:
// -Window animation scale
// -Transition animation scale
// -Animator duration scale
// They should all show "Animation off". Then re-enable this line and run a
// test again, this time it will show "Animation scale 1x"
mSystemAnimations.enableAll();
}
}
apply plugin: 'android'
android {
productFlavors {
dev {
applicationId "com.cookbrite.dev"
}
production {
applicationId "com.cookbrite.android"
}
}
// ...
// Get the path to ADB. Required when running tests directly from Android Studio.
// Source: http://stackoverflow.com/a/26771087/112705
def adb = android.getAdbExe().toString()
// Source: http://stackoverflow.com/q/29908110/112705
afterEvaluate {
task grantAnimationPermissionDev(type: Exec, dependsOn: 'installDevDebug') {
commandLine "$adb shell pm grant $android.productFlavors.dev.applicationId android.permission.SET_ANIMATION_SCALE".split(' ')
}
task grantAnimationPermissionProduction(type: Exec, dependsOn: 'installProductionDebug') {
commandLine "$adb shell pm grant $android.productFlavors.production.applicationId android.permission.SET_ANIMATION_SCALE".split(' ')
}
// When launching individual tests from Android Studio, it seems that only the assemble tasks
// get called directly, not the install* versions
tasks.each { task ->
if (task.name.startsWith('assembleDevDebugAndroidTest')) {
task.dependsOn grantAnimationPermissionDev
} else if (task.name.startsWith('assembleProductionDebugAndroidTest')) {
task.dependsOn grantAnimationPermissionProduction
}
}
}
/**
* Disable animations so that they do not interfere with Espresso tests.
*
* Source: https://code.google.com/p/android-test-kit/wiki/DisablingAnimations
*/
public final class SystemAnimations extends AndroidJUnitRunner {
private static final String ANIMATION_PERMISSION = "android.permission.SET_ANIMATION_SCALE";
private static final float DISABLED = 0.0f;
private static final float DEFAULT = 1.0f;
private final Context context;
SystemAnimations(Context context) {
this.context = context;
}
void disableAll() {
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(DISABLED);
}
}
void enableAll() {
int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION);
if (permStatus == PackageManager.PERMISSION_GRANTED) {
setSystemAnimationsScale(DEFAULT);
}
}
private void setSystemAnimationsScale(float animationScale) {
try {
Class<?> windowManagerStubClazz = Class.forName("android.view.IWindowManager$Stub");
Method asInterface = windowManagerStubClazz.getDeclaredMethod("asInterface", IBinder.class);
Class<?> serviceManagerClazz = Class.forName("android.os.ServiceManager");
Method getService = serviceManagerClazz.getDeclaredMethod("getService", String.class);
Class<?> windowManagerClazz = Class.forName("android.view.IWindowManager");
Method setAnimationScales = windowManagerClazz.getDeclaredMethod("setAnimationScales", float[].class);
Method getAnimationScales = windowManagerClazz.getDeclaredMethod("getAnimationScales");
IBinder windowManagerBinder = (IBinder) getService.invoke(null, "window");
Object windowManagerObj = asInterface.invoke(null, windowManagerBinder);
float[] currentScales = (float[]) getAnimationScales.invoke(windowManagerObj);
for (int i = 0; i < currentScales.length; i++) {
currentScales[i] = animationScale;
}
setAnimationScales.invoke(windowManagerObj, new Object[]{currentScales});
} catch (Exception e) {
Log.e("SystemAnimations", "Could not change animation scale to " + animationScale + " :'(");
}
}
}
@GaborPeto
Copy link

What's the reason for SystemAnimations extending AndroidJUnitRunner ?

@danielgomezrico
Copy link

I made some editions here if someone is interested https://gist.github.com/danielgomezrico/9371a79a7222a156ddad

@dharmendrainnovify
Copy link

@caipivara your link it broken

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment