Depending on the way you want to access the data, you have three basic methods for reading it in an AWARE plugin or an application that uses AWARE as a library.


Passive context

Reading the data directly from the database can be used using simple SQL queries (since the data is stored in an SQLite database). In this example, if you replace the tableColumns, whereCondition, and whereArguments with null, you get all the accelerometer records into memory. Please note that, depending on your device and available RAM, you may have to impose a whereCondition when loading all the records on your database. For example, to read the accelerometer data table, you will need a line like this:

Cursor accelerometer_data = getContentResolver().query(Accelerometer_Data.CONTENT_URI, tableColumns, whereCondition, whereArguments, orderBy);

This line returns a cursor object containing data from the defined URI, in this case the URI for the accelerometer’s database. The other parameters for the query() method are the conditions for your SQL query. Here is an example to retrieve all the good records from the database (with good accuracy) in an ascendent orderly fashion:

Cursor accelerometer_data = getContentResolver().query(Accelerometer_Data.CONTENT_URI, null, "accuracy > 1", null, "timestamp ASC");

This query would return the data for all the table columns where the accuracy value is greater than 1 (low accuracy) and order the results chronologically (in an ascending order). The SQL query that is run is as follows.

SELECT * FROM accelerometer_data WHERE accuracy > 1 ORDER BY timestamp ASC

The data that was fetched will then be stored in the cursor object and can be read by moving the position within the cursor (moveToNext() method for example) and then reading the value for a field with the get methods (such as getString() which returns a string).

accelerometer_data.moveToFirst();
do {
   double x = accelerometer_data.getDouble(accelerometer_data.getColumnIndex(Accelerometer_Data.VALUES_0));
   double y = accelerometer_data.getDouble(accelerometer_data.getColumnIndex(Accelerometer_Data.VALUES_1));
   double z = accelerometer_data.getDouble(accelerometer_data.getColumnIndex(Accelerometer_Data.VALUES_2));
   //do what you need with x,y,z variables
} while (accelerometer_data.moveToNext());

This will iterate through all the fetched results, since the moveToNext() method returns False if is already in the last result and tries to move to the next (non-existing) result, resulting in the while-loop ending.

This method of reading data is best for analyzing past datapoints or reading data at certain intervals. If you want to access data directly when it is stored, you can use the other two methods explained below.


Active context method #1 – listening to changes in the data

In addition to passively reading data when the plugin finds it applicable, there are methods to also read the data in real time as it changes. The first method is to listen to the database for changes and then read the latest values.

The way to implement this functionality is to create a custom ContentObserver class.

public class ScreenObserver extends ContentObserver {
    public ScreenObserver(Handler handler) {
         super(handler);
    }

The ContentObserver class has an onChange() method that gets triggered everytime the database (“content”) it is listening to experiences changes (e.g. when new values get inserted). Inside the onChange() method you can include the functionality that you want to happen when the database changes, such as reading the new values.

public void onChange(boolean selfChange) {
    super(selfChange);
    // Get the latest recorded value
    Cursor screen = getContentResolver().query(Screen_Data.CONTENT_URI, null, null, null,
        Screen_Data.TIMESTAMP + ” DESC LIMIT 1”);
    if (screen != null && screen.moveToFirst()) {
        // Here we read the value
        int screen_status = screen.getInt(screen.getColumnIndex(Screen_Data.SCREEN_STATUS);
    }
}

Finally, you need to register your newly created ScreenObserver to your plugin and define to what URI it is listening to inside your Plugin.java file.

ScreenObserver so = new ScreenObserver(new Handler());
getContentResolver().registerContentObserver(Screen_Data.CONTENT_URI, true, so);

Also, its important that you unregister the observer in the onDestroy() method of your plugin so that your plugin does not cause memory leaks (the observers get left on even if your plugin crashes or is closed by Android).

getContentResolver().unregisterContentObserver(so);

Using this method you can always get the latest value from the database as the values change.

 


Active context method #2 – listening to new broadcasts

The new values from sensors and plugins are also broadcasted across Android by using broadcast services. Broadcasts are ways for different processes to communicate with each other. Basically each application can register to listen to different broadcasts or send broadcasts and will be notified every time a new broadcast is sent system-wide.

What you need to do is to create a new custom BroadcastReceiver class. The class will inherit a method onReceive() that gets called everytime the listener receives new broadcasts.

public class ScreenStatusListener extends BroadcastReceiver {
    public void onReceive(Context c, Intent intent) {
        Log.d(TAG, ”Yay the screen was unlocked!”);
    }
}

The information of the broadcast (such as new data values) is inside the Intent object that the onReceive() method receives. Specifically inside any broadcast extras in the intent. The data can be then accessed by looking at the specific sensor’s information for what broadcasts and extras it sends.

public void onReceive(Context c, Intent intent) {
    Object o = intent.getExtras().get("name of the extra");
}

Finally, you need to create the listener and register it inside your Plugin.java class. Its preferred to create the listeners as static class variables.

private static ScreenStatusListener ssl = new ScreenStatusListener();

The rest of the code can go inside the onCreate() or onResume() method.

IntentFilter broadcastFilter = new IntentFilter();
broadcastFilter.addAction(Screen.ACTION_AWARE_SCREEN_UNLOCKED);
registerReceiver(ssl, broadcastFilter);

The action you are adding to the filter is the type of broadcast the listener is triggered on.

Again, its important to unregister the receiver in the onDestroy() method to prevent memory leaks.

How do I read data?