Illegalstateexception at seemingly random point in time.
My program is receiving a stream of accelerator and gyroscope data and sending that to my activity. It should keep running until manually stopped by an activity but after a random period of time(sometimes 10minutes or 2 hours) I'll get this exception and my catch block is never reached:
2019-10-01 09:39:21.812 25026-25026/io.lumme.capture E/AndroidRuntime: FATAL EXCEPTION: main Process: io.lumme.capture, PID: 25026 java.lang.IllegalStateException: The specified message queue synchronization barrier token has not been posted or has already been removed. at android.os.MessageQueue.removeSyncBarrier(MessageQueue.java:514) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1774) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7827) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911) at android.view.Choreographer.doCallbacks(Choreographer.java:723) at android.view.Choreographer.doFrame(Choreographer.java:658) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6944) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
At a minimum I need to keep the application from crashing and retry connection but don't know where the exception can be caught?
`
@Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
// Typecast the binder to the service's LocalBinder class
serviceBinder = (BtleService.LocalBinder) service;
retrieveBoard();
try {
// ---------------------------------------------------------------------------------------------
board.connectAsync().onSuccessTask(new Continuation<Void, Task<Route>>() {
@Override
public Task<Route> then(Task<Void> task) throws Exception {
accelerometer = board.getModule(Accelerometer.class);
accelerometer.configure()
.odr(25f) // Set sampling frequency to 25Hz, or closest valid ODR
.commit();
// Adds a Stream route to access the accelerometer module features
return accelerometer.acceleration().addRouteAsync(new RouteBuilder() {
@Override
public void configure(RouteComponent source) {
source.stream(new Subscriber() {
@Override
public void apply(Data data, Object... env) {
// When data is received update the accelerator text field
float x = (float) (data.value(Acceleration.class).x() * 9.80665);
float y = (float) (data.value(Acceleration.class).y() * 9.80665);
float z = (float) (data.value(Acceleration.class).z() * 9.80665);
long time = data.timestamp().getTimeInMillis();
if (mDataObserved != null) {
mDataObserved.onAccelObserved(x, y, z, time, retry_count);
}
}
});
}
});
}
}).continueWith(new Continuation<Route, Void>() {
@Override
public Void then(Task<Route> task) throws Exception {
if (task.isFaulted()) {
Log.e("fault", task.getError().toString());
}
// Task Failed
Exception error = task.getError();
// retry?
board.disconnectAsync();
onServiceConnected(componentName, service);
} else {
// Task Worked
accelerometer.acceleration().start();
accelerometer.start();
}
return null;
}
}).continueWith(new Continuation<Void, Task<Void>>() {
@Override
public Task<Void> then(Task<Void> task) throws Exception {
gyroBmi160 = board.getModule(GyroBmi160.class);
gyroBmi160.configure()
.odr(GyroBmi160.OutputDataRate.ODR_25_HZ)
.range(GyroBmi160.Range.FSR_500)
.commit();
// Adds a Stream route to access the gyro module features
return gyroBmi160.angularVelocity().addRouteAsync(new RouteBuilder() {
@Override
public void configure(RouteComponent source) {
source.stream(new Subscriber() {
@Override
public void apply(Data data, Object... env) {
// When data is received update the gyro text field
float x = (float) (data.value(AngularVelocity.class).x() * (Math.PI / 180));
float y = (float) (data.value(AngularVelocity.class).y() * (Math.PI / 180));
float z = (float) (data.value(AngularVelocity.class).z() * (Math.PI / 180));
long time = data.timestamp().getTimeInMillis();
if (mDataObserved != null) {
mDataObserved.onGyroObserved(x, y, z, time, retry_count);
}
// -----------------------------------------------------------------
}
});
}
}).continueWith(new Continuation<Route, Void>() {
@Override
public Void then(Task<Route> task) throws Exception {
if(task.isFaulted()){
Log.e("fault", task.getError().toString());
// Task Failed
Exception error = task.getError();
// retry?
board.disconnectAsync();
onServiceConnected(componentName, service);
} else {
// Task Worked
gyroBmi160.angularVelocity().start();
gyroBmi160.start();
}
return null;
}
});
}
});
} catch (Exception e){
Log.i(TAG, "--------------------------------------------------------");
Log.i(TAG, e.getMessage().toString());
Log.i(TAG, "--------------------------------------------------------");
}`
Comments
What are the steps the reproduce the issue? If not consistently reproducible, then what were the steps that lead to one of the incidents?
onAccelObserved and onGyroObserved just write the data to a file and have it constantly updating two textfields.
For now having the textfields update less frequently seems to reduce the issue, I just recreate the whole process on crash. I though it might be a synchronization issue but making the methods syncronized doesn't fix it.
If the answer isn't obvious it seems like my current fix is good enough.