Three-minute app tutorial video for children!

I have created a 3-minute tutorial video to help participating children understand the functionalities of the app ahead of the upcoming user study at De Lange Keizer BSO. I used iMovie, and GoAnimate‘s tools to create that video. Check it out!

Advertisements

Location sharing app for families: a formal(ish) description

Finally the app is done. Here’s a formal description, as it went in one of the papers we wrote:

The application permits its users to share check-ins in certain locations with other users of the system (such as family members and school friends), similar to the popular application Foursquare. The check-in feature was selected for our case study based on the analysis previous qualitative data with members of our target group.

Basic features and preferences

Users can place other users of the system in one of two lists (“family” or “friends”), otherwise they are placed in the list “others”. Users can select with which lists they share their check-ins, and from which lists they view shared check-ins.

Users can create locations either through placing a marker on an integrated Google Map, or simply by detecting the current GPS position. The application will create a 50m*50m location surrounding the resulting GPS coordinates, to which the users can assign a name.

When a user wants to check-in, a list of nearby, already created locations is displayed (with the option of adding a new location). The user can select their location, and confirm their check-in, to be shared with the users in the lists our user is sharing with, according to their preferences. Users who receive this check-in will get a pop-up with the sharer’s name and location information, assuming that they opted (in their own preferences) to view check-ins from the list to which the sharer belongs.

Social commitments

The application allows for additional, norm-based behavior customization. Drawing from the social commitments framework by Singh, and our analysis of user data, we have created the following commitment model:

A commitment (S, T, t, n, e, d) consists of S the source (creator of the commitment), T the target that has to comply with it, t the triggering condition that activates the commitment, n the normative effect (an obligation or a prohibition of sharing or viewing a check-in, from someone or a group of people), e the expiry condition that deactivates the commitment, and d the deadline by which an obligation commitment should be fulfilled.

For example, Mark (source) can create the following commitment: (1) I want Paula (target) to share her check-ins with me (normative effect), if she enters the park (triggering condition). Another example is Mark creating the commitment: (2) I want Paula to “not view” check-ins from the group “friends” (normative effect) after 9 pm (triggering condition). In the current app version, the deadline ASAP is used for obligation commitments. Expiry condition in (1) is not required, while in (2) it is implied as a certain hour (9 am).

Upon creation, commitments are sent from source to target, whereby the target can either accept or delete the commitment, or “decide later”. The commitment enters its “active” state when it’s been accepted by the target, and the trigger condition has been met. The commitment leaves its “active” state when the expiry condition has been met, but can re-enter that state if the triggering condition was met again, provided that it was not deleted.

Conflicts between preferences and an active commitment are decided in favor of the commitment. For example, if Mark is in Paula’s family list, and Paula opted in her preferences to “not share check-ins with family”, accepting commitment (1) above means Paula’s check-in will be shared with Mark if she enters the park. Conflicts between two active commitments would be solved in favor of the commitment most recently accepted.

A 3-minute tutorial video of the application (with subtitles) can be seen here.

Fully implemented app interface

Finally we have the app’s XML code for the interface implemented. Along with our programmer we both took part in implementing this interface. With android it can be quite tricky to create menus that update their contents interdependently, such as the Afspraken (agreements) menu, see photos. Must use runOnUiThread, which can be quite complex. Luckily StackOverflow is abundant with examples on that, like this one for example.

However, it is a still a very satisfying experience to have such a complex menu finally work flawlessly, while knowing that I’m being able to implement what is required in case we needed to change anything.

Screenshot_2014-05-13-08-54-13  Screenshot_2014-05-13-08-54-24  Screenshot_2014-05-13-08-54-40  Screenshot_2014-05-13-08-55-38

Screenshot_2014-05-13-08-56-00  Screenshot_2014-05-13-08-56-27  Screenshot_2014-05-13-08-57-12  Screenshot_2014-06-09-17-55-50

Creating a listener in an Android app

First we define the polling period.

private static long POLL_PERIOD = 20000; // period in ms.
privatestaticbooleancreated = false; // / safety check

Then, create the listener as a service. From there we call the service thread.

@Override
publicsynchronizedvoid onCreate() {
if (created) {
thrownew IllegalStateException(
"attempt to create listener twice!!");
}

created = true;
System.out.println("listener was created");
startServiceThread();
}

This thread will run the service. Has to be a thread in Android, can’t run on the main UI.

private void startServiceThread() {
new Thread(new Runnable() {
@Override
publicvoid run() {
runService();
}
}).start();
}

And here starts the endless loop of the listener. You let the thread sleep for your polling period, then you do your stuff after that call.

public void runService() {
System.out.println("listener running");
// the main loop.
while (true) {
try {
// first this, to ensure we always sleep in the loop.
Thread.sleep(POLL_PERIOD);
// do your stuff here
} catch (Throwable e) {
if (e instanceof UnknownHostException) {
System.out.println("check failed, no network");
} else {
e.printStackTrace();
}
}
}
}

A not-so-costly Google Location Listener implementation for Android apps

You need to, sometimes, get a very quick GPS position, even if not a very fine estimation, and then after that you can rely on a more relaxed location updates. This below is a way to speed up the initial requests and then later switched to “relaxed” mode.

Up top, you can have these variables.

private LocationClient locationClient = null;
private longinitialInterval = 2000; // 2 seconds
private long usualInterval = 10000; // 10 seconds
private int num Updates = 0;
LocationRequest locReq = new LocationRequest();

Then, on initial connection, set the request time to initialInterval (2 seconds).

@Override
public void onConnected(Bundle connectionHint){
System.out.println("Success connected to GooglePlayServices");
locReq.setInterval(initialInterval);
locationClient.requestLocationUpdates(locReq, this);
}

After a certain number of updates, change to usualInterval, which is 10 seconds (can be more).

@Override
public void onLocationChanged(Location location) {
LocationCache.getInstance().setPosition(getPos(location));
System.out.println("loc: " + location.getLatitude() 
+ "/" + location.getLongitude());

if (numUpdates<30){
locReq.setInterval(usualInterval);
locationClient.requestLocationUpdates(locReq, this);
numUpdates = numUpdates + 1;
}

}

Your own custom transitions within an Android app

Below is a function that takes you to another activity (namely, LocationsActivity). Instead of using the usual startActivity(), we call startActivity through this function:

public void locationsClick(View v) throws
JSONException, IOException {
Utils.forwardToActivity(this, new Intent
(this, LocationsActivity.class));
}

And in that function, we can override the transition, to our custom ones R.anim.move_in_right, R.anim.move_out_left.

/**
* go forward to given activity. Makes the new activity
* scroll in from * the right, hence the 'forward'.
**/

public static void forwardToActivity
(Activity currentActivity, Intent intent) {
currentActivity.startActivity(intent);
currentActivity.overridePendingTransition
(R.anim.move_in_right, R.anim.move_out_left);
}