Created
July 21, 2015 18:40
-
-
Save julian-ramos/6ee7ad8a74ee4b442530 to your computer and use it in GitHub Desktop.
Code to have a foreground service recording accelerometer data at a sampling rate that is at least the one specified when the sensor is registered. This service restarts itself and also survives power saving modes. This was only tested on an android watch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class SensorService extends Service implements SensorEventListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { | |
| // final Handler handler = new Handler(); | |
| private PowerManager pm; | |
| private PowerManager.WakeLock wl; | |
| GoogleApiClient googleClient; | |
| String tail="."; | |
| String recordingStrategy=""; | |
| int countDM=0; | |
| boolean thread=false; | |
| public static String TAG = "sparks SensorService"; | |
| int count=0; | |
| long t0,t1; | |
| Data data; | |
| int samplingRate=0; | |
| private final static int SENS_ACCELEROMETER = Sensor.TYPE_ACCELEROMETER; | |
| private static final String SPARK_MESSAGE = "/sparks"; | |
| private int FREQUENCY_UPDATED=1; | |
| SensorManager mSensorManager; | |
| public static final String STORAGE_FOLDER = Environment.getExternalStorageDirectory()+"/sparks"; | |
| public static final String BROADCAST_ACTION = "sparkBroadcast"; | |
| String FILENAME = "/motionData"; | |
| public static final String EXTENSION=".csv"; | |
| private PrintWriter file; | |
| SimpleDateFormat sdf; | |
| File f; | |
| int notificationId = 001; | |
| Intent intent,intentSpark; | |
| int counter = 0; | |
| /* | |
| * This functions returns the index number of the next file. | |
| * For instance if the name of the files is data and | |
| * it finds that data2 exists then it will return 2. If there is no | |
| * data files it will return zero | |
| * */ | |
| void checkPath(String path){ | |
| File dir; | |
| dir = new File(path); | |
| if (!dir.exists()) dir.mkdirs(); | |
| } | |
| //TODO | |
| //Move this function to the utils | |
| String fileExists(String filename){ | |
| int i=0; | |
| f = new File(filename+"-"+Integer.toString(i)+EXTENSION); | |
| while( i < 30) | |
| { | |
| if(!f.exists()) | |
| { | |
| Log.d(TAG,"File does not exist ->"+filename); | |
| break; | |
| } | |
| i++; | |
| f = new File(filename+"-"+Integer.toString(i)+EXTENSION); | |
| } | |
| return filename+"-"+Integer.toString(i)+EXTENSION; | |
| } | |
| @Override | |
| public void onCreate() { | |
| super.onCreate(); | |
| sdf = new SimpleDateFormat("yyyy-MM-dd"); | |
| intent = new Intent(BROADCAST_ACTION); | |
| // intentSpark = new Intent(SPARK_MESSAGE); | |
| // intentSpark.putExtra("start", "started"); | |
| // sendBroadcast(intentSpark); | |
| // registering to receive messages from other services | |
| registerReceiver(broadcastReceiver, new IntentFilter(msgServiceListener.BROADCAST_ACTION)); | |
| // Build a new GoogleApiClient for the the Wearable API | |
| googleClient = new GoogleApiClient.Builder(getApplicationContext()) | |
| .addApi(Wearable.API) | |
| .addConnectionCallbacks(this) | |
| .addOnConnectionFailedListener(this) | |
| .build(); | |
| googleClient.connect(); | |
| Log.d(TAG,"service starting"); | |
| sendMessage(SPARK_MESSAGE,"started"); | |
| Notification not=null; | |
| Intent viewIntent = new Intent(this, MainActivity.class); | |
| PendingIntent viewPendingIntent = | |
| PendingIntent.getActivity(getApplicationContext(), 0, viewIntent, 0); | |
| NotificationCompat.Builder notificationBuilder = | |
| new NotificationCompat.Builder(getApplicationContext()) | |
| .setContentTitle("Title") | |
| .setContentText("hola") | |
| .setContentIntent(viewPendingIntent); | |
| NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); | |
| not=notificationBuilder.build(); | |
| notificationManager.notify(notificationId,not ); | |
| startForeground(notificationId, not); | |
| } | |
| @Override | |
| public void onDestroy() { | |
| // stopForeground(true); | |
| stopMeasurement(); | |
| file.flush(); | |
| file.close(); | |
| super.onDestroy(); | |
| unregisterReceiver(broadcastReceiver); | |
| sendMessage(SPARK_MESSAGE,"stopped"); | |
| // if (wl.isHeld()){ | |
| // wl.release(); | |
| // } | |
| // intentSpark.putExtra("stop", "stopped"); | |
| // sendBroadcast(intentSpark); | |
| // handler.removeCallbacksAndMessages(sendUpdatesToUI); | |
| } | |
| @Override | |
| public IBinder onBind(Intent intent) { | |
| return null; | |
| } | |
| protected void startMeasurement() { | |
| // mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE)); | |
| // while(FILENAME.equalsIgnoreCase("/motionData")){ | |
| // SystemClock.sleep(200); | |
| // Log.d(TAG,"waiting to get filename"+FILENAME); | |
| // } | |
| mSensorManager = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE); | |
| Sensor accelerometerSensor = mSensorManager.getDefaultSensor(SENS_ACCELEROMETER); | |
| // Register the listener | |
| if (mSensorManager != null) { | |
| if (accelerometerSensor != null) { | |
| mSensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_GAME); | |
| Log.d(TAG,"Listener registered"); | |
| } else { | |
| Log.w(TAG, "No Accelerometer found"); | |
| } | |
| } | |
| } | |
| private void stopMeasurement() { | |
| try { | |
| // String[] paths = new String[1]; | |
| // paths[0] = f.getAbsolutePath(); | |
| Intent mediaScannerIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); | |
| Uri fileContentUri = Uri.fromFile(f); // With 'permFile' being the File object | |
| mediaScannerIntent.setData(fileContentUri); | |
| getApplicationContext().sendBroadcast(mediaScannerIntent); | |
| // MediaScannerConnection.scanFile(this, paths, null, null); | |
| } catch (Exception e) { | |
| } | |
| if (mSensorManager != null) | |
| mSensorManager.unregisterListener(this); | |
| } | |
| private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { | |
| @Override | |
| public void onReceive(Context context, Intent intent) { | |
| // Log.d(TAG,"got a broadcast"); | |
| if (intent.getStringExtra("action")!=null){ | |
| if (intent.getStringExtra("action").contains("start")){ | |
| // startAccelService(); | |
| Log.d(TAG,"Action received"); | |
| } | |
| if (intent.getStringExtra("action").contains("stop")){ | |
| Log.d(TAG,"Action received"); | |
| // stopAccelService(); | |
| } | |
| } | |
| if (intent.getStringExtra("frequency")!=null){ | |
| // Log.d(TAG,"Frequency received"); | |
| // updateUI(intent); | |
| } | |
| if (intent.getStringExtra("filename")!=null){ | |
| FILENAME="/"+intent.getData(); | |
| Log.d(TAG," Got a filename "+FILENAME); | |
| // updateUI(intent); | |
| } | |
| if (intent.getStringExtra("sync")!=null){ | |
| Log.d(TAG,"got a sync command"); | |
| } | |
| } | |
| }; | |
| @Override | |
| public void onSensorChanged(SensorEvent event) { | |
| // Start the main activity if it is not running | |
| // if (!MainActivity.active){ | |
| // if (!thread){ | |
| // new Thread( new Runnable() { | |
| // @Override | |
| // public void run() { | |
| // Intent intentMain; | |
| // intentMain = new Intent(getBaseContext(),MainActivity.class); | |
| // intentMain.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
| // startActivity(intentMain); | |
| // thread=false; | |
| // } | |
| // }).start(); | |
| // } | |
| // } | |
| t1=System.currentTimeMillis(); | |
| if (t1-t0>1000){ | |
| Log.d(TAG,"Sampling rate "+ Float.toString(count)); | |
| tail=String.format("%s.",tail); | |
| intent.putExtra("frequency", String.format("%d%s",samplingRate,tail)); | |
| sendBroadcast(intent); | |
| samplingRate=count; | |
| count=0; | |
| t0=t1; | |
| if (tail.length()>5){ | |
| tail="."; | |
| } | |
| } | |
| count++; | |
| data.setX(event.values[0]); | |
| data.setY(event.values[1]); | |
| data.setZ(event.values[2]); | |
| data.setTime(t1); | |
| if (recordingStrategy.equalsIgnoreCase("fullDay")){ | |
| storeDataMultiple(data); | |
| } | |
| else{ | |
| storeDataFast(data); | |
| } | |
| } | |
| void storeDataFast(Data data){ | |
| file.println(String.format("%s,%f,%f,%f",Long.toString(data.getTime()),data.getX(),data.getY(),data.getZ())); | |
| } | |
| void storeDataMultiple(Data data){ | |
| if (countDM>90000){ | |
| countDM=0; | |
| file.close(); | |
| try { | |
| file= new PrintWriter(fileExists(STORAGE_FOLDER+FILENAME)); | |
| } catch (FileNotFoundException e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| file.println(String.format("%s,%f,%f,%f",Long.toString(data.getTime()),data.getX(),data.getY(),data.getZ())); | |
| countDM++; | |
| } | |
| @Override | |
| public void onAccuracyChanged(Sensor sensor, int accuracy) { | |
| } | |
| @Override | |
| public int onStartCommand(Intent intent, int flags, int startId) { | |
| // //Power management | |
| PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); | |
| wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag"); | |
| wl.acquire(); | |
| Log.d(TAG,"onStartCommand"); | |
| if (null==intent){ | |
| Log.d(TAG,"intent was null"); | |
| //This means the service was running but for some reason was interrupted so it is restarted | |
| String filename; | |
| FILENAME = "/fullday"+"-"+sdf.format(System.currentTimeMillis()); | |
| Log.d(TAG,"Restarting full day data collection"); | |
| checkPath(STORAGE_FOLDER); | |
| filename = fileExists(STORAGE_FOLDER+FILENAME); | |
| recordingStrategy="fullDay"; | |
| try { | |
| file = new PrintWriter(filename); | |
| data= new Data(); | |
| startMeasurement(); | |
| } catch (FileNotFoundException e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| else if (intent.hasExtra("fullDay")){ | |
| String filename; | |
| FILENAME = "/fullday"+"-"+sdf.format(System.currentTimeMillis()); | |
| Log.d(TAG,"Start full day data collection"); | |
| checkPath(STORAGE_FOLDER); | |
| filename = fileExists(STORAGE_FOLDER+FILENAME); | |
| recordingStrategy="fullDay"; | |
| try { | |
| file = new PrintWriter(filename); | |
| data= new Data(); | |
| startMeasurement(); | |
| } catch (FileNotFoundException e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| else if (intent.hasExtra("filename")){ | |
| FILENAME="/"+intent.getStringExtra("filename")+"-"+sdf.format(System.currentTimeMillis()); | |
| Log.d(TAG,"got filename "+FILENAME); | |
| Log.d(TAG,"Starting measurement"); | |
| try { | |
| String filename; | |
| checkPath(STORAGE_FOLDER); | |
| filename = fileExists(STORAGE_FOLDER+FILENAME); | |
| file = new PrintWriter(filename); | |
| // file. | |
| } catch (FileNotFoundException e) { | |
| e.printStackTrace(); | |
| } | |
| data = new Data(); | |
| t0=System.currentTimeMillis(); | |
| startMeasurement(); | |
| } | |
| // We want this service to continue running until it is explicitly | |
| // stopped, so return sticky. | |
| return START_STICKY; | |
| } | |
| private void sendMessage( final String path, final String text ) { | |
| new Thread( new Runnable() { | |
| @Override | |
| public void run() { | |
| NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes( googleClient ).await(); | |
| for(Node node : nodes.getNodes()) { | |
| MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage( | |
| googleClient, node.getId(), path, text.getBytes() ).await(); | |
| } | |
| } | |
| }).start(); | |
| } | |
| @Override | |
| public void onConnected(Bundle bundle) { | |
| } | |
| @Override | |
| public void onConnectionSuspended(int i) { | |
| } | |
| @Override | |
| public void onConnectionFailed(ConnectionResult connectionResult) { | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment