I have a class, Recorder, which captures sensor data and writes it to a database. All the database handling occurs in Recorder. Here I’m running it in a new thread. mContext comes from getApplicationContext().
Runnable startRunnable = new Runnable(){
public void run() {
Recorder recorder = new Recorder((SensorManager) getSystemService(SENSOR_SERVICE), mContext);
recorder.start();
}
};
recorderThread = new Thread(startRunnable);
recorderThread.start();
Here are the relevant bits for Recorder:
public Recorder(SensorManager sensorManager, Context context){
mSensorManager = sensorManager;
mContext = context;
}
void start(){
List <Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
for(Sensor sensor : sensorList){
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
}
}
public void onSensorChanged(SensorEvent event) {
SensorDatabase dbHelper = new SensorDatabase(mContext);
mDb = dbHelper.getWritableDatabase();
if(mDb != null && mDb.isOpen()){
ContentValues values = new ContentValues();
values.put(DataColumns.ACCURACY, event.accuracy);
// more values stuff ...
mDb.insert(SensorDatabase.TABLE_NAME, null, values);
mDb.close();
}
}
The application records the data, but is getting ANR errors. If I make it so that the database doesn’t get initialized in Recorder, there is no ANR error.
How could this Runnable be blocking the UI thread here? There are no callbacks, and the UI thread never tries to open a database connection, at least it isn’t my intention to do so.
I looked into traces.txt for the ANR, it said thread “main” was executing:
android.database.sqlite.SQLiteStatement.native_executeSql(Native Method)
Any pointers? I’m pretty confused.
The
Runnableis not blocking the main application thread (a.k.a., “UI thread”).onSensorChanged()is blocking the main application thread, becauseonSensorChanged()is called on the main application thread, and therefore you are doing disk I/O on the main application thread.