Last active
October 22, 2022 02:36
-
-
Save xrigau/11284124 to your computer and use it in GitHub Desktop.
Disable animations for Espresso tests - run with `gradle cATDD`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<manifest | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.novoda.espresso"> | |
<!-- For espresso testing purposes, this is removed in live builds, but not in dev builds --> | |
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" /> | |
<!-- ... --> | |
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: 'android' | |
android { | |
// ... | |
productFlavors { | |
dev { | |
// The one for development/testing | |
} | |
live { | |
// The flavour for releasing | |
} | |
} | |
} | |
// ... | |
task grantAnimationPermission(type: Exec, dependsOn: 'installDevDebug') { // or install{productFlavour}{buildType} | |
commandLine "adb shell pm grant $android.defaultConfig.packageName android.permission.SET_ANIMATION_SCALE".split(' ') | |
} | |
tasks.whenTaskAdded { task -> | |
if (task.name.startsWith('connectedAndroidTest')) { | |
task.dependsOn grantAnimationPermission | |
} | |
} | |
def copyAndReplaceText(source, dest, Closure replaceText) { | |
dest.write(replaceText(source.text)) | |
} | |
// Override Data in Manifest - This can be done using different Manifest files for each flavor, this way there's no need to modify the manifest | |
android.applicationVariants.all { variant -> | |
if (variant.name.startsWith('dev')) { // Where dev is the one you'll use to run Espresso tests | |
System.out.println("Not removing the SET_ANIMATION_SCALE permission for $variant.name") | |
return | |
} | |
System.out.println("Removing the SET_ANIMATION_SCALE permission for $variant.name") | |
variant.processManifest.doLast { | |
copyAndReplaceText(manifestOutputFile, manifestOutputFile) { | |
def replaced = it.replace('<uses-permission android:name="android.permission.SET_ANIMATION_SCALE"/>', ''); | |
if (replaced.contains('SET_ANIMATION_SCALE')) { | |
// For security, imagine an extra space is added before closing tag, then the replace would fail - TODO use regex | |
throw new RuntimeException("Don't ship with this permission! android.permission.SET_ANIMATION_SCALE") | |
} | |
replaced | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MyInstrumentationTestCase extends ActivityInstrumentationTestCase2<MyActivity> { | |
private SystemAnimations systemAnimations; | |
public MyInstrumentationTestCase() { | |
super(MyActivity.class); | |
} | |
@Override | |
protected void setUp() throws Exception { | |
super.setUp(); | |
systemAnimations = new SystemAnimations(getInstrumentation().getContext()); | |
systemAnimations.disableAll(); | |
getActivity(); | |
} | |
@Override | |
protected void tearDown() throws Exception { | |
super.tearDown(); | |
systemAnimations.enableAll(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SystemAnimations { | |
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 + " :'("); | |
} | |
} | |
} |
Have you seen https://github.com/linkedin/test-butler? Does the same thing but automatically, just need to install a tiny app on emulator.
Gradle support to auto install the test helper app works from 3.0.0-alpha1 or using a little gradle script
Why not just make a manifest in the existing androidTest flavor? I.e. app/src/androidTest/AndroidManifest.xml. Then you don't need any special build flavor to include this.
I see, because the disable animations thing is happening in the app, rather than in the instrumentation. If someone knows how to run it in the instrumentation, it would eliminate the need for build flavors and other gradle tricks.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@tasomaniac Not sure what I'm doing wrong but issuing any of the
adb
commands you listed in your Jan 4, 2016 comment doesn't have any effect until I restart my emulator?Tried with
Nexus 5 API 21
AVD and with Genymotion running an API 21 image; neither would change animation scales usingadb
until I restarted the emulator.