Pinte

25
In Touch with Things: Programming NFC on Android with MORENA Kevin Pinte Andoni Lombide Carreton Wolfgang De Meuter Droidcon April 10, 2013 Berlin, Germany

Transcript of Pinte

Page 1: Pinte

In Touch with Things: Programming NFC on Android with MORENA

Kevin PinteAndoni Lombide CarretonWolfgang De Meuter

DroidconApril 10, 2013Berlin, Germany

Page 2: Pinte

• NFC (touch range).

• Callback on activities to detect RFID tags with subscribed MIME-type in memory.

• File access abstraction

RFID in Android

NdefMessage: { , , }

NdefRecord byte array

read write

Page 3: Pinte

Drawbacks of the Android NFC API

• Manual failure handlingfailures are the rule rather than the exception:NFC causes A LOT of failures because of its hardware characteristics

• Blocking communicationAndroid documentation recommends to use a separate thread for many NFC operations

• Manual data conversion

• Tight coupling with activity-based architecture

Page 4: Pinte

Lessons Learnt from Previous Ambient-Oriented Programming Research

• Using objects as first class software representations for RFID-tagged “things” is a nice abstraction.

• These objects can be directly stored in the RFID tags’ memory to minimize data conversion.

• Event-driven discovery (fortunately built-in into Android).

• Asynchronous, fault tolerant reads and writes.experimental scripting

language for mobile apps in ad hoc networks

RFID tags as “mobile devices” and I/O as

network communication

Page 5: Pinte

Application

MORENA Middleware Architecture

Android

Tag level

Thing level One middlewarefor Android 4.0 or higher (API 14)

Page 6: Pinte

Evaluation: Wi-Fi Sharing Application

Page 7: Pinte

Evaluation: Wi-Fi Sharing Application

Page 8: Pinte

Things

public class WifiConfig extends Thing {

public String ssid_; public String key_;

public WifiConfig(ThingActivity<WifiConfig> activity, String ssid, String key) { super(activity); ssid_ = ssid; key_ = key; } public boolean connect(WifiManager wm) {

// Connect to ssid_ with password key_ };}

From now on, we don’t have to worry about the

activity anymore.

Supported serialization: - JSON-serializable fields. - Skipping transient fields. - Deep serialization, no cycles.

Page 9: Pinte

Initializing Things

@Overridepublic void whenDiscovered(EmptyRecord empty) { empty.initialize( myWifiThing, new ThingSavedListener<WifiConfig>() { @Override public void signal(WifiConfig thing) { toast("WiFi joiner created!"); } }, new ThingSaveFailedListener() { @Override public void signal() { toast("Creating WiFi joiner failed, try again."); } },

5000);}

As soon as an empty tag is detected

Page 10: Pinte

Discovering and Reading Things

@Overridepublic void whenDiscovered(WifiConfig wc) { toast("Joining Wifi network " + wc.ssid_); wc.connect();}

As soon as a WifiConfig tag is detected

Contains cached fields for synchronous access.

Physical reads must be asynchronous.

Page 11: Pinte

Saving Modified ThingsmyWifiConfig.ssid_ = "MyNewWifiName";myWifiConfig.key_ = "MyNewWifiPassword";

myWifiConfig.saveAsync( new ThingSavedListener<WifiConfig>() { @Override public void signal(WifiConfig wc) { toast("WiFi joiner saved!"); } }, new ThingSaveFailedListener() { @Override public void signal() { toast("Saving WiFi joiner failed, try again."); } }, 5000);

Page 12: Pinte

Broadcasting Things to Other Phones

myWifiConfig.broadcast( new ThingBroadcastSuccessListener<WifiConfig>() { @Override public void signal(WifiConfig wc) { toast("WiFi joiner shared!"); } }, new ThingBroadcastFailedListener<WifiConfig>() { @Override public void signal(WifiConfig wc) { toast("Failed to share WiFi joiner, try again."); } }, 5000);

Will trigger whenDiscovered on the receiving phone with the broadcasted thing

Page 13: Pinte

Evaluation: WiFi Sharing Application

Page 14: Pinte

MORENA Middleware Architecture

Android

Tag level

Thing level

Application

One middlewarefor Android 4.0 or higher (API 14)

Page 15: Pinte

Detecting RFID Tags

new TextTagDiscoverer(currentActivity, TEXT_TYPE, new NdefMessageToStringConverter(), new StringToNdefMessageConverter());

private class TextTagDiscoverer extends TagDiscoverer { @Override public void onTagDetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); } @Override public void onTagRedetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); }}

Page 16: Pinte

The Tag Reference Abstraction

Page 17: Pinte

Reading RFID Tags

tagReference.read( new TagReadListener() { @Override public void signal(TagReference tagReference) { // tagReference.getCachedData() } }, new TagReadFailedListener() { @Override public void signal(TagReference tagReference) { // Deal with failure } });

Page 18: Pinte

Writing RFID Tags

tagReference.write( toWrite, new TagWrittenListener() { @Override public void signal(TagReference tagReference) { // Handle write success } }, new TagWriteFailedListener() { @Override public void signal(TagReference tagReference) { // Deal with failure } });

Page 19: Pinte

Fine-grained Filtering

private class TextTagDiscoverer extends TagDiscoverer { @Override public void onTagDetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); } @Override public void onTagRedetected(TagReference tagReference) { readTagAndUpdateUI(tagReference); }

@Override public boolean checkCondition(TagReference tagReference) { // Can be used to apply a predicate // on tagReference.getCachedData() }}

Page 20: Pinte

MORENA Conclusion

• Event-driven discovery.

• Non-blocking communication:

• Things: cached copy, asynchronous saving of cached data.

• TagReferences: first class references to RFID tags offering asynchronous reads and writes.

• Automatic data conversion

• Looser coupling from activity-based architecture

Page 21: Pinte

Current Research: Volatile Database

• Data structures over many tags?

• Querying collections of things?

• Stronger consistency guarantees?

• Transactions?

• Validations?

• ... Active Record (RoR) for RFID

Page 22: Pinte

Thing Associations

defmodel: Shelf properties: { number: Number} associations: { hasMany: `books};

defmodel: Book properties: { title: Text; authors: Text; isbn: Text;} proto: { def isMisplaced(currentShelf) { shelf != currentShelf; };} associations: {

belongsTo: `shelf};

a shelf contains many books

a book belongs to exactly one shelf in the library

Page 23: Pinte

Instantiating a Model and Saving to Tag

def newBook := Book.create: {title := “Agile Web Development with Rails”;authors := “Dave Thomas, ...”;isbn := “978-0-9776-1663-3”;

};def saveReq := newBook.saveAsync(10.seconds);when: saveReq succeeded: {

// the book was saved to a tag} catch: { |exc|

// book could not be saved within 10 sec};

newBook.shelf := shelf42;

shelf42.books << newBook; associate a book with a shelf:foreign key in book thing

Page 24: Pinte

Working with Many Things: Reactive Queries

def shelf42 := Shelf.all.first: { |s| s.number == 42 };def currentShelf := Shelf.all.last;

def misplacedBooks := Book.all.where: { |b|b.isMisplaced(currentShelf)

};

misplacedBooks.each: { |b|b.shelf := currentShelf;b.saveAsync(5.seconds)

};

most recently scanned shelf

synchronize misplaced books with current shelf

finding misplaced books in a library

all books not matching the last scanned shelf

Page 25: Pinte

In Touch with Things: Programming NFC on Android with MORENA

Droidcon, April 10, 2013, Berlin, Germany

@ambienttalk

soft.vub.ac.be/amopcode.google.com/p/ambienttalk

tinyurl.com/morena-android

[email protected]

@bommasaurus

tinyurl.com/kevinpinte