Reputation: 318
I'm resurrecting an old app I wrote that wakes up once every minute and logs my phone's orientation.
The issue I'm observing now, which is different from when the code was written circa 2015, is that the onSensorChanged
method only ever fires the first time the code is run.
From the logs, I see onStartcommand
is activated every minute, which is the frequency at which an AlarmManager
sends a wakeup Intent to the Service. However, as noted, the actual onSensorChanged
event only ever fires once.
Here's the Service
implementing SensorEventListener
:
public class MainSensorSampler extends Service implements SensorEventListener {
private SensorManager sm;
private Sensor mAccelerometer;
private final int MAX_BATCH_DELAY = 10*1000; // 10 second batch length
private static final String TAG = "AKA_MainSensorSampler";
private long lastUpdate = 0;
private String filePath;
public int onStartCommand(Intent intent, int flags, int startId){
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "we are inside onStartCommand()");
filePath = this.getFilesDir().getPath().toString() + "/aka_fixture.csv";
Log.d(TAG, "filepath is "+filePath);
// here is where I removed the sensormanager init code and moved it to onCreate
sm = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sm.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
Log.d(TAG, "about to return START_STICKY, should we be doing this more than once?");
return START_STICKY;
}
protected void onResume(){
Log.d(TAG, "in onResume()");
sm.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// don't care
Log.d(TAG, "we are inside an onAccuracyChanged");
}
@Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
Log.d(TAG, "we are inside onSensorChanged");
long ts = System.currentTimeMillis();
// don't write to file here, this method gets called like all the time
if(ts - (60*1000) > lastUpdate){
Log.d(TAG, "we are inside an Accelerometer Event");
// if the sensor change event is at least one minute away from the last reading
// record it to the log
// this is a crummy way to ignore intra-interval events
// sending {<timestamp>, <x>, <y>, <z> <newline>}
String data = Long.toString(ts)+","+Double.toString(event.values[0])+","+Double.toString(event.values[1])+","+Double.toString(event.values[2]);
Log.d(TAG,"Made String "+data);
writeData(data, filePath);
lastUpdate = ts;
// trying this because we seem to fire the onStartCommand method every interval, and
// that is where we register a listener
sm.unregisterListener(this);
}
}
}
public void writeData(String data, String strFilePath) {
PrintWriter csvWriter;
try {
/*1. declare stringBuffer*/
StringBuffer oneLineStringBuffer = new StringBuffer();
File file = new File(strFilePath);
if (!file.exists()) {
file = new File(strFilePath);
}
csvWriter = new PrintWriter(new FileWriter(file, true));
/*2. append to stringBuffer*/
oneLineStringBuffer.append(data);
oneLineStringBuffer.append(System.lineSeparator());
/*3. print to csvWriter*/
csvWriter.print(oneLineStringBuffer);
csvWriter.close();
} catch (Exception e) {
Log.d(TAG,"Writing to file messed up!");
e.printStackTrace();
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onDestroy(){
Log.d(TAG, "we are inside onDestroy()");
sm.unregisterListener(this);
super.onDestroy();
}
}
...and here is a sample of the logs just after the app is initialized, showing the first (successful) reading:
D/AKA_MainSensorSampler: we are inside onStartCommand()
D/AKA_MainSensorSampler: filepath is /data/user/0/com.akamediasystem.fixture/files/aka_fixture.csv
D/CompatibilityChangeReporter: Compat change id reported: 136069189; UID 10039; state: DISABLED
D/AKA_MainSensorSampler: about to return START_STICKY, should we be doing this more than once?
D/AKA_MainSensorSampler: we are inside an onAccuracyChanged
D/AKA_MainSensorSampler: we are inside onSensorChanged
D/AKA_MainSensorSampler: we are inside an Accelerometer Event
D/AKA_MainSensorSampler: Made String 1662922456038,0.6526423692703247,-0.9367900490760803,9.750154495239258
D/AKA_Uploader: Inside Uploader's onStartCommand() method
D/AKA_Uploader: Filepath is /data/user/0/com.akamediasystem.fixture/files/aka_fixture.csv
D/AKA_Uploader: 1662922456038,0.6526423692703247,-0.9367900490760803,9.750154495239258
D/TrafficStats: tagSocket(5) with statsTag=0xffffffff, statsUid=-1
I/TrafficStats: untagSocket(5)
D/AKA_Uploader: Success:
D/AKA_Uploader: deleted file? true
D/AKA_Uploader: reached onFinish in the Uploader task
..., and subsequent payload-less readings:
D/AKA_MainSensorSampler: we are inside onStartCommand()
D/AKA_MainSensorSampler: filepath is /data/user/0/com.akamediasystem.fixture/files/aka_fixture.csv
D/AKA_MainSensorSampler: about to return START_STICKY, should we be doing this more than once?
D/AKA_Uploader: Inside Uploader's onStartCommand() method
D/AKA_Uploader: Filepath is /data/user/0/com.akamediasystem.fixture/files/aka_fixture.csv
D/AKA_Uploader:
D/TrafficStats: tagSocket(5) with statsTag=0xffffffff, statsUid=-1
D/TrafficStats: tagSocket(5) with statsTag=0xffffffff, statsUid=-1
I/TrafficStats: untagSocket(5)
D/AKA_Uploader: Success:
D/AKA_Uploader: deleted file? true
D/AKA_Uploader: reached onFinish in the Uploader task
D/AKA_MainSensorSampler: we are inside onStartCommand()
D/AKA_MainSensorSampler: filepath is /data/user/0/com.akamediasystem.fixture/files/aka_fixture.csv
D/AKA_MainSensorSampler: about to return START_STICKY, should we be doing this more than once?
I'm concerned that I am re-registering the same SensorEventListener
many times, possibly leading to the registration being ignored? Or perhaps some other recent Android update has deprecated this strategy for interval sampling in the background, which worked for years until now?
Edit/update, I'm targeting API level 19 and this only needs to run on my personal phone, a Pixel 4a running the latest Android.
Thanks for any help you can provide!
AKA
Upvotes: 0
Views: 232