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 @@
+
+
+
+
+    
+
+