diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..173b3f416 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: android +jdk: openjdk7 +env: + global: + - ADB_INSTALL_TIMEOUT=8 +android: + components: + - build-tools-23.0.1 + - android-23 + - extra + - addon + - sys-img-armeabi-v7a-android-19 +before_script: + - echo no | android create avd --force -n test -t android-19 --abi armeabi-v7a -s "480x800" + - emulator -avd test -no-skin -no-audio -no-window & + - android-wait-for-emulator + - adb shell input keyevent 82 & +script: + - ./gradlew connectedAndroidTest + - cat app/build/reports/androidTests/connected/*html | awk '/
/ { on=1 } /<\/pre>/ { on = 0 } { if(on) print }' diff --git a/app/build.gradle b/app/build.gradle index c042caeb7..14e4da3d0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion "21.1.2" + buildToolsVersion "23.0.1" defaultConfig { applicationId "org.isoron.uhabits" @@ -43,3 +43,13 @@ dependencies { androidTestCompile 'com.android.support.test.espresso:espresso-intents:2.2.1' } + +task grantAnimationPermission(type: Exec, dependsOn: 'installDebug') { + commandLine "adb shell pm grant org.isoron.uhabits android.permission.SET_ANIMATION_SCALE".split(' ') +} + +tasks.whenTaskAdded { task -> + if (task.name.startsWith('connected')) { + task.dependsOn grantAnimationPermission + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/org/isoron/uhabits/ui/MainTest.java b/app/src/androidTest/java/org/isoron/uhabits/ui/MainTest.java index 0adfa290c..e76e4d783 100644 --- a/app/src/androidTest/java/org/isoron/uhabits/ui/MainTest.java +++ b/app/src/androidTest/java/org/isoron/uhabits/ui/MainTest.java @@ -63,6 +63,18 @@ public class MainTest MainActivity.class); @Before + public void setup() + { + disableAnimations(); + skipTutorial(); + } + + public void disableAnimations() + { + Context context = InstrumentationRegistry.getInstrumentation().getContext(); + new SystemAnimations(context).disableAll(); + } + public void skipTutorial() { try diff --git a/app/src/androidTest/java/org/isoron/uhabits/ui/SystemAnimations.java b/app/src/androidTest/java/org/isoron/uhabits/ui/SystemAnimations.java new file mode 100644 index 000000000..56138290e --- /dev/null +++ b/app/src/androidTest/java/org/isoron/uhabits/ui/SystemAnimations.java @@ -0,0 +1,68 @@ +package org.isoron.uhabits.ui; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.support.test.runner.AndroidJUnitRunner; +import android.util.Log; + +import java.lang.reflect.Method; + +/** + * 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() { + Log.i("SystemAnimations", "Trying to disable animations"); + int permStatus = context.checkCallingOrSelfPermission(ANIMATION_PERMISSION); + if (permStatus == PackageManager.PERMISSION_GRANTED) { + setSystemAnimationsScale(DISABLED); + } else { + Log.e("SystemAnimations", "Permission denied"); + } + + } + + 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}); + Log.i("SystemAnimations", "All animations successfully disabled"); + } catch (Exception e) { + Log.e("SystemAnimations", "Could not change animation scale to " + animationScale + " :'("); + } + } +} \ No newline at end of file diff --git a/app/src/debug/AndroidManifest.xml b/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..0829dbe45 --- /dev/null +++ b/app/src/debug/AndroidManifest.xml @@ -0,0 +1,26 @@ + + ++ + + +