浏览代码

Add flurry analytics

Various changes to activity recorder algorithm
tags/ActivityRecorder/0.2.0
Chris Smith 14 年前
父节点
当前提交
9f8b155648
共有 22 个文件被更改,包括 277 次插入31 次删除
  1. 1
    1
      code/ActivityRecorder/AndroidManifest.xml
  2. 4
    0
      code/ActivityRecorder/build.xml
  3. 二进制
      code/ActivityRecorder/dist/ActivityRecorder.apk
  4. 二进制
      code/ActivityRecorder/lib/FlurryAgent.jar
  5. 3
    1
      code/ActivityRecorder/nbproject/project.properties
  6. 3
    0
      code/ActivityRecorder/res/values/strings.xml
  7. 19
    0
      code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/ActivityRecorderActivity.java
  8. 2
    2
      code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/ClassifierService.java
  9. 10
    7
      code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/R.java
  10. 116
    15
      code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/RecorderService.java
  11. 4
    3
      code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/rpc/Classification.java
  12. 1
    1
      code/SensorLogger/AndroidManifest.xml
  13. 3
    0
      code/SensorLogger/build.xml
  14. 二进制
      code/SensorLogger/dist/SensorLogger.apk
  15. 二进制
      code/SensorLogger/lib/FlurryAgent.jar
  16. 3
    1
      code/SensorLogger/nbproject/project.properties
  17. 18
    0
      code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/CountdownActivity.java
  18. 19
    0
      code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/IntroActivity.java
  19. 18
    0
      code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/RecordingActivity.java
  20. 25
    0
      code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/ResultsActivity.java
  21. 17
    0
      code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/ThanksActivity.java
  22. 11
    0
      website/index.html

+ 1
- 1
code/ActivityRecorder/AndroidManifest.xml 查看文件

1
 <?xml version="1.0" encoding="UTF-8"?>
1
 <?xml version="1.0" encoding="UTF-8"?>
2
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
-     package="uk.co.md87.android.activityrecorder" android:versionCode="2" android:versionName="0.1.3">
3
+     package="uk.co.md87.android.activityrecorder" android:versionCode="4" android:versionName="0.2.1">
4
     <application android:label="Activity Recorder" android:icon="@drawable/icon">
4
     <application android:label="Activity Recorder" android:icon="@drawable/icon">
5
          <activity android:name=".ActivityRecorderActivity" android:label="Activity Recorder">
5
          <activity android:name=".ActivityRecorderActivity" android:label="Activity Recorder">
6
             <intent-filter>
6
             <intent-filter>

+ 4
- 0
code/ActivityRecorder/build.xml 查看文件

18
 
18
 
19
     <target depends="init,compile,-pre-jar,-dex,-package-res-and-assets,-package-res-no-assets,-package-dex,-build-without-signing,-post-jar" description="Build unsigned JAR." name="unsigned-jar"/>
19
     <target depends="init,compile,-pre-jar,-dex,-package-res-and-assets,-package-res-no-assets,-package-dex,-build-without-signing,-post-jar" description="Build unsigned JAR." name="unsigned-jar"/>
20
 
20
 
21
+    <target name="-pre-jar">
22
+       <unzip src="lib/FlurryAgent.jar" dest="${build.classes.dir}" overwrite="true"/>
23
+    </target>
24
+
21
 </project>
25
 </project>

二进制
code/ActivityRecorder/dist/ActivityRecorder.apk 查看文件


二进制
code/ActivityRecorder/lib/FlurryAgent.jar 查看文件


+ 3
- 1
code/ActivityRecorder/nbproject/project.properties 查看文件

17
 dist.dir=dist
17
 dist.dir=dist
18
 dist.javadoc.dir=${dist.dir}/javadoc
18
 dist.javadoc.dir=${dist.dir}/javadoc
19
 excludes=
19
 excludes=
20
+file.reference.FlurryAgent.jar=lib/FlurryAgent.jar
20
 gen.source.dir=${src.dir}
21
 gen.source.dir=${src.dir}
21
 includes=**
22
 includes=**
22
 intermediate.dex=${build.dir}/classes.dex
23
 intermediate.dex=${build.dir}/classes.dex
23
-javac.classpath=
24
+javac.classpath=\
25
+    ${file.reference.FlurryAgent.jar}
24
 # Space-separated list of extra javac options
26
 # Space-separated list of extra javac options
25
 javac.compilerargs=
27
 javac.compilerargs=
26
 javac.deprecation=false
28
 javac.deprecation=false

+ 3
- 0
code/ActivityRecorder/res/values/strings.xml 查看文件

