package kr.ac.kaist.resl.sensorservice; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONException; import org.json.JSONObject; import android.app.Service; import android.content.Intent; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.AsyncTask; import android.os.Environment; import android.os.IBinder; import android.provider.Settings; public class SensorService extends Service implements SensorEventListener { private SensorManager sensorManager =null; public static String message=""; private Map<String, Object> sensorValues; private FileThread fileThread; private RemoteThread remoteThread; String androidId; public SensorService() { } @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { androidId = android.provider.Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID); } @Override public void onStart(Intent intent, int startId) { if( sensorManager == null ) sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL); for( int i = 0 ; i < sensors.size() ; i++ ) { sensorManager.registerListener(this, sensors.get(i), SensorManager.SENSOR_DELAY_NORMAL); } sensorValues = new HashMap<String, Object>(); sensorValues.put("android_id", androidId); } @Override public void onDestroy() { if( sensorManager != null ) sensorManager.unregisterListener(this); fileThread.cont = false; remoteThread.cont = false; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @SuppressWarnings("deprecation") @Override public void onSensorChanged(SensorEvent event) { float[] values = event.values; if( event.sensor.getType() == Sensor.TYPE_ACCELEROMETER ) { //Sensor : 1 /* * All values are in SI units (m/s^2) values[0]: Acceleration minus Gx on the x-axis values[1]: Acceleration minus Gy on the y-axis values[2]: Acceleration minus Gz on the z-axis */ //sensorValues.put("accelerometer.x", values[0]); //sensorValues.put("accelerometer.y", values[1]); //sensorValues.put("accelerometer.z", values[2]); }else if( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD ) { //Sensor : 2 /* * All values are in micro-Tesla (uT) and measure the ambient magnetic field in the X, Y and Z axis. */ //sensorValues.put("magnetic_field.x", values[0]); //sensorValues.put("magnetic_field.y", values[1]); //sensorValues.put("magnetic_field.z", values[2]); }else if( event.sensor.getType() == Sensor.TYPE_ORIENTATION ) { //Sensor : 3 //Deprecated float fDigit = (float)values[0]%10; float valueFloat = (float)values[0] - fDigit; if( valueFloat < 0 ) sensorValues.put("orientation", 0); else sensorValues.put("orientation", valueFloat); }else if( event.sensor.getType() == Sensor.TYPE_GYROSCOPE) { //Sensor : 4 /* values[0]: Angular speed around the x-axis values[1]: Angular speed around the y-axis values[2]: Angular speed around the z-axis */ //sensorValues.put("gyroscope.x", values[0]); //sensorValues.put("gyroscope.y", values[1]); //sensorValues.put("gyroscope.z", values[2]); }else if( event.sensor.getType() == Sensor.TYPE_LIGHT) { //Sensor : 5 float fDigit = (float)values[0]%10; float valueFloat = (float)values[0] - fDigit; if( valueFloat < 0 ) sensorValues.put("light", 0); else sensorValues.put("light", valueFloat); }else if( event.sensor.getType() == Sensor.TYPE_PRESSURE) { //Sensor : 6 //Atmospheric pressure in hPa (millibar) sensorValues.put("pressure", values[0]); }else if( event.sensor.getType() == Sensor.TYPE_TEMPERATURE) { //Sensor : 7 //Ambient light level in SI lux units sensorValues.put("temperature", values[0]); } else if( event.sensor.getType() == Sensor.TYPE_PROXIMITY) { //Sensor : 8 // values[0]: Proximity sensor distance measured in centimeters // G2 may support binary / near / far sensorValues.put("proximity", values[0]); }else if( event.sensor.getType() == Sensor.TYPE_GRAVITY) { //Sensor : 9 //A three dimensional vector indicating the direction and magnitude of gravity. Units are m/s^2. The coordinate system is the same as is used by the acceleration sensor. //Note: When the device is at rest, the output of the gravity sensor should be identical to that of the accelerometer. //sensorValues.put("gravity.x", values[0]); //sensorValues.put("gravity.y", values[1]); //sensorValues.put("gravity.z", values[2]); }else if( event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) { //Sensor : 10 // acceleration = gravity + linear-acceleration //sensorValues.put("linear_acceleration.x", values[0]); //sensorValues.put("linear_acceleration.y", values[1]); //sensorValues.put("linear_acceleration.z", values[2]); }else if( event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { //Sensor : 11 /* values[0]: x*sin(θ/2) values[1]: y*sin(θ/2) values[2]: z*sin(θ/2) values[3]: cos(θ/2) values[4]: estimated heading Accuracy (in radians) (-1 if unavailable) */ //sensorValues.put("rotation_vector.xsin", values[0]); //sensorValues.put("rotation_vector.ysin", values[1]); //sensorValues.put("rotation_vector.zsin", values[2]); //sensorValues.put("rotation_vector.cos", values[3]); //sensorValues.put("rotation_vector.accuracy", values[4]); }else if( event.sensor.getType() == Sensor.TYPE_RELATIVE_HUMIDITY) { //Sensor : 12 sensorValues.put("relative_humidity", values[0]); }else if( event.sensor.getType() == Sensor.TYPE_AMBIENT_TEMPERATURE) { //Sensor : 13 sensorValues.put("ambient_temperature", values[0]); } else if( event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED) { //Sensor : 14 }else if( event.sensor.getType() == Sensor.TYPE_GAME_ROTATION_VECTOR) { //Sensor : 15 }else if( event.sensor.getType() == Sensor.TYPE_GYROSCOPE_UNCALIBRATED) { //Sensor : 16 }else if( event.sensor.getType() == Sensor.TYPE_SIGNIFICANT_MOTION) { //Sensor : 17 // Not work }else if( event.sensor.getType() == Sensor.TYPE_STEP_DETECTOR) { //Sensor : 18 }else if( event.sensor.getType() == Sensor.TYPE_STEP_COUNTER ) { //Sensor : 19 sensorValues.put("step_counter", values[0]); }else if( event.sensor.getType() == Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR ) { //Sensor : 20 } else if( event.sensor.getType() == 33171000) { //Sensor : Basic Gestures //Cannot Understand }else if( event.sensor.getType() == 33171002) { //Sensor : Facing sensorValues.put("facing", values[0]); }else if( event.sensor.getType() == 33171003) { //Sensor : Tilt }else if( event.sensor.getType() == 33171006) { //Sensor : AMD }else if( event.sensor.getType() == 33171007) { //Sensor : RMD }else if( event.sensor.getType() == 33171008) { //Sensor : VMD }else if( event.sensor.getType() == 33171009) { //Sensor : Pedometer }else if( event.sensor.getType() == 33171010) { //Sensor : Pedestrian-activitiy-monitor }else if( event.sensor.getType() == 33171011) { //Sensor : Motion Accelerometer } if( fileThread == null ) { fileThread = new FileThread(); fileThread.start(); } if( remoteThread == null ) { remoteThread = new RemoteThread(); remoteThread.start(); } } public class RemoteThread extends Thread { public boolean cont; public Map<String, Object> prevValues; public RemoteThread() { cont = true; prevValues = new HashMap<String, Object>(); } public void run() { try { while(cont) { SensorService.message = getJSON(sensorValues, prevValues); if( message != null ) { new HttpAsyncTask().execute(message); } cloneMaps(sensorValues, prevValues); Thread.sleep(MainActivity.period*1000); } } catch (InterruptedException e) { e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void cloneMaps(Map<String, Object> source, Map<String, Object> target) { Iterator<String> iter = source.keySet().iterator(); while( iter.hasNext() ) { String key = (String)iter.next(); Object value = source.get(key); target.put(key, value); } } public class FileThread extends Thread { public boolean cont; public FileThread() { cont = true; } public void run() { try { while(cont) { if( isExternalStorageWritable() ) { String strToSave = getJSON(sensorValues); if( strToSave != null ) writeToSDFile("Sensor", strToSave); } Thread.sleep(10000); } } catch (InterruptedException e) { e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public String getJSON(Map<String, Object> sensorValues) throws JSONException { Iterator<String> iter = sensorValues.keySet().iterator(); JSONObject ret = new JSONObject(); while( iter.hasNext() ) { String key = (String)iter.next(); Object value = sensorValues.get(key); ret.put(key, value); } return ret.toString(); } public String getJSON(Map<String, Object> sensorValues, Map<String, Object> prevValues) throws JSONException { Iterator<String> iter = sensorValues.keySet().iterator(); JSONObject ret = new JSONObject(); String android_id = "default"; while( iter.hasNext() ) { String key = (String)iter.next(); Object value = sensorValues.get(key); if( value instanceof Float ) { if( prevValues.containsKey(key) ) { Float prevValue = (Float)prevValues.get(key); if( !((Float)value).toString().equals(prevValue.toString()) ) { ret.put(key, (Float)value); } } } else if( value instanceof String ) { android_id = (String)value; } } if( ret.length() != 0 ) { ret.put("android_id", android_id); return ret.toString(); } return null; } private class HttpAsyncTask extends AsyncTask<String, Integer, Double>{ @Override protected Double doInBackground(String... params) { try { postData(params[0]); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } } public void postData(String message) throws ClientProtocolException, IOException { HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost(MainActivity.URL); StringEntity params = new StringEntity(message); post.setEntity(params); client.execute(post); } public boolean isExternalStorageWritable(){ String state = Environment.getExternalStorageState(); if( Environment.MEDIA_MOUNTED.equals( state)){ return true; } return false; } private void writeToSDFile(String fileName, String message){ // Find the root of the external storage. // See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal File root = android.os.Environment.getExternalStorageDirectory(); // See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder File dir = new File (root.getAbsolutePath() + "/SensorService"); dir.mkdirs(); File file = new File(dir, fileName+".json"); try { FileOutputStream f = new FileOutputStream(file); PrintWriter pw = new PrintWriter(f); pw.print(message); pw.flush(); pw.close(); f.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }