Browse Source

Functioning activity recorder

Refactored ExceptionHandler to be general purpose
tags/ActivityRecorder/0.1.0
Chris Smith 14 years ago
parent
commit
bc4592824b

+ 1
- 0
code/ActivityRecorder/AndroidManifest.xml View File

@@ -13,6 +13,7 @@
13 13
         <service android:name=".ClassifierService" android:label="Activity Classification Service"/>
14 14
     </application>
15 15
 
16
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
16 17
     <uses-permission android:name="android.permission.INTERNET"/>
17 18
     <uses-sdk android:minSdkVersion="3" />
18 19
 </manifest>

BIN
code/ActivityRecorder/dist/ActivityRecorder.apk View File


+ 7
- 0
code/ActivityRecorder/res/layout/item.xml View File

@@ -0,0 +1,7 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
3
+    android:layout_width="fill_parent"
4
+    android:layout_height="fill_parent"
5
+    android:padding="10dp"
6
+    android:textSize="16sp" >
7
+</TextView>

+ 4
- 3
code/ActivityRecorder/res/layout/main.xml View File

@@ -11,10 +11,11 @@
11 11
         android:layout_marginTop="5dip"
12 12
         android:layout_marginBottom="5dip"
13 13
         />
14
-    <TextView
14
+     <ListView
15
+        android:id="@+id/list"
15 16
         android:layout_width="fill_parent"
16 17
         android:layout_height="fill_parent"
17 18
         android:layout_weight="1"
18
-        android:layout_gravity="fill"
19
-        android:text="Hello Android from NetBeans"/>
19
+        android:drawSelectorOnTop="false"
20
+        />
20 21
 </LinearLayout>

+ 96
- 1
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/ActivityRecorderActivity.java View File

@@ -7,11 +7,24 @@ package uk.co.md87.android.activityrecorder;
7 7
 
8 8
 import android.app.Activity;
9 9
 import android.content.ComponentName;
10
+import android.content.Intent;
10 11
 import android.content.ServiceConnection;
12
+import android.content.pm.PackageManager.NameNotFoundException;
11 13
 import android.os.Bundle;
14
+import android.os.Handler;
12 15
 import android.os.IBinder;
16
+import android.os.RemoteException;
17
+import android.telephony.TelephonyManager;
18
+import android.util.Log;
19
+import android.view.View;
20
+import android.view.View.OnClickListener;
21
+import android.widget.ArrayAdapter;
22
+import android.widget.Button;
23
+import android.widget.ListView;
13 24
 import android.widget.Toast;
25
+import java.util.Map;
14 26
 import uk.co.md87.android.activityrecorder.rpc.ActivityRecorderBinder;
27
+import uk.co.md87.android.common.ExceptionHandler;
15 28
 
16 29
 /**
17 30
  *
@@ -21,10 +34,14 @@ public class ActivityRecorderActivity extends Activity {
21 34
 
22 35
     ActivityRecorderBinder service = null;
23 36
 
24
-    private ServiceConnection connection = new ServiceConnection() {
37
+    final Handler handler = new Handler();
38
+
39
+    private final ServiceConnection connection = new ServiceConnection() {
25 40
 
26 41
         public void onServiceConnected(ComponentName arg0, IBinder arg1) {
27 42
             service = ActivityRecorderBinder.Stub.asInterface(arg1);
43
+
44
+            handler.postDelayed(updateRunnable, 500);
28 45
         }
29 46
 
30 47
         public void onServiceDisconnected(ComponentName arg0) {
@@ -33,12 +50,90 @@ public class ActivityRecorderActivity extends Activity {
33 50
         }
34 51
     };
35 52
 
53
+    private final Runnable updateRunnable = new Runnable() {
54
+
55
+        public void run() {
56
+            updateButton();
57
+            
58
+            handler.postDelayed(updateRunnable, 500);
59
+        }
60
+    };
61
+
62
+    private OnClickListener clickListener = new OnClickListener() {
63
+
64
+        public void onClick(View arg0) {
65
+            try {
66
+                if (service.isRunning()) {
67
+                    stopService(new Intent(ActivityRecorderActivity.this,
68
+                            RecorderService.class));
69
+                } else {
70
+                    startService(new Intent(ActivityRecorderActivity.this,
71
+                            RecorderService.class));
72
+                }
73
+
74
+                updateButton();
75
+            } catch (RemoteException ex) {
76
+                Log.e(getClass().getName(), "Unable to get service state", ex);
77
+            }
78
+        }
79
+    };
80
+
36 81
     /** {@inheritDoc} */
37 82
     @Override
38 83
     public void onCreate(Bundle icicle) {
39 84
         super.onCreate(icicle);
40 85
 
86
+        Thread.setDefaultUncaughtExceptionHandler(
87
+                new ExceptionHandler("ActivityRecorder",
88
+                "http://chris.smith.name/android/upload", getVersionName(), getIMEI()));
89
+
90
+        bindService(new Intent(this, RecorderService.class), connection, BIND_AUTO_CREATE);
91
+
41 92
         setContentView(R.layout.main);
93
+        ((Button) findViewById(R.id.togglebutton)).setEnabled(false);
94
+        ((Button) findViewById(R.id.togglebutton)).setOnClickListener(clickListener);
95
+        ((ListView) findViewById(R.id.list)).setAdapter(
96
+                new ArrayAdapter<Map.Entry<Long, String>>(this, R.layout.item));
97
+    }
98
+
99
+    /** {@inheritDoc} */
100
+    @Override
101
+    protected void onDestroy() {
102
+        super.onDestroy();
103
+
104
+        unbindService(connection);
105
+    }
106
+
107
+    @SuppressWarnings("unchecked")
108
+    void updateButton() {
109
+        try {
110
+            ((Button) findViewById(R.id.togglebutton)).setText(service.isRunning()
111
+                    ? R.string.service_enabled : R.string.service_disabled);
112
+            ((Button) findViewById(R.id.togglebutton)).setEnabled(true);
113
+            
114
+            // Hacky
115
+            ((ArrayAdapter<Map.Entry<Long, String>>) ((ListView) findViewById(R.id.list))
116
+                    .getAdapter()).clear();
117
+            for (Map.Entry<Long, String> entry : ((Map<Long, String>) service
118
+                    .getClassifications()).entrySet()) {
119
+                ((ArrayAdapter<Map.Entry<Long, String>>) ((ListView) findViewById(R.id.list))
120
+                    .getAdapter()).add(entry);
121
+            }
122
+        } catch (RemoteException ex) {
123
+            Log.e(getClass().getName(), "Unable to get service state", ex);
124
+        }
125
+    }
126
+
127
+    public String getVersionName() {
128
+        try {
129
+            return getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
130
+        } catch (NameNotFoundException ex) {
131
+            return "Unknown";
132
+        }
133
+    }
134
+
135
+    public String getIMEI() {
136
+        return ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).getDeviceId();
42 137
     }
43 138
 
44 139
 }

+ 15
- 1
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/ClassifierService.java View File

@@ -11,6 +11,7 @@ import android.content.Intent;
11 11
 import android.content.ServiceConnection;
12 12
 import android.os.IBinder;
13 13
 import android.os.RemoteException;
14
+import android.util.Log;
14 15
 import android.widget.Toast;
15 16
 
16 17
 import java.util.Map;
@@ -50,7 +51,18 @@ public class ClassifierService extends Service implements Runnable {
50 51
     public void onStart(Intent intent, int startId) {
51 52
         super.onStart(intent, startId);
52 53
 
54
+        Log.i(getClass().getName(), "Starting classifier");
55
+
53 56
         data = intent.getFloatArrayExtra("data");
57
+
58
+        new Thread(this).start();
59
+    }
60
+
61
+    @Override
62
+    public void onDestroy() {
63
+        super.onDestroy();
64
+
65
+        unbindService(connection);
54 66
     }
55 67
 
56 68
     @Override
@@ -99,7 +111,9 @@ public class ClassifierService extends Service implements Runnable {
99 111
 
100 112
         classification = bestActivity;
101 113
 
102
-        bindService(new Intent(this, ActivityRecorderActivity.class), connection, BIND_AUTO_CREATE);
114
+        Log.i(getClass().getName(), "Classification: " + classification);
115
+
116
+        bindService(new Intent(this, RecorderService.class), connection, BIND_AUTO_CREATE);
103 117
     }
104 118
 
105 119
 }

+ 3
- 1
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/R.java View File

@@ -14,10 +14,12 @@ public final class R {
14 14
         public static final int icon=0x7f020000;
15 15
     }
16 16
     public static final class id {
17
+        public static final int list=0x7f060001;
17 18
         public static final int togglebutton=0x7f060000;
18 19
     }
19 20
     public static final class layout {
20
-        public static final int main=0x7f030000;
21
+        public static final int item=0x7f030000;
22
+        public static final int main=0x7f030001;
21 23
     }
22 24
     public static final class raw {
23 25
         public static final int basic_model=0x7f040000;

+ 4
- 0
code/ActivityRecorder/src/uk/co/md87/android/activityrecorder/RecorderService.java View File

@@ -34,6 +34,7 @@ public class RecorderService extends Service {
34 34
     private final ActivityRecorderBinder.Stub binder = new ActivityRecorderBinder.Stub() {
35 35
 
36 36
         public void submitClassification(String classification) throws RemoteException {
37
+            Log.i(getClass().getName(), "Adding classification: " + classification);
37 38
             classifications.put(System.currentTimeMillis(), classification);
38 39
         }
39 40
 
@@ -100,6 +101,7 @@ public class RecorderService extends Service {
100 101
     }
101 102
 
102 103
     public void sample() {
104
+        Log.i(getClass().getName(), "Sampling");
103 105
         data[(nextSample * 2) % 256] = values[0];
104 106
         data[(nextSample * 2 + 1) % 256] = values[1];
105 107
         
@@ -118,6 +120,7 @@ public class RecorderService extends Service {
118 120
     }
119 121
 
120 122
     public void analyse(float[] data) {
123
+        Log.i(getClass().getName(), "Analysing");
121 124
         final Intent intent = new Intent(this, ClassifierService.class);
122 125
         intent.putExtra("data", data);
123 126
         startService(intent);
@@ -160,6 +163,7 @@ public class RecorderService extends Service {
160 163
     }
161 164
 
162 165
     void register() {
166
+        Log.i(getClass().getName(), "Registering");
163 167
         nextSample = 0;
164 168
         manager.registerListener(accelListener,
165 169
                 manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),

+ 77
- 0
code/ActivityRecorder/src/uk/co/md87/android/common/ExceptionHandler.java View File

@@ -0,0 +1,77 @@
1
+/*
2
+ * To change this template, choose Tools | Templates
3
+ * and open the template in the editor.
4
+ */
5
+
6
+package uk.co.md87.android.common;
7
+
8
+import java.io.IOException;
9
+import java.io.PrintWriter;
10
+import java.io.StringWriter;
11
+import java.io.Writer;
12
+import java.lang.Thread.UncaughtExceptionHandler;
13
+import java.util.ArrayList;
14
+import java.util.List;
15
+import org.apache.http.NameValuePair;
16
+import org.apache.http.client.entity.UrlEncodedFormEntity;
17
+import org.apache.http.client.methods.HttpPost;
18
+import org.apache.http.impl.client.DefaultHttpClient;
19
+import org.apache.http.message.BasicNameValuePair;
20
+import org.apache.http.protocol.HTTP;
21
+
22
+/**
23
+ *
24
+ * @author chris
25
+ */
26
+public class ExceptionHandler implements UncaughtExceptionHandler {
27
+
28
+    private UncaughtExceptionHandler defaultUEH;
29
+
30
+    private String appname, url, version, imei;
31
+
32
+    /*
33
+     * if any of the parameters is null, the respective functionality
34
+     * will not be used
35
+     */
36
+    public ExceptionHandler(String appname, String url, String version, String imei) {
37
+        this.appname = appname;
38
+        this.url = url;
39
+        this.version = version;
40
+        this.imei = imei;
41
+        this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
42
+    }
43
+
44
+    public void uncaughtException(Thread t, Throwable e) {
45
+        String timestamp = String.valueOf(System.currentTimeMillis());
46
+        final Writer result = new StringWriter();
47
+        final PrintWriter printWriter = new PrintWriter(result);
48
+        e.printStackTrace(printWriter);
49
+        String stacktrace = result.toString();
50
+        printWriter.close();
51
+        String filename = timestamp + ".stacktrace";
52
+
53
+        sendToServer(stacktrace, filename);
54
+
55
+        defaultUEH.uncaughtException(t, e);
56
+    }
57
+
58
+    private void sendToServer(String stacktrace, String filename) {
59
+        DefaultHttpClient httpClient = new DefaultHttpClient();
60
+        HttpPost httpPost = new HttpPost(url);
61
+
62
+        httpPost.setHeader("x-application", appname + "-exception");
63
+        httpPost.setHeader("x-version", version);
64
+        httpPost.setHeader("x-imei", imei);
65
+
66
+        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
67
+        nvps.add(new BasicNameValuePair("filename", filename));
68
+        nvps.add(new BasicNameValuePair("stacktrace", stacktrace));
69
+        try {
70
+            httpPost.setEntity(
71
+                    new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
72
+            httpClient.execute(httpPost);
73
+        } catch (IOException e) {
74
+            e.printStackTrace();
75
+        }
76
+    }
77
+}

+ 0
- 1
code/SensorLogger/AndroidManifest.xml View File

@@ -23,7 +23,6 @@
23 23
             android:label="Sensor Logger &gt; Thanks"/>
24 24
 
25 25
         <service android:name=".SensorLoggerService" android:label="Sensor Logger Service"/>
26
-
27 26
         <service android:name=".RecorderService" android:label="Sensor Logger Service"/>
28 27
         <service android:name=".ClassifierService" android:label="Sensor Classifier Service"/>
29 28
         <service android:name=".UploaderService" android:label="Sensor Uploader Service"/>

code/SensorLogger/src/uk/co/md87/android/sensorlogger/ExceptionHandler.java → code/SensorLogger/src/uk/co/md87/android/common/ExceptionHandler.java View File

@@ -3,7 +3,7 @@
3 3
  * and open the template in the editor.
4 4
  */
5 5
 
6
-package uk.co.md87.android.sensorlogger;
6
+package uk.co.md87.android.common;
7 7
 
8 8
 import java.io.IOException;
9 9
 import java.io.PrintWriter;
@@ -27,13 +27,14 @@ public class ExceptionHandler implements UncaughtExceptionHandler {
27 27
 
28 28
     private UncaughtExceptionHandler defaultUEH;
29 29
 
30
-    private String url, version, imei;
30
+    private String appname, url, version, imei;
31 31
 
32 32
     /*
33 33
      * if any of the parameters is null, the respective functionality
34 34
      * will not be used
35 35
      */
36
-    public ExceptionHandler(String url, String version, String imei) {
36
+    public ExceptionHandler(String appname, String url, String version, String imei) {
37
+        this.appname = appname;
37 38
         this.url = url;
38 39
         this.version = version;
39 40
         this.imei = imei;
@@ -58,7 +59,7 @@ public class ExceptionHandler implements UncaughtExceptionHandler {
58 59
         DefaultHttpClient httpClient = new DefaultHttpClient();
59 60
         HttpPost httpPost = new HttpPost(url);
60 61
 
61
-        httpPost.setHeader("x-application", "SensorLogger-exception");
62
+        httpPost.setHeader("x-application", appname + "-exception");
62 63
         httpPost.setHeader("x-version", version);
63 64
         httpPost.setHeader("x-imei", imei);
64 65
 

+ 3
- 3
code/SensorLogger/src/uk/co/md87/android/sensorlogger/activities/IntroActivity.java View File

@@ -14,7 +14,7 @@ import android.util.Log;
14 14
 import android.view.View;
15 15
 import android.view.View.OnClickListener;
16 16
 import android.widget.Button;
17
-import uk.co.md87.android.sensorlogger.ExceptionHandler;
17
+import uk.co.md87.android.common.ExceptionHandler;
18 18
 
19 19
 import uk.co.md87.android.sensorlogger.R;
20 20
 
@@ -30,8 +30,8 @@ public class IntroActivity extends BoundActivity implements OnClickListener {
30 30
         super.onCreate(icicle);
31 31
 
32 32
         Thread.setDefaultUncaughtExceptionHandler(
33
-                new ExceptionHandler("http://chris.smith.name/android/upload",
34
-                getVersionName(), getIMEI()));
33
+                new ExceptionHandler("SensorLogger",
34
+                "http://chris.smith.name/android/upload", getVersionName(), getIMEI()));
35 35
 
36 36
         setContentView(R.layout.intro);
37 37
 

Loading…
Cancel
Save