installedApps) {
98 | apps.clear();
99 | apps.addAll(installedApps);
100 | notifyDataSetChanged();
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/fr/xebia/jmartinez/installed/internal/ActivityRule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Jake Wharton
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package fr.xebia.jmartinez.installed.internal;
17 |
18 | import android.app.Activity;
19 | import android.app.Instrumentation;
20 | import android.content.Intent;
21 | import android.support.test.InstrumentationRegistry;
22 | import org.junit.Before;
23 | import org.junit.Rule;
24 | import org.junit.rules.TestRule;
25 | import org.junit.runner.Description;
26 | import org.junit.runners.model.Statement;
27 |
28 | /**
29 | * A JUnit {@link org.junit.Rule @Rule} which launches an activity when your test starts. Stop extending
30 | * gross {@code ActivityInstrumentationBarfCase2}!
31 | *
32 | * Usage:
33 | *
{@code
34 | * @Rule
35 | * public final ActivityRule example =
36 | * new ActivityRule<>(ExampleActivity.class);
37 | * }
38 | *
39 | * This will automatically launch the activity for each test method. The instance will also be
40 | * created sooner should you need to use it in a {@link org.junit.Before @Before} method.
41 | *
42 | * You can also customize the way in which the activity is launched by overriding
43 | * {@link #getLaunchIntent(String, Class)} and customizing or replacing the {@link android.content.Intent}.
44 | *
{@code
45 | * @Rule
46 | * public final ActivityRule example =
47 | * new ActivityRule(ExampleActivity.class) {
48 | * @Override
49 | * protected Intent getLaunchIntent(String packageName, Class activityClass) {
50 | * Intent intent = super.getLaunchIntent(packageName, activityClass);
51 | * intent.putExtra("Hello", "World!");
52 | * return intent;
53 | * }
54 | * };
55 | * }
56 | */
57 | public class ActivityRule implements TestRule {
58 | private final Class activityClass;
59 |
60 | private T activity;
61 | private Instrumentation instrumentation;
62 |
63 | public ActivityRule(Class activityClass) {
64 | this.activityClass = activityClass;
65 | }
66 |
67 | protected Intent getLaunchIntent(String targetPackage, Class activityClass) {
68 | Intent intent = new Intent(Intent.ACTION_MAIN);
69 | intent.setClassName(targetPackage, activityClass.getName());
70 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
71 | return intent;
72 | }
73 |
74 | public final Instrumentation instrumentation() {
75 | launchActivity();
76 | return instrumentation;
77 | }
78 |
79 | @Override public final Statement apply(final Statement base, Description description) {
80 | return new Statement() {
81 | @Override public void evaluate() throws Throwable {
82 | launchActivity();
83 |
84 | base.evaluate();
85 |
86 | if (!activity.isFinishing()) {
87 | activity.finish();
88 | }
89 | activity = null; // Eager reference kill in case someone leaked our reference.
90 | }
91 | };
92 | }
93 |
94 | private Instrumentation fetchInstrumentation() {
95 | Instrumentation result = instrumentation;
96 | return result != null ? result
97 | : (instrumentation = InstrumentationRegistry.getInstrumentation());
98 | }
99 |
100 | @SuppressWarnings("unchecked") // Guarded by generics at the constructor.
101 | private void launchActivity() {
102 | if (activity != null) return;
103 |
104 | Instrumentation instrumentation = fetchInstrumentation();
105 |
106 | String targetPackage = instrumentation.getTargetContext().getPackageName();
107 | Intent intent = getLaunchIntent(targetPackage, activityClass);
108 |
109 | activity = (T) instrumentation.startActivitySync(intent);
110 | instrumentation.waitForIdleSync();
111 | }
112 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/fr/xebia/jmartinez/installed/internal/JUnitTestCase.java:
--------------------------------------------------------------------------------
1 | package fr.xebia.jmartinez.installed.internal;
2 |
3 | import android.app.Activity;
4 | import android.app.Instrumentation;
5 | import android.support.test.InstrumentationRegistry;
6 | import android.support.test.internal.runner.lifecycle.ActivityLifecycleMonitorRegistry;
7 | import android.support.test.runner.lifecycle.ActivityLifecycleMonitor;
8 | import android.support.test.runner.lifecycle.Stage;
9 |
10 | import com.android.support.test.deps.guava.base.Throwables;
11 | import com.android.support.test.deps.guava.collect.Iterables;
12 | import com.android.support.test.deps.guava.collect.Sets;
13 |
14 | import org.junit.After;
15 | import org.junit.Rule;
16 |
17 | import java.util.Collection;
18 | import java.util.Set;
19 | import java.util.concurrent.Callable;
20 | import java.util.concurrent.atomic.AtomicReference;
21 |
22 | public class JUnitTestCase {
23 |
24 | @Rule
25 | public final ActivityRule main;
26 |
27 | @Rule
28 | public final SpoonRule spoonRule = new SpoonRule();
29 |
30 | public JUnitTestCase(Class mainActivity) {
31 | this.main = new ActivityRule<>(mainActivity);
32 | }
33 |
34 | public void takeScreenshot(String tag) {
35 | spoonRule.takeScreenshot(getCurrentActivity(), tag);
36 | }
37 |
38 | @After
39 | public void tearDown() throws Exception {
40 | closeAllActivities(main.instrumentation());
41 | }
42 |
43 | protected Activity getCurrentActivity() {
44 | Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
45 | instrumentation.waitForIdleSync();
46 | final Activity[] activity = new Activity[1];
47 | instrumentation.runOnMainSync(new Runnable() {
48 | @Override
49 | public void run() {
50 | ActivityLifecycleMonitor activityLifecycleMonitor = ActivityLifecycleMonitorRegistry.getInstance();
51 | Collection resumedActivities = activityLifecycleMonitor.getActivitiesInStage(Stage.RESUMED);
52 | activity[0] = Iterables.getOnlyElement(resumedActivities);
53 | }
54 | });
55 | return activity[0];
56 | }
57 |
58 | protected static void closeAllActivities(Instrumentation instrumentation) throws Exception {
59 | final int NUMBER_OF_RETRIES = 100;
60 | int i = 0;
61 | while (closeActivity(instrumentation)) {
62 | if (i++ > NUMBER_OF_RETRIES) {
63 | throw new AssertionError("Limit of retries excesses");
64 | }
65 | Thread.sleep(200);
66 | }
67 | }
68 |
69 | protected static X callOnMainSync(Instrumentation instrumentation, final Callable callable) throws Exception {
70 | final AtomicReference retAtomic = new AtomicReference<>();
71 | final AtomicReference exceptionAtomic = new AtomicReference<>();
72 | instrumentation.runOnMainSync(new Runnable() {
73 | @Override
74 | public void run() {
75 | try {
76 | retAtomic.set(callable.call());
77 | } catch (Throwable e) {
78 | exceptionAtomic.set(e);
79 | }
80 | }
81 | });
82 | final Throwable exception = exceptionAtomic.get();
83 | if (exception != null) {
84 | Throwables.propagateIfInstanceOf(exception, Exception.class);
85 | Throwables.propagate(exception);
86 | }
87 | return retAtomic.get();
88 | }
89 |
90 | public static Set getActivitiesInStages(Stage... stages) {
91 | final Set activities = Sets.newHashSet();
92 | final ActivityLifecycleMonitor instance = ActivityLifecycleMonitorRegistry.getInstance();
93 | for (Stage stage : stages) {
94 | final Collection activitiesInStage = instance.getActivitiesInStage(stage);
95 | if (activitiesInStage != null) {
96 | activities.addAll(activitiesInStage);
97 | }
98 | }
99 | return activities;
100 | }
101 |
102 | private static boolean closeActivity(Instrumentation instrumentation) throws Exception {
103 | final Boolean activityClosed = callOnMainSync(instrumentation, new Callable() {
104 | @Override
105 | public Boolean call() throws Exception {
106 | final Set activities = getActivitiesInStages(Stage.RESUMED,
107 | Stage.STARTED, Stage.PAUSED, Stage.STOPPED, Stage.CREATED);
108 | activities.removeAll(getActivitiesInStages(Stage.DESTROYED));
109 | if (activities.size() > 0) {
110 | final Activity activity = activities.iterator().next();
111 | activity.finish();
112 | return true;
113 | } else {
114 | return false;
115 | }
116 | }
117 | });
118 | if (activityClosed) {
119 | instrumentation.waitForIdleSync();
120 | }
121 | return activityClosed;
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------