9
 
9
 
10
     <string name="activity_unknown">Unknown</string>
10
     <string name="activity_unknown">Unknown</string>
11
     <string name="activity_walking">Walking</string>
11
     <string name="activity_walking">Walking</string>
12
+    <string name="activity_walking_stairs">Walking (stairs)</string>
12
     <string name="activity_walking_stairs_up">Walking (up stairs)</string>
13
     <string name="activity_walking_stairs_up">Walking (up stairs)</string>
13
     <string name="activity_walking_stairs_down">Walking (down stairs)</string>
14
     <string name="activity_walking_stairs_down">Walking (down stairs)</string>
14
     <string name="activity_dancing">Dancing</string>
15
     <string name="activity_dancing">Dancing</string>
16
+    <string name="activity_idle">Idle</string>
15
     <string name="activity_idle_standing">Standing still</string>
17
     <string name="activity_idle_standing">Standing still</string>
16
     <string name="activity_idle_sitting">Sitting down</string>
18
     <string name="activity_idle_sitting">Sitting down</string>
19
+    <string name="activity_vehicle">Travelling</string>
17
     <string name="activity_vehicle_bus">Travelling by bus</string>
20
     <string name="activity_vehicle_bus">Travelling by bus</string>
18
     <string name="activity_vehicle_car">Travelling by car</string>
21
     <string name="activity_vehicle_car">Travelling by car</string>
19
 </resources>
22
 </resources>

+ 19
- 0
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/ActivityRecorderActivity.java 查看文件

22
 import android.widget.ArrayAdapter;
22
 import android.widget.ArrayAdapter;
23
 import android.widget.Button;
23
 import android.widget.Button;
24
 import android.widget.ListView;
24
 import android.widget.ListView;
25
+import com.flurry.android.FlurryAgent;
25
 import java.util.List;
26
 import java.util.List;
26
 
27
 
27
 import uk.co.md87.android.activityrecorder.rpc.ActivityRecorderBinder;
28
 import uk.co.md87.android.activityrecorder.rpc.ActivityRecorderBinder;
77
         public void onClick(View arg0) {
78
         public void onClick(View arg0) {
78
             try {
79
             try {
79
                 if (service.isRunning()) {
80
                 if (service.isRunning()) {
81
+                    FlurryAgent.onEvent("recording_stop");
80
                     stopService(new Intent(ActivityRecorderActivity.this,
82
                     stopService(new Intent(ActivityRecorderActivity.this,
81
                             RecorderService.class));
83
                             RecorderService.class));
82
                     unbindService(connection);
84
                     unbindService(connection);
83
                     bindService(new Intent(ActivityRecorderActivity.this, RecorderService.class),
85
                     bindService(new Intent(ActivityRecorderActivity.this, RecorderService.class),
84
                             connection, BIND_AUTO_CREATE);
86
                             connection, BIND_AUTO_CREATE);
85
                 } else {
87
                 } else {
88
+                    FlurryAgent.onEvent("recording_start");
86
                     handler.removeCallbacks(updateRunnable);
89
                     handler.removeCallbacks(updateRunnable);
87
                     ((Button) findViewById(R.id.togglebutton)).setEnabled(false);
90
                     ((Button) findViewById(R.id.togglebutton)).setEnabled(false);
88
 
91
 
175
         return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getDeviceId();
178
         return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getDeviceId();
176
     }
179
     }
177
 
180
 
181
+    /** {@inheritDoc} */
182
+    @Override
183
+    protected void onStart() {
184
+        super.onStart();
185
+
186
+        FlurryAgent.onStartSession(this, "EMKSQFUWSCW51AKBL2JJ");
187
+    }
188
+
189
+    /** {@inheritDoc} */
190
+    @Override
191
+    protected void onStop() {
192
+        super.onStop();
193
+
194
+        FlurryAgent.onEndSession(this);
195
+    }
196
+
178
 }
197
 }

+ 2
- 2
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/ClassifierService.java 查看文件

51
     public void onStart(Intent intent, int startId) {
51
     public void onStart(Intent intent, int startId) {
52
         super.onStart(intent, startId);
52
         super.onStart(intent, startId);
53
 
53
 
54
-        Log.i(getClass().getName(), "Starting classifier");
54
+        //Log.i(getClass().getName(), "Starting classifier");
55
 
55
 
56
         data = intent.getFloatArrayExtra("data");
56
         data = intent.getFloatArrayExtra("data");
57
 
57
 
111
 
111
 
112
         classification = bestActivity;
112
         classification = bestActivity;
113
 
113
 
114
-        Log.i(getClass().getName(), "Classification: " + classification);
114
+        //Log.i(getClass().getName(), "Classification: " + classification);
115
 
115
 
116
         bindService(new Intent(this, RecorderService.class), connection, BIND_AUTO_CREATE);
116
         bindService(new Intent(this, RecorderService.class), connection, BIND_AUTO_CREATE);
117
     }
117
     }

+ 10
- 7
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/R.java 查看文件

25
         public static final int basic_model=0x7f040000;
25
         public static final int basic_model=0x7f040000;
26
     }
26
     }
