Skip to content

Instantly share code, notes, and snippets.

@julian-ramos
Created July 21, 2015 18:40
Show Gist options
  • Select an option

  • Save julian-ramos/6ee7ad8a74ee4b442530 to your computer and use it in GitHub Desktop.

Select an option

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
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