eventGetBrodcastCategories() {
return mBroadcastListeners.keySet();
}
/**
* Actual data returned in the map will depend on the type of event.
*
*
* Example (python):
* import android, time
* droid = android.Android()
* droid.startSensing()
* time.sleep(1)
* droid.eventClearBuffer()
* time.sleep(1)
* e = eventPoll(1).result
* event_entry_number = 0
* x = e[event_entry_ number]['data']['xforce']
*
*
* e has the format:
* [{u'data': {u'accuracy': 0, u'pitch': -0.48766891956329345, u'xmag': -5.6875, u'azimuth':
* 0.3312483489513397, u'zforce': 8.3492730000000002, u'yforce': 4.5628165999999997, u'time':
* 1297072704.813, u'ymag': -11.125, u'zmag': -42.375, u'roll': -0.059393649548292161,
* u'xforce': 0.42223078000000003}, u'name': u'sensors', u'time': 1297072704813000L}]
* x has the string value of the x force data (0.42223078000000003) at the time of the event
* entry.
*/
@Rpc(description = "Returns and removes the oldest n events (i.e. location or sensor update, etc.) from the event buffer.",
returns = "A List of Maps of event properties.")
public List eventPoll(
@RpcParameter(name = "number_of_events") @RpcDefault("1") Integer number_of_events) {
List events = Lists.newArrayList();
for (int i = 0; i < number_of_events; i++) {
Event event = mEventQueue.poll();
if (event == null) {
break;
}
events.add(event);
}
return events;
}
@Rpc(description = "Blocks until an event with the supplied name occurs. Event is removed from the buffer if removeEvent is True.",
returns = "Map of event properties.")
public Event eventWaitFor(
@RpcParameter(name = "eventName")
final String eventName,
@RpcParameter(name = "removeEvent")
final Boolean removeEvent,
@RpcParameter(name = "timeout", description = "the maximum time to wait (in ms)") @RpcOptional Integer timeout)
throws InterruptedException {
Event result = null;
final FutureResult futureEvent;
synchronized (mEventQueue) { // First check to make sure it isn't already there
for (Event event : mEventQueue) {
if (event.getName().equals(eventName)) {
result = event;
if (removeEvent)
mEventQueue.remove(event);
return result;
}
}
futureEvent = new FutureResult();
addNamedEventObserver(eventName, new EventObserver() {
@Override
public void onEventReceived(Event event) {
if (event.getName().equals(eventName)) {
synchronized (futureEvent) {
if (!futureEvent.isDone()) {
futureEvent.set(event);
// TODO: Remove log.
Log.v(String.format("Removing observer (%s) got event (%s)",
this,
event));
removeEventObserver(this);
}
if (removeEvent)
mEventQueue.remove(event);
}
}
}
});
}
if (futureEvent != null) {
if (timeout != null) {
result = futureEvent.get(timeout, TimeUnit.MILLISECONDS);
} else {
result = futureEvent.get();
}
}
return result;
}
@Rpc(description = "Blocks until an event occurs. The returned event is removed from the buffer.",
returns = "Map of event properties.")
public Event eventWait(
@RpcParameter(name = "timeout", description = "the maximum time to wait") @RpcOptional Integer timeout)
throws InterruptedException {
Event result = null;
final FutureResult futureEvent = new FutureResult();
EventObserver observer;
synchronized (mEventQueue) { // Anything in queue?
if (mEventQueue.size() > 0) {
return mEventQueue.poll(); // return it.
}
observer = new EventObserver() {
@Override
public void onEventReceived(Event event) { // set up observer for any events.
synchronized (futureEvent) {
if (!futureEvent.isDone()) {
futureEvent.set(event);
// TODO: Remove log.
Log.v(String.format("onEventReceived for event (%s)", event));
}
}
}
};
addGlobalEventObserver(observer);
}
if (timeout != null) {
result = futureEvent.get(timeout, TimeUnit.MILLISECONDS);
} else {
result = futureEvent.get();
}
if (result != null) {
mEventQueue.remove(result);
}
// TODO: Remove log.
Log.v(String.format("Removing observer (%s) got event (%s)", observer, result));
if (observer != null) {
removeEventObserver(observer); // Make quite sure this goes away.
}
return result;
}
/**
*
* Example:
* import android
* from datetime import datetime
* droid = android.Android()
* t = datetime.now()
* droid.eventPost('Some Event', t)
*
*/
@Rpc(description = "Post an event to the event queue.")
public void eventPost(
@RpcParameter(name = "name", description = "Name of event") String name,
@RpcParameter(name = "data", description = "Data contained in event.") String data,
@RpcParameter(name = "enqueue",
description = "Set to False if you don't want your events to be added to the event queue, just dispatched.") @RpcOptional @RpcDefault("false") Boolean enqueue) {
postEvent(name, data, enqueue.booleanValue());
}
/**
* Post an event and queue it
*/
public void postEvent(String name, Object data) {
postEvent(name, data, true);
}
/**
* Posts an event with to the event queue.
*/
public void postEvent(String name, Object data, boolean enqueue) {
Event event = new Event(name, data);
if (enqueue != false) {
synchronized (mEventQueue) {
while (mEventQueue.size() >= MAX_QUEUE_SIZE) {
mEventQueue.remove();
}
mEventQueue.add(event);
}
Log.v(String.format("postEvent(%s)", name));
}
synchronized (mNamedEventObservers) {
for (EventObserver observer : mNamedEventObservers.get(name)) {
observer.onEventReceived(event);
}
}
synchronized (mGlobalEventObservers) {
// TODO: Remove log.
Log.v(String.format("mGlobalEventObservers size (%s)", mGlobalEventObservers.size()));
for (EventObserver observer : mGlobalEventObservers) {
observer.onEventReceived(event);
}
}
}
@RpcDeprecated(value = "eventPost", release = "r4")
@Rpc(description = "Post an event to the event queue.")
@RpcName(name = "postEvent")
public void rpcPostEvent(
@RpcParameter(name = "name") String name,
@RpcParameter(name = "data") String data) {
postEvent(name, data);
}
@RpcDeprecated(value = "eventPoll", release = "r4")
@Rpc(description = "Returns and removes the oldest event (i.e. location or sensor update, etc.) from the event buffer.",
returns = "Map of event properties.")
public Event receiveEvent() {
return mEventQueue.poll();
}
@RpcDeprecated(value = "eventWaitFor", release = "r4")
@Rpc(description = "Blocks until an event with the supplied name occurs. Event is removed from the buffer if removeEvent is True.",
returns = "Map of event properties.")
public Event waitForEvent(
@RpcParameter(name = "eventName")
final String eventName,
@RpcOptional
final Boolean removeEvent,
@RpcParameter(name = "timeout", description = "the maximum time to wait") @RpcOptional Integer timeout)
throws InterruptedException {
return eventWaitFor(eventName, removeEvent, timeout);
}
@Rpc(description = "Opens up a socket where you can read for events posted")
public int startEventDispatcher(
@RpcParameter(name = "port", description = "Port to use") @RpcDefault("0") @RpcOptional() Integer port) {
if (mEventServer == null) {
if (port == null) {
port = 0;
}
mEventServer = new EventServer(port);
addGlobalEventObserver(mEventServer);
bEventServerRunning = true;
}
return mEventServer.getAddress().getPort();
}
@Rpc(description = "sl4a session is shutting down, send terminate event to client.")
public void closeSl4aSession() {
eventClearBuffer();
postEvent("EventDispatcherShutdown", null);
}
@Rpc(description = "Stops the event server, you can't read in the port anymore")
public void stopEventDispatcher() throws RuntimeException {
if (bEventServerRunning == true) {
if (mEventServer == null) {
throw new RuntimeException("Not running");
}
bEventServerRunning = false;
mEventServer.shutdown();
Log.v(String.format("stopEventDispatcher (%s)", mEventServer));
removeEventObserver(mEventServer);
mEventServer = null;
}
return;
}
@Override
public void shutdown() {
try {
stopEventDispatcher();
} catch (Exception e) {
Log.e("Exception tearing down event dispatcher", e);
}
mGlobalEventObservers.clear();
mEventQueue.clear();
}
public void addNamedEventObserver(String eventName, EventObserver observer) {
mNamedEventObservers.put(eventName, observer);
}
public void addGlobalEventObserver(EventObserver observer) {
mGlobalEventObservers.add(observer);
}
public void removeEventObserver(EventObserver observer) {
mNamedEventObservers.removeAll(observer);
mGlobalEventObservers.remove(observer);
}
public class BroadcastListener extends android.content.BroadcastReceiver {
private EventFacade mParent;
private boolean mEnQueue;
public BroadcastListener(EventFacade parent, boolean enqueue) {
mParent = parent;
mEnQueue = enqueue;
}
@Override
public void onReceive(Context context, Intent intent) {
Bundle data;
if (intent.getExtras() != null) {
data = (Bundle) intent.getExtras().clone();
} else {
data = new Bundle();
}
data.putString("action", intent.getAction());
try {
mParent.eventPost("sl4a", JsonBuilder.build(data).toString(), mEnQueue);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}