27
     public static final class string {
27
     public static final class string {
28
-        public static final int activity_dancing=0x7f050008;
29
-        public static final int activity_idle_sitting=0x7f05000a;
30
-        public static final int activity_idle_standing=0x7f050009;
28
+        public static final int activity_dancing=0x7f050009;
29
+        public static final int activity_idle=0x7f05000a;
30
+        public static final int activity_idle_sitting=0x7f05000c;
31
+        public static final int activity_idle_standing=0x7f05000b;
31
         public static final int activity_unknown=0x7f050004;
32
         public static final int activity_unknown=0x7f050004;
32
-        public static final int activity_vehicle_bus=0x7f05000b;
33
-        public static final int activity_vehicle_car=0x7f05000c;
33
+        public static final int activity_vehicle=0x7f05000d;
34
+        public static final int activity_vehicle_bus=0x7f05000e;
35
+        public static final int activity_vehicle_car=0x7f05000f;
34
         public static final int activity_walking=0x7f050005;
36
         public static final int activity_walking=0x7f050005;
35
-        public static final int activity_walking_stairs_down=0x7f050007;
36
-        public static final int activity_walking_stairs_up=0x7f050006;
37
+        public static final int activity_walking_stairs=0x7f050006;
38
+        public static final int activity_walking_stairs_down=0x7f050008;
39
+        public static final int activity_walking_stairs_up=0x7f050007;
37
         public static final int app_name=0x7f050000;
40
         public static final int app_name=0x7f050000;
38
         public static final int error_disconnected=0x7f050001;
41
         public static final int error_disconnected=0x7f050001;
39
         public static final int service_disabled=0x7f050003;
42
         public static final int service_disabled=0x7f050003;

+ 116
- 15
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/RecorderService.java 查看文件

22
 import java.io.InputStream;
22
 import java.io.InputStream;
23
 import java.io.ObjectInputStream;
23
 import java.io.ObjectInputStream;
24
 import java.util.ArrayList;
24
 import java.util.ArrayList;
25
+import java.util.HashMap;
25
 import java.util.List;
26
 import java.util.List;
26
 import java.util.Map;
27
 import java.util.Map;
27
 
28
 
34
  */
35
  */
35
 public class RecorderService extends Service {
36
 public class RecorderService extends Service {
36
 
37
 
38
+    static final double DELTA = 0.25;
39
+    static final double THRESHOLD = 0.5;
40
+
41
+    private final HashMap<String, HashMap<String, Double>> scores
42
+            = new HashMap<String, HashMap<String, Double>>() {{
43
+        put("", new HashMap<String, Double>() {{
44
+            put("null", 0.5d);
45
+            put("CLASSIFIED", 0.5d);
46
+        }});
47
+
48
+        put("CLASSIFIED", new HashMap<String, Double>() {{
49
+            put("null", 0.2d);
50
+            put("DANCING", 0.2d);
51
+            put("WALKING", 0.2d);
52
+            put("VEHICLE", 0.2d);
53
+            put("IDLE", 0.2d);
54
+        }});
55
+
56
+        put("CLASSIFIED/WALKING", new HashMap<String, Double>() {{
57
+            put("null", 0.5d);
58
+            put("STAIRS", 0.5d);
59
+        }});
60
+
61
+        put("CLASSIFIED/VEHICLE", new HashMap<String, Double>() {{
62
+            put("null", 0.333d);
63
+            put("CAR", 0.333d);
64
+            put("BUS", 0.333d);
65
+        }});
66
+
67
+        put("CLASSIFIED/IDLE", new HashMap<String, Double>() {{
68
+            put("null", 0.333d);
69
+            put("STANDING", 0.333d);
70
+            put("SITTING", 0.333d);
71
+        }});
72
+
73
+        put("CLASSIFIED/WALKING/STAIRS", new HashMap<String, Double>() {{
74
+            put("null", 0.333d);
75
+            put("UP", 0.333d);
76
+            put("DOWN", 0.333d);
77
+        }});
78
+    }};
79
+
37
     private final ActivityRecorderBinder.Stub binder = new ActivityRecorderBinder.Stub() {
80
     private final ActivityRecorderBinder.Stub binder = new ActivityRecorderBinder.Stub() {
38
 
81
 
39
         public void submitClassification(String classification) throws RemoteException {
82
         public void submitClassification(String classification) throws RemoteException {
40
-            Log.i(getClass().getName(), "Adding classification: " + classification);
83
+            //Log.i(getClass().getName(), "Received classification: " + classification);
41
 
84
 
42
-            if (!classifications.isEmpty() && classification.equals(classifications
43
-                    .get(classifications.size() - 1).getClassification())) {
44
-                classifications.get(classifications.size() - 1).updateEnd(System.currentTimeMillis());
45
-            } else {
46
-                classifications.add(new Classification(classification, System.currentTimeMillis()));
47
-            }
85
+            updateScores(classification);
48
         }
86
         }
49
 
87
 
50
         public List<Classification> getClassifications() throws RemoteException {
88
         public List<Classification> getClassifications() throws RemoteException {
111
     }
149
     }
112
 
150
 
113
     public void sample() {
151
     public void sample() {
114
-        Log.i(getClass().getName(), "Sampling");
152
+        //Log.i(getClass().getName(), "Sampling");
115
         data[(nextSample * 2) % 256] = values[0];
153
         data[(nextSample * 2) % 256] = values[0];
116
         data[(nextSample * 2 + 1) % 256] = values[1];
154
         data[(nextSample * 2 + 1) % 256] = values[1];
117
         
155
         
120
             System.arraycopy(data, 0, cache, 0, 256);
158
             System.arraycopy(data, 0, cache, 0, 256);
121
             analyse(cache);
159
             analyse(cache);
122
 
160
 
123
-            if (nextSample == 192) {
124
-                unregister();
125
-                return;
126
-            }
161
+            unregister();
162
+            return;
127
         }
163
         }
128
 
164
 
129
         handler.postDelayed(sampleRunnable, 50);
165
         handler.postDelayed(sampleRunnable, 50);
130
     }
166
     }
131
 
167
 
132
     public void analyse(float[] data) {
168
     public void analyse(float[] data) {
133
-        Log.i(getClass().getName(), "Analysing");
169
+        //Log.i(getClass().getName(), "Analysing");
134
         final Intent intent = new Intent(this, ClassifierService.class);
170
         final Intent intent = new Intent(this, ClassifierService.class);
135
         intent.putExtra("data", data);
171
         intent.putExtra("data", data);
136
         startService(intent);
172
         startService(intent);
174
         manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
210
         manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
175
         handler.postDelayed(registerRunnable, 1000);
211
         handler.postDelayed(registerRunnable, 1000);
176
 
212
 
213
+        classifications.add(new Classification("", System.currentTimeMillis()));
214
+
177
         wl.acquire();
215
         wl.acquire();
178
     }
216
     }
179
 
217
 
180
     void register() {
218
     void register() {
181
-        Log.i(getClass().getName(), "Registering");
219
+        //Log.i(getClass().getName(), "Registering");
182
         nextSample = 0;
220
         nextSample = 0;
183
         manager.registerListener(accelListener,
221
         manager.registerListener(accelListener,
184
                 manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
222
                 manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
185
                 SensorManager.SENSOR_DELAY_FASTEST);
223
                 SensorManager.SENSOR_DELAY_FASTEST);
186
         handler.postDelayed(sampleRunnable, 50);
224
         handler.postDelayed(sampleRunnable, 50);
187
-        handler.postDelayed(registerRunnable, 60000);
225
+        handler.postDelayed(registerRunnable, 30000);
188
     }
226
     }
189
 
227
 
190
     void unregister() {
228
     void unregister() {
191
         manager.unregisterListener(accelListener);
229
         manager.unregisterListener(accelListener);
192
     }
230
     }
193
 
231
 
232
+    void updateScores(final String classification) {
233
+        String path = "";
234
+
235
+        for (String part : classification.split("/")) {
236
+            if (!scores.containsKey(path)) {
237
+                throw new RuntimeException("Path not found: " + path
238
+                        + " (classification: " + classification + ")");
239
+            }
240
+
241
+            updateScores(scores.get(path), part);
242
+            path = path + (path.length() == 0 ? "" : "/") + part;
243
+        }
244
+
245
+        if (scores.containsKey(path)) {
246
+            // This classification has children which we're not using
247
+            // e.g. we've received CLASSIFIED/WALKING, but we're not walking
248
+            //      up or down stairs
249
+            updateScores(scores.get(path), "null");
250
+        }
251
+
252
+        final String best = getClassification();
253
+
254
+        if (!classifications.isEmpty() && best.equals(classifications
255
+                    .get(classifications.size() - 1).getClassification())) {
256
+            classifications.get(classifications.size() - 1).updateEnd(System.currentTimeMillis());
257
+        } else {
258
+            classifications.add(new Classification(best, System.currentTimeMillis()));
259
+        }
260
+    }
261
+
262
+    String getClassification() {
263
+        String path = "";
264
+
265
+        do {
266
+            final Map<String, Double> map = scores.get(path);
267
+            double best = THRESHOLD;
268
+            String bestPath = "null";
269
+
270
+            for (Map.Entry<String, Double> entry : map.entrySet()) {
271
+                if (entry.getValue() >= best) {
272
+                    best = entry.getValue();
273
+                    bestPath = entry.getKey();
274
+                }
275
+            }
276
+
277
+            path = path + (path.length() == 0 ? "" : "/") + bestPath;
278
+        } while (scores.containsKey(path));
279
+
280
+        return path.replaceAll("(^CLASSIFIED)?/?null$", "");
281
+    }
282
+
283
+    void updateScores(final Map<String, Double> map, final String target) {
284
+        for (Map.Entry<String, Double> entry : map.entrySet()) {
285
+            //Log.d(getClass().getName(), "Score for " + entry.getKey() + " was: " + entry.getValue());
286
+            entry.setValue(entry.getValue() * (1 - DELTA));
287
+
288
+            if (entry.getKey().equals(target)) {
289
+                entry.setValue(entry.getValue() + DELTA);
290
+            }
291
+            //Log.d(getClass().getName(), "Score for " + entry.getKey() + " is now: " + entry.getValue());
292
+        }
293
+    }
294
+
194
     @Override
295
     @Override
195
     public void onDestroy() {
296
     public void onDestroy() {
196
         super.onDestroy();
297
         super.onDestroy();

+ 4
- 3
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/rpc/Classification.java 查看文件

55
         final int length = (int) ((end - start) / 1000);
55
         final int length = (int) ((end - start) / 1000);
56
 
56
 
57
         if (length < 60) {
57
         if (length < 60) {
58
-            duration = length + " secs";
58
+            duration = "<1 min";
59
         } else if (length < 60 * 60) {
59
         } else if (length < 60 * 60) {
60
             duration = (length / 60) + " mins";
60
             duration = (length / 60) + " mins";
61
         } else {
61
         } else {
73
     }
73
     }
74
 
74
 
75
     public Classification withContext(final Context context) {
75
     public Classification withContext(final Context context) {
76
-        String name = "activity_" + getClassification().substring(11)
77
-                .replace("/", "_").toLowerCase();
76
+        String name = "activity" + (getClassification().length() == 0
77
+                ? "_unknown" : getClassification().substring(10)
78
+                .replace("/", "_").toLowerCase());
78
 
79
 
79
         niceClassification = context.getResources().getText(
80
         niceClassification = context.getResources().getText(
80
                 context.getResources().getIdentifier(name, "string",
81
                 context.getResources().getIdentifier(name, "string",

+ 1
- 1
code/SensorLogger/AndroidManifest.xml 查看文件

1
 <?xml version="1.0" encoding="UTF-8"?>
1
 <?xml version="1.0" encoding="UTF-8"?>
2
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
-     package="uk.co.md87.android.sensorlogger" android:versionCode="16" android:versionName="0.2.3">
3
+     package="uk.co.md87.android.sensorlogger" android:versionCode="17" android:versionName="0.2.4">
4
     <application android:label="Sensor Logger" android:icon="@drawable/icon">
4
     <application android:label="Sensor Logger" android:icon="@drawable/icon">
5
         <activity android:name=".activities.IntroActivity" android:label="Sensor Logger">
5
         <activity android:name=".activities.IntroActivity" android:label="Sensor Logger">
6
             <intent-filter>
6
             <intent-filter>

+ 3
- 0
code/SensorLogger/build.xml 查看文件

18
 
18
 
19
     <target depends="init,compile,-pre-jar,-dex,-package-res-and-assets,-package-res-no-assets,-package-dex,-build-without-signing,-post-jar" description="Build unsigned JAR." name="unsigned-jar"/>
19
     <target depends="init,compile,-pre-jar,-dex,-package-res-and-assets,-package-res-no-assets,-package-dex,-build-without-signing,-post-jar" description="Build unsigned JAR." name="unsigned-jar"/>
20
 
20
 
21
+    <target name="-pre-jar">
22
+       <unzip src="lib/FlurryAgent.jar" dest="${build.classes.dir}" overwrite="true"/>
23
+    </target>
21
 
24
 
22
 </project>
25
 </project>

二进制
code/SensorLogger/dist/SensorLogger.apk 查看文件


二进制
code/SensorLogger/lib/FlurryAgent.jar 查看文件


+ 3
- 1
code/SensorLogger/nbproject/project.properties 查看文件

17
 dist.dir=dist
17
 dist.dir=dist
18
 dist.javadoc.dir=${dist.dir}/javadoc
18
 dist.javadoc.dir=${dist.dir}/javadoc
19
 excludes=
19
 excludes=
20
+file.reference.FlurryAgent.jar=lib/FlurryAgent.jar
20
 gen.source.dir=${src.dir}
21
 gen.source.dir=${src.dir}
21
 includes=**
22
 includes=**
22
 intermediate.dex=${build.dir}/classes.dex
23
 intermediate.dex=${build.dir}/classes.dex
23
-javac.classpath=
24
+javac.classpath=\
25
+    ${file.reference.FlurryAgent.jar}
24
 # Space-separated list of extra javac options
26
 # Space-separated list of extra javac options
25
 javac.compilerargs=
27
 javac.compilerargs=
26
 javac.deprecation=false
28
 javac.deprecation=false

+ 18
- 0
code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/CountdownActivity.java 查看文件

11
 import android.os.RemoteException;
11
 import android.os.RemoteException;
12
 import android.util.Log;
12
 import android.util.Log;
13
 import android.widget.TextView;
13
 import android.widget.TextView;
14
+import com.flurry.android.FlurryAgent;
14
 import java.util.TimerTask;
15
 import java.util.TimerTask;
15
 
16
 
16
 import uk.co.md87.android.sensorlogger.R;
17
 import uk.co.md87.android.sensorlogger.R;
57
             if (time > 0) {
58
             if (time > 0) {
58
                 handler.postDelayed(task, 500);
59
                 handler.postDelayed(task, 500);
59
             } else {
60
             } else {
61
+                FlurryAgent.onEvent("countdown_to_recording");
60
                 startActivity(new Intent(this, RecordingActivity.class));
62
                 startActivity(new Intent(this, RecordingActivity.class));
61
                 finish();
63
                 finish();
62
             }
64
             }
65
         }
67
         }
66
     }
68
     }
67
 
69
 
70
+    /** {@inheritDoc} */
71
+    @Override
72
+    protected void onStart() {
73
+        super.onStart();
74
+
75
+        FlurryAgent.onStartSession(this, "TFBJJPQUQX3S1Q6IUHA6");
76
+    }
77
+
78
+    /** {@inheritDoc} */
79
+    @Override
80
+    protected void onStop() {
81
+        super.onStop();
82
+
83
+        FlurryAgent.onEndSession(this);
84
+    }
85
+
68
 }
86
 }

+ 19
- 0
code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/IntroActivity.java 查看文件

14
 import android.view.View;
14
 import android.view.View;
15
 import android.view.View.OnClickListener;
15
 import android.view.View.OnClickListener;
16
 import android.widget.Button;
16
 import android.widget.Button;
17
+import com.flurry.android.FlurryAgent;
17
 import uk.co.md87.android.common.ExceptionHandler;
18
 import uk.co.md87.android.common.ExceptionHandler;
18
 
19
 
19
 import uk.co.md87.android.sensorlogger.R;
20
 import uk.co.md87.android.sensorlogger.R;
54
     @Override
55
     @Override
55
     public void onClick(final View arg0) {
56
     public void onClick(final View arg0) {
56
         try {
57
         try {
58
+            FlurryAgent.onEvent("intro_to_countdown");
59
+
57
             service.setState(2);
60
             service.setState(2);
58
             startActivity(new Intent(this, CountdownActivity.class));
61
             startActivity(new Intent(this, CountdownActivity.class));
59
             finish();
62
             finish();
62
         }
65
         }
63
     }
66
     }
64
 
67
 
68
+    /** {@inheritDoc} */
69
+    @Override
70
+    protected void onStart() {
71
+        super.onStart();
72
+        
73
+        FlurryAgent.onStartSession(this, "TFBJJPQUQX3S1Q6IUHA6");
74
+    }
75
+
76
+    /** {@inheritDoc} */
77
+    @Override
78
+    protected void onStop() {
79
+        super.onStop();
80
+
81
+        FlurryAgent.onEndSession(this);
82
+    }
83
+
65
 }
84
 }

+ 18
- 0
code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/RecordingActivity.java 查看文件

11
 import android.os.RemoteException;
11
 import android.os.RemoteException;
12
 import android.util.Log;
12
 import android.util.Log;
13
 import android.widget.TextView;
13
 import android.widget.TextView;
14
+import com.flurry.android.FlurryAgent;
14
 import java.util.TimerTask;
15
 import java.util.TimerTask;
15
 
16
 
16
 import uk.co.md87.android.sensorlogger.R;
17
 import uk.co.md87.android.sensorlogger.R;
76
             }
77
             }
77
 
78
 
78
             if (serviceState > 4) {
79
             if (serviceState > 4) {
80
+                FlurryAgent.onEvent("countdown_to_results");
79
                 startActivity(new Intent(this, ResultsActivity.class));
81
                 startActivity(new Intent(this, ResultsActivity.class));
80
                 finish();
82
                 finish();
81
             } else {
83
             } else {
86
         }
88
         }
87
     }
89
     }
88
 
90
 
91
+    /** {@inheritDoc} */
92
+    @Override
93
+    protected void onStart() {
94
+        super.onStart();
95
+
96
+        FlurryAgent.onStartSession(this, "TFBJJPQUQX3S1Q6IUHA6");
97
+    }
98
+
99
+    /** {@inheritDoc} */
100
+    @Override
101
+    protected void onStop() {
102
+        super.onStop();
103
+
104
+        FlurryAgent.onEndSession(this);
105
+    }
106
+
89
 }
107
 }

+ 25
- 0
code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/ResultsActivity.java 查看文件

19
 import android.widget.AutoCompleteTextView;
19
 import android.widget.AutoCompleteTextView;
20
 import android.widget.Button;
20
 import android.widget.Button;
21
 import android.widget.TextView;
21
 import android.widget.TextView;
22
+import com.flurry.android.FlurryAgent;
22
 import java.util.TimerTask;
23
 import java.util.TimerTask;
23
 
24
 
24
 import uk.co.md87.android.sensorlogger.R;
25
 import uk.co.md87.android.sensorlogger.R;
43
     private final OnClickListener yesListener = new OnClickListener() {
44
     private final OnClickListener yesListener = new OnClickListener() {
44
 
45
 
45
         public void onClick(View arg0) {
46
         public void onClick(View arg0) {
47
+            FlurryAgent.onEvent("results_yes_click");
48
+
46
             findViewById(R.id.resultsno).setEnabled(false);
49
             findViewById(R.id.resultsno).setEnabled(false);
47
             findViewById(R.id.resultsyes).setEnabled(false);
50
             findViewById(R.id.resultsyes).setEnabled(false);
48
 
51
 
60
             = new DialogInterface.OnClickListener() {
63
             = new DialogInterface.OnClickListener() {
61
 
64
 
62
         public void onClick(DialogInterface arg0, int arg1) {
65
         public void onClick(DialogInterface arg0, int arg1) {
66
+            FlurryAgent.onEvent("results_correction_submitted");
67
+
63
             dialog = ProgressDialog.show(ResultsActivity.this, "Please wait",
68
             dialog = ProgressDialog.show(ResultsActivity.this, "Please wait",
64
                     "Submitting...", true);
69
                     "Submitting...", true);
65
             
70
             
75
     private final OnClickListener noListener = new OnClickListener() {
80
     private final OnClickListener noListener = new OnClickListener() {
76
 
81
 
77
         public void onClick(View arg0) {
82
         public void onClick(View arg0) {
83
+            FlurryAgent.onEvent("results_no_click");
84
+
78
             findViewById(R.id.resultsno).setEnabled(false);
85
             findViewById(R.id.resultsno).setEnabled(false);
79
             findViewById(R.id.resultsyes).setEnabled(false);
86
             findViewById(R.id.resultsyes).setEnabled(false);
80
 
87
 
132
     void checkStage() {
139
     void checkStage() {
133
         try {
140
         try {
134
             if (service.getState() == 7) {
141
             if (service.getState() == 7) {
142
+                FlurryAgent.onEvent("results_to_thanks");
143
+
135
                 service.setState(8);
144
                 service.setState(8);
136
                 startActivity(new Intent(this, ThanksActivity.class));
145
                 startActivity(new Intent(this, ThanksActivity.class));
137
                 finish();
146
                 finish();
143
         }
152
         }
144
     }
153
     }
145
 
154
 
155
+    /** {@inheritDoc} */
156
+    @Override
157
+    protected void onStart() {
158
+        super.onStart();
159
+
160
+        FlurryAgent.onStartSession(this, "TFBJJPQUQX3S1Q6IUHA6");
161
+    }
162
+
163
+    /** {@inheritDoc} */
164
+    @Override
165
+    protected void onStop() {
166
+        super.onStop();
167
+
168
+        FlurryAgent.onEndSession(this);
169
+    }
170
+
146
 }
171
 }

+ 17
- 0
code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/ThanksActivity.java 查看文件

9
 import android.os.Bundle;
9
 import android.os.Bundle;
10
 import android.telephony.TelephonyManager;
10
 import android.telephony.TelephonyManager;
11
 import android.widget.TextView;
11
 import android.widget.TextView;
12
+import com.flurry.android.FlurryAgent;
12
 
13
 
13
 import uk.co.md87.android.sensorlogger.R;
14
 import uk.co.md87.android.sensorlogger.R;
14
 
15
 
51
         return builder.toString();
52
         return builder.toString();
52
     }
53
     }
53
 
54
 
55
+    /** {@inheritDoc} */
56
+    @Override
57
+    protected void onStart() {
58
+        super.onStart();
59
+
60
+        FlurryAgent.onStartSession(this, "TFBJJPQUQX3S1Q6IUHA6");
61
+    }
62
+
63
+    /** {@inheritDoc} */
64
+    @Override
65
+    protected void onStop() {
66
+        super.onStop();
67
+
68
+        FlurryAgent.onEndSession(this);
69
+    }
70
+
54
 }
71
 }

+ 11
- 0
website/index.html 查看文件

74
        </p>
74
        </p>
75
        <h4>Changelog</h4>
75
        <h4>Changelog</h4>
76
        <ul>
76
        <ul>
77
+        <li><strong>0.2.3 &rarr; 0.2.4</strong>: Added analytics</li>
77
         <li><strong>0.2.2 &rarr; 0.2.3</strong>: Fix another force close, updated model for classification</li>
78
         <li><strong>0.2.2 &rarr; 0.2.3</strong>: Fix another force close, updated model for classification</li>
78
         <li><strong>0.2.1 &rarr; 0.2.2</strong>: Fix force close, add reporting of exceptions</li>
79
         <li><strong>0.2.1 &rarr; 0.2.2</strong>: Fix force close, add reporting of exceptions</li>
79
         <li><strong>0.2.0 &rarr; 0.2.1</strong>: Bug fix related to turning display off</li>
80
         <li><strong>0.2.0 &rarr; 0.2.1</strong>: Bug fix related to turning display off</li>
112
         integrated, and the service will eventually provide an API for other
113
         integrated, and the service will eventually provide an API for other
113
         applications to listen out for changes in the user's activity.
114
         applications to listen out for changes in the user's activity.
114
        </p>
115
        </p>
116
+       <p>
117
+        The classification algorithm now uses scores assigned to each possible
118
+        classification instead of merely using the results from the last
119
+        set of sensor input. This means that the classifications may be
120
+        slightly delayed (it will take a minute or so to react to changes in
121
+        activity), but it makes the algorithm much more tolerant of occasional
122
+        erroneous readings.
123
+       </p>
115
        <h4>Changelog</h4>
124
        <h4>Changelog</h4>
116
        <ul>
125
        <ul>
126
+        <li><strong>0.2.0 &rarr; 0.2.1</strong>: Added analytics</li>
127
+        <li><strong>0.1.3 &rarr; 0.2.0</strong>: Changed classification algorithm to favour existing classifications, change recording to one sample every 30 seconds instead of 2 overlapping samples every 60 seconds, disable logging, durations measured in seconds now show as "&lt;1 min"</li>
117
         <li><strong>0.1.2 &rarr; 0.1.3</strong>: More efficient updating of activity list, give feedback when starting service</li>
128
         <li><strong>0.1.2 &rarr; 0.1.3</strong>: More efficient updating of activity list, give feedback when starting service</li>
118
         <li><strong>0.1.1 &rarr; 0.1.2</strong>: Fix various issues when starting service</li>
129
         <li><strong>0.1.1 &rarr; 0.1.2</strong>: Fix various issues when starting service</li>
119
         <li><strong>0.1.0 &rarr; 0.1.1</strong>: Fix exception when stopping service in some conditions</li>
130
         <li><strong>0.1.0 &rarr; 0.1.1</strong>: Fix exception when stopping service in some conditions</li>

正在加载...
取消
保存