Upload
prismtech
View
658
Download
0
Embed Size (px)
Citation preview
Connected Mobile and Web Applications with
AngeloCorsaro,PhDChiefTechnologyOfficer
IaaS
analytics
operational systems
information systems
mobile
desktop
web
embeddedfog computing
integration
Applications can autonomously and asynchronously read and write data enjoying spatial and
temporal decoupling DDS Global Data Space
...
Data Writer
Data Writer
Data Writer
Data Reader
Data Reader
Data Reader
Data Reader
Data Writer
TopicAQoS
TopicBQoS
TopicCQoS
TopicDQoS
Global Data Space
Built-in dynamic discovery isolates applications from
network topology and connectivity details
DDS Global Data Space
...
Data Writer
Data Writer
Data Writer
Data Reader
Data Reader
Data Reader
Data Reader
Data Writer
TopicAQoS
TopicBQoS
TopicCQoS
TopicDQoS
Dynamic Discovery
QoS policies allow to express temporal and availability
constraints for data
DDS Global Data Space
...
Data Writer
Data Writer
Data Writer
Data Reader
Data Reader
Data Reader
Data Reader
Data Writer
TopicAQoS
TopicBQoS
TopicCQoS
TopicDQoS
QoS - Enabled
No single point of failure or bottleneck
Decentralised Data Space Data
Writer
Data Writer
Data Writer
Data Reader
Data Reader
Data Reader
Data Writer
TopicAQoS
TopicBQoS
TopicCQoS
TopicDQoS
TopicDQoS
TopicDQoS
TopicAQoS
Connectivity is dynamically adapted to chose the most
effective way of sharing data
Adaptive ConnectivityData
Writer
Data Writer
Data Writer
Data Reader
Data Reader
Data Reader
Data Writer
TopicAQoS
TopicBQoS
TopicCQoS
TopicDQoS
TopicDQoS
TopicDQoS
TopicAQoS
ThecommunicationbetweentheDataWriterandmatchingDataReaderscanbepeer-to-peerexploitingUDP/IP(UnicastandMulticast)orTCP/IP
ThecommunicationbetweentheDataWriterandmatchingDataReaderscanbe“brokered”butstillexploitingUDP/IP(UnicastandMulticast)orTCP/IP
A domain-wide information’s class A Topic defined by means
of a <name, type, qos>
TopicDDS Global Data Space
...
Data Writer
Data Writer
Data Writer
Data Reader
Data Reader
Data Reader
Data Reader
Data Writer
TopicAQoS
TopicBQoS
TopicCQoS
TopicDQoS
TopicTypeName
QoS
Topic types can be expressed using different syntaxes,
including IDL and ProtoBuf
Topic Type struct CarDynamics { string cid; long x; long y; float dx; long dy; } #pragma keylist CarDynamics cid
IDL
Topic types can be expressed using different syntaxes,
including IDL and ProtoBuf
Topic Type message CarDynamics { option (.omg.dds.type) = {name: "CarDynamics"}; required string cid = 0 [(.omg.dds.member).key = true]; required long x = 1; required long y = 2; required float dx = 3; required long dy = 4; }
ProtoBuf
Topic types can be expressed using different syntaxes,
including IDL and ProtoBuf
Topic Type class CarDynamics: constructor: (@cid, @x, @y, @dx, @dy) ->
CoffeeScript
Topic types can be expressed using different syntaxes,
including IDL and ProtoBuf
Topic Type public struct VehicleDynamics { public string cid { get; set; } public int x { get; set; } public int y { get; set; } public int dx { get; set; } public int dy { get; set; } public VehicleDynamics (string cid, int x, int y, int dx, int dy) { this.cid = cid; this.x = x; this.y = y; this.dx = dx; this.dy = dy; } }
C#
Vortex “knows” about application
data types and uses this
information provide type-
safety and content-based
routing
Content Awareness structCarDynamics{
@keystringcid;longx;longy;floatdx;longdy;}
cid x y dx dyGR 33N GO 167 240 45 0LO 00V IN 65 26 65 0AN 637 OS 32 853 0 50AB 123 CD 325 235 80 0
“dx>50ORdy>50”
Type
CarDynamics
cid x y dx dyLO 00V IN 65 26 65 0AB 123 CD 325 235 80 0
A collection of policies that control non-functional
properties such as reliability, persistence, temporal
constraints and priority
QoS HISTORY
LIFESPAN
DURABILITY
DEADLINE
LATENCY BUDGET
TRANSPORT PRIO
TIME-BASED FILTER
RESOURCE LIMITS
USER DATA
TOPIC DATA
GROUP DATA
OWENERSHIP
OWN. STRENGTH
LIVELINESS
ENTITY FACTORY
DW LIFECYCLE
DR LIFECYCLE
PRESENTATION
RELIABILITY
PARTITION
DEST. ORDER
RxO QoS Local QoS
QoS Policies controlling end-to-end properties follow a Request
vs. Offered
QoS Domain
Participant
DURABILITY
OWENERSHIP
DEADLINE
LATENCY BUDGET
LIVELINESS
RELIABILITY
DEST. ORDER
Publisher
DataWriter
PARTITION
DataReader
Subscriber
DomainParticipant
offered QoS
Topicwrites reads
Domain Idjoins joins
produces-in consumes-from
RxO QoS Policies
requested QoS
Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
Device implementations optimised for OT, IT and
consumer platforms
Native support for Cloud and Fog Computing Architectures
Available across IT, Consumer and OT platforms Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
Polyglot and Interoperable across Programming
Languages Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
Fully Independent of the Cloud Infrastructure
Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
Private Clouds
Native Integration with the hottest real-time analytics
platforms and CEP Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
High Performance
30 μs peer-to-peer latency
4.2M+ msgs/sec peer-to-peer throughput
Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
High Performance
4 μs fog/cloud routing latency
Device-2-DeviceDevice-2-Cloud
Fog-2-Cloud
Device-2-Fog
Cloud-2-Cloud
Fog-2-Fog
SecureData-Level security with
Pluggable Authentication Access Control and Crypto
Vortex device such are used to share data between different kinds of applications within a car
Café can be used in Android based infotainment
Lite in ECU, sensors and onboard analytics
Vortex Fog is used to transparently (for in car apps) decouple and control the data sharing within and across the car
Vortex Fog also helps defining security boundaries and policies
Vortex Fog efficiently and securely deals with cloud connectivity adapting traffic flows and protocols
Device-to-Cloud Communication
Cloud Analytics
Fog AnalyticsFog Analytics
Fog Analytics
Vortex Cloud efficiently and securely makes data available to any device at an Internet Scale
Device-to-Cloud Communication
Cloud Analytics
Fog AnalyticsFog Analytics
Fog Analytics
Cop
yrig
ht P
rism
Tech
, 201
4
• A JavaScript DDS API to provide HTML5/JavaScript applications with a high-level communication abstraction
• Vortex Web exploits HTML5 features, such as web-sockets and web-workers, to provide time and space efficient Web-App to Cloud communication
Vortex Web
DDS#API JavaScript
Browser#/#Node.js
CoffeeScript
Cop
yrig
ht P
rism
Tech
, 201
4
Client Side (dds.js): JavaScript CoffeeScript and .NET API for accessing DDS abstractions
Server Side (vortex-web): A Router that transparently bridges data between matching DDS entities, e.g. Browser-2-Browser, DDS-2-Browser and Browser-2-DDS
Vortex Web
TopicA
TopicB
TopicC
TopicDQoS
QoS
QoS
QoSData
Reader
Data Reader
Data Writer
Data Writer
dds.js
dds.js
v-web
v-web
Cop
yrig
ht P
rism
Tech
, 201
4Vortex-Web takes advantage of HTML5 WebSockets as well as Web Workers
WebSockets are used for both the control as well as the data plane
Web Workers are used to decouple I/O from processing (recall that a JS context is single-threaded)
Client-Side Architecture / JS
Cop
yrig
ht P
rism
Tech
, 201
4
JS-Client ArchitectureControl-Link.js
Send-Link.js
Recv-Link.js
dds-runtime.jsdds.js
mainworker(orwindowcontext)
worker
worker
worker
worker
Vortex-WebServer
control-protocol
data(frombrowser)
data(
tobro
wser)
Cop
yrig
ht P
rism
Tech
, 201
4
The .NET client for Vortex-Web takes advantage of the async / await support for providing a lightweight, scalable and efficient client API.
Independent WebSockets are used for both the control and the data plane
Client-Side Architecture / .NET
Cop
yrig
ht P
rism
Tech
, 201
4
.Net Client Architecture
vortex.web.sharp
Vortex-WebServer
control-protocol
data(frombrowser)
data(tobrowser)
Cop
yrig
ht P
rism
Tech
, 201
4
Vortex-Web can be deployed to simply provide access to a “regular” DDS system or to extend Vortex-Cloud with JavaScript / pure .Net support
In general, you should think of Vortex-Web as an add-on to either a regular or a Vortex-Cloud DDS system
Vortex-Web takes advantage of DDS to support fault-tolerance and load-balancing
Vortex Web Deployment
Cop
yrig
ht P
rism
Tech
, 201
4
Multiple instances can be deployed on a single system to provide fault-tolerance as well as to help in partitioning the load
The switch-over between instances is dealt-with by the client library
Traditional System Deployment
TopicA
TopicB
TopicC
TopicDQoS
QoS
QoS
QoSData
Reader
Data Reader
Data Writer
Data Writer
dds.js
dds.js
v-web
v-web
Cop
yrig
ht P
rism
Tech
, 201
4
Multiple instances can be deployed on the same IaaS platform sa Vortex-Cloud provide fault-tolerance as well as to help in partitioning the front-end load
The switch-over between instances is dealt-with by the dds.js library
Cloud Based Deployment
VORTEXCloud
IaaSserver-side
dds.jsdds.js
Cop
yrig
ht P
rism
Tech
, 201
4
Runtime
runtime = new dds.runtime.Runtime();runtime.connect(server, authToken);
CoffeeScript
Example:
runtime = new dds.runtime.Runtime()runtime.connect(“ws://88.77.66.55:9876”, “albator:corsaire”);
Cop
yrig
ht P
rism
Tech
, 201
4
Topic
cell = new dds.Topic(0, 'Cell', ‘com.activefloor.Cell')runtime.registerTopic(cell)
post = new dds.Topic(0, 'Post')runtime.registerTopic(post)
myTopic = new dds.Topic(domainID, topicName, topicType)runtime.registerTopic(myTopic)
CoffeeScript
Example:
Cop
yrig
ht P
rism
Tech
, 201
4
DataWriter
dw = new dds.DataWriter(runtime, topic, qos)
post = {}post.name = “kydos”post.msg = “having fun with Vortex Web”
dw.write(post)
dw = new dds.DataWriter(runtime, topic, qos)
CoffeeScript
Example:
Cop
yrig
ht P
rism
Tech
, 201
4
DataReader
dr = new dds.DataReader(runtime, topic, qos)
dr = new dds.DataReader(runtime, topic, qos)
CoffeeScript
Example:
Cop
yrig
ht P
rism
Tech
, 201
4
A DataReader can be bound to a user provided function that will handle incoming data or to a cache
Notice, that as you are in control of how data-readers are bound to cache you can be very creative
Binding a DataReader
Cop
yrig
ht P
rism
Tech
, 201
4
Binding to User Function
dr.addListener((s) -> console.log(JSON.stringify(s)))
dr.addListener(f)CoffeeScript
Example:
Cop
yrig
ht P
rism
Tech
, 201
4
Binding to a Cache
// BindingbindCell = dds.bind((s) -> s.x + “-” + s.y)ccache = new DataCache(historyDepth)bindCell(ccache, cdr)
// Working with the Cache: Compute number of active cellsactiveCells = ccache.map((c) -> if (c.pressure > p0) then 1 else 0).fold(0)((a, c) -> a + c)
cache = new DataCache(historyDepth)bind(keyMapper)(dr, cache)
CoffeeScript
Example:
Cop
yrig
ht P
rism
Tech
, 201
4
DataCache Operations
# Writes a data sample into the cache corresponding to the key k write: (k, data)
# Returns a list representing the content of the cache ordered by key.read()
# Returns a list representing the last sample for each keyreadLast()
# Returns a list representing the content of the cache ordered by key. # The data is actually removed from the cache.take()
# Returns a list representing the last sample for each key# The data is actually removed from the cache.takeLast()
Cop
yrig
ht P
rism
Tech
, 201
4
DataCache Operations
# Returns a list representing the content of the cache that matches for given predicate.# The data is actually removed from the cache.takeWithFilter(p)
# Returns Some(v) if a value associated to the key k exists. Otherwise it returns Noneget: (k)
# Returns Some(v) if a value associated to the key k exists. Otherwise it returns f()getOrElse(k, f)
# Clear the content of the cache.clear()
Cop
yrig
ht P
rism
Tech
, 201
4
DataCache Operations
# Returns a new DataCache whose content is obtained by applying the function# f to each element of the cachemap(f)
# Executes the function f on each element of the cacheforEach(f)
# Executes the function f only on the first n samples associated with a keyforEachN(f, n) # Returns the element of the cache that match the predicate pfilter(p)
# Returns the element of the cache that do not match the predicate pfilterNot(p)
Cop
yrig
ht P
rism
Tech
, 201
4
DataCache Operations
# Folds the content of the data cache using z as “zero” for the folding function f# For instance, assuming that the operator “+” is defined for the elements of # the cache, then you could compute the sum of all elements doing:# c.fold(0)((a, v) -> a + v)# the product by: # c.fold(1)((a, v) -> a * v)# a comma separated string representation of the content:# c.fold(“”)(a, v) -> a + “, “ + vfold(z)(f)
# Register a listener l to be notified whenever data which matches a # predicate p is written into the cache. If no predicate is provided # then the listeners is always notified upon data insertion.addListener(l, p)
Cop
yrig
ht P
rism
Tech
, 201
4Let’s see the steps required to build a Web Chat that may look like this
But before let’s play with it a bit
Web Chat
http://demo.prismtech.com
Cop
yrig
ht P
rism
Tech
, 201
4
The Chat CoffeeScript#CreateusefulaliasforcoffezandjQueryroot=thisz_=coffez$=jQuery
server=“ws://demo-eu.prismtech.com:9999"
#TheposttypeusedbythechatapplicationclassPostconstructor:(@name,@msg)->
#Createtheruntimeruntime=newdds.runtime.Runtime()
#DefinethePosttopicusedtosendandreceivechatpostspostTopic=newdds.Topic(0,"Post")
#DefinetheQoSfortheDataReader/WriterdrQos=newdds.DataReaderQos(dds.Reliability.Reliable)dwQos=newdds.DataWriterQos(dds.Reliability.Reliable)
Cop
yrig
ht P
rism
Tech
, 201
4
The Chat CoffeeScriptpostReader=z_.NonepostWriter=z_.None
avatar="avatar"+Math.floor((Math.random()*10000)+1);
#AddposttothechatandformatittoshowitisfrommecreateMyPost=(post)->...
#AddposttothechatandformatittoshowitisfromotherscreateOtherPost=(post)->...
#AddposttothechatandformatittoshowitisfromothersprocessPost=()->msg=$("#ChatMessage").val()post=newPost(avatar,msg)#Publishthepost(noticethatpostWriterisanOptionMonad)#Takealookat(http://en.wikibooks.org/wiki/Haskell/Understanding_monads/Maybe)#or(http://www.scala-lang.org/api/2.11.0/index.html#scala.Option)postWriter.map((dw)->dw.write(post))$("#ChatMessageList").append(createMyPost(post))$("#ChatMessage").val("")
Cop
yrig
ht P
rism
Tech
, 201
4
The Chat CoffeeScript#Dealwithclickandkeysevents…
$("#ChatMessage").keyup((e)->if(e.keyCodeis13)thenprocessPost())
$("#SendMsgButton").click((evt)->console.log("SendButtonhasbeenclicked")processPost())
$("#SelectAvatarButton").click((evt)->s=$("#AvatarName").val()if(sisnt"")avatar=s)
Cop
yrig
ht P
rism
Tech
, 201
4
The Chat CoffeeScript#Handletheruntimeonconnecteventruntime.onconnect=()->#CreateDataReaderandDataWriterforourposts
runtime.registerTopic(postTopic)dr=newdds.DataReader(runtime,postTopic,drQos)dw=newdds.DataWriter(runtime,postTopic,dwQos)
#Registeralistenerwiththedatareadertopostmessages#inourchatdr.addListener((post)->if(post.nameisntavatar)$("#ChatMessageList").append(createOtherPost(post)))postReader=z_.Some(dr)postWriter=z_.Some(dw)
connectRuntime=()->$("#AvatarName").val(avatar)runtime.connect(server,"uid:pwd")
$(document).ready(()->connectRuntime())
Cop
yrig
ht P
rism
Tech
, 201
4Only ~10 lines code for implementing the communication required by a chat application!
Content filtering could be used to further simplify the application and reduce number of lines of code, i.e. avoid the check on the origin of the message to avoid duplicate posts
In Summary
Cop
yrig
ht P
rism
Tech
, 201
4
Very close to the JavaScript/CoffeScript API
Takes advantage of async /await
Pure .Net API without any native dependencies.
.NET API for Vortex Web
Cop
yrig
ht P
rism
Tech
, 201
4C# implementation of a Chat with a minimalistic GUI
GUI coded in GTKSharp
The same business logic could be targeted to Android / iOS using Xamarin Studio
.Net SharpChat
Cop
yrig
ht P
rism
Tech
, 201
4
Topic Types are defined in C#
The Post Type
public class Post { public string name { get; } public string msg { get; } public Post (string name, string msg) { this.name = name; this.msg = msg; } }
Cop
yrig
ht P
rism
Tech
, 201
4
.Net SharpChat
class MainClass { public static void Main (string[] args) { var user = args.Length > 0 ? args [0] : “anonymous”; var uri = args.Length > 1 ? args [0] : ”ws://localhost:9000”; var vortex = new VortexApp (user, uri); vortex.Run (); } }
class VortexApp { public DataWriter<Post> dw { get; set; } public DataReader<Post> dr { get; set; } private MainWindow win; public string user { get; } public string uri { get; } public VortexApp(string user, string uri) { this.user = user; this.uri = uri; } public async Task Init() { var auth = user + ":nopwd"; var v = new Vortex (0); await v.Connect (uri, auth); if (v.IsConnected) { var tname = "Post"; var post = await v.CreateTopic<Post> (tname); dr = await v.CreateDataReader<Post> (post); dw = await v.CreateDataWriter<Post> (post); } else Console.WriteLine ("Unable to connect to: " + uri); } public void Run () { Application.Init (); Init ().Wait (); win = new MainWindow (user, this.dw); win.Show (); dr.OnDataAvailable += (object sender, SampleData<Post> e) => { win.addPost(e.Data); } ; Application.Run (); } }
Listener are lambdas
Readers and Writers are strongly typed (but can do projections)
using System;using Gtk;using vortex.web;using sharpchat;public partial class MainWindow: Gtk.Window{ private DataWriter<Post> dw; private string user; […]
protected void onKeyReleaseEvent (object o, KeyReleaseEventArgs args) { var k = args.Event.Key; if (k == Gdk.Key.Return) { var rmsg = this.inputText.Buffer.Text; var msg = rmsg.Remove(rmsg.Length -1); dw.Write(new Post(this.user, msg)); this.inputText.Buffer.Clear (); } } private void appendToMessageBoard (string user, string msg) { var text = this.messageBoard.Buffer.Text + "\ n" + user + " >> " + msg; this.messageBoard.Buffer.Text = text; } public void addPost(Post p) { appendToMessageBoard (p.name, p.msg); } }
Async Write
Vortex integrates with Freeboard and makes it supersimple to create dashboards from data coming from Mobile, Web, Embedded, and Cloud apps
Vortex Cafe can be used to develop android applications in Java
The .Net client for Vortex-Web can be used to along with Xamain to develop native applications for Android , iOS and Windows Phone
The JS client for Vortex-Web can be used to develop native applications with Apache Cordova.
Cop
yrig
ht P
rism
Tech
, 201
4
Pure Java version of Vortex targeting JVM and embedded JVMs
DDSI Protocol Stack optimised for mobility and Android OS
Only DDS on the market designed and Engineered for Android
Vortex Café
J2SE
DDSI$$(Optimised*for*Mobility)*
DDS$API Java Scala JavaScript
Cop
yrig
ht P
rism
Tech
, 201
4To learn how to write an Android Application that uses Vortex Café we’ll develop a very simple Chat
To keep things simple this chat will have a single “chat room”
DDS Chat for Android
Cop
yrig
ht P
rism
Tech
, 201
4
Our Chat application will have a very simple architecture with simply one Activity that will take care of:
- Sending Posts into the ChatRoom
- Displaying Posts in the room since when we joined
In terms of information modelling, we’ll have a single topic representing the user post
Step 1: Architecture
structPost{stringname;stringmsg;};#pragmakeylistPostname
Cop
yrig
ht P
rism
Tech
, 201
4
Creating DDS entities, such as DomainParticipants, DataReaders and DataWriters involves network communication, such as discovery information
In addition when an a DDS entity is destroyed it looses its state
As such, tying the life-cycle of DDS entities to activities should be done with great care
Step 2: Lifecycle Management[1/2]
Cop
yrig
ht P
rism
Tech
, 201
4
In general, it is a better idea to tie the life-cycle of DDS entities to the Application as opposed to Activities
In some cases, it may make sense to tie the life-cycle of DataReaders/DataWriters to that of the activity that relies on them -- Usually this makes sense for activities that are “one-off”
Step 2: Lifecycle Management[2/2]
Cop
yrig
ht P
rism
Tech
, 201
4
Applicationpublic class ChatApplication extends Application {
DataReader<Post> dr; DataWriter <Post> dw; DomainParticipant dp;
@Override public void onCreate() { super.onCreate(); // This should be defined via a resource -- but for a small // demo that’s OK.
System.setProperty(ServiceEnvironment.IMPLEMENTATION_CLASS_NAME_PROPERTY, "com.prismtech.cafe.core.ServiceEnvironmentImpl"); ServiceEnvironment env = ServiceEnvironment.createInstance( ChatApplication.class.getClassLoader()); DomainParticipantFactory dpf = DomainParticipantFactory.getInstance(env);
dp = dpf.createParticipant(0); Topic<Post> topic = dp.createTopic("Post",Post.class); Publisher pub = dp.createPublisher(); Subscriber sub = dp.createSubscriber();
dw = pub.createDataWriter(topic); dr = sub.createDataReader(topic); }
Cop
yrig
ht P
rism
Tech
, 201
4
Application
public DataReader<Post> reader() { return this.dr; }
public DataWriter<Post> writer() { return this.dw; }
@Override public void onTerminate() { super.onTerminate(); this.dp.close(); }}
Cop
yrig
ht P
rism
Tech
, 201
4
Manifest...
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="ChatApplication" > <activity android:name=“com.ddschat.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity></application>
Cop
yrig
ht P
rism
Tech
, 201
4
When using Vortex Café you need to grant the proper permissions for networking:
More Manifest...
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
Cop
yrig
ht P
rism
Tech
, 201
4
Activity GUI<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >
<TextView android:id="@+id/chatMessages" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/chat_msgs" android:visibility="gone" android:background="#666" android:textColor="#fff" android:paddingLeft="5dp" /> <ListView android:id="@+id/messageList" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" />
Cop
yrig
ht P
rism
Tech
, 201
4
Activity GUI
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" >
<EditText android:id="@+id/message" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:hint="@string/edit_message" />
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="sendChatMessage" android:text="@string/button_send" /> </LinearLayout>
</LinearLayout>
Cop
yrig
ht P
rism
Tech
, 201
4
Activity 1 2 public class MainActivity extends Activity { 3 4 private static final String TAG = "ChatMainActivity"; 5 private final Handler handler = new Handler(); 6 private ArrayAdapter<String> chatMessages; 7 8 public class ChatMessageListener extends ChatMessageDataListener { 9 // ...10 }11 12 @Override13 protected void onCreate(Bundle savedInstanceState) {14 super.onCreate(savedInstanceState);15 setContentView(R.layout.activity_main);16 chatMessages = new ArrayAdapter<String>(this, R.layout.messages);17 chatMessages.add("Welcome to the DDS Chat Room");18 ListView mview = (ListView) findViewById(R.id.messageList);19 mview.setAdapter(chatMessages);20 ChatApplication app = (ChatApplication) getApplication();21 22 app.reader().setListener(new ChatMessageListener());23 24 }25
Cop
yrig
ht P
rism
Tech
, 201
4
Activity
25 26 @Override27 public boolean onCreateOptionsMenu(Menu menu) {28 // Inflate the menu; this adds items to the action bar if it is present.29 getMenuInflater().inflate(R.menu.main, menu);30 return true;31 }
Cop
yrig
ht P
rism
Tech
, 201
4
Activity
32 33 public void sendChatMessage(View view) {34 EditText editText = (EditText) findViewById(R.id.message);35 String msg = editText.getText().toString();36 editText.setText("");37 // chatMessages.add(msg);38 ChatApplication app = (ChatApplication) getApplication();39 try {40 Log.i(TAG, ">>> Sending data " + msg);41 app.writer().write(new Post(usr, msg));42 } catch (TimeoutException te) {43 }44 }45 46 }
Cop
yrig
ht P
rism
Tech
, 201
4
Receiving data is a bit trickier since in Android only the thread that runs an activity has the right to change the UI
This means, that from a DDS listener it is not possible to change an the UI directly!
The solution is to use an Android Handlerto which we can post Runnable to be executed by the activity thread
Let’s see how this works...
Receiving Data
Cop
yrig
ht P
rism
Tech
, 201
4
DDS Listener & Android Handler
1 public class ChatMessageListener extends ChatMessageDataListener { 2 3 private DataReader<Post> dr; 4 5 public ChatMessageListener() { 6 ChatApplication app = (ChatApplication) getApplication(); 7 dr = app.reader(); 8 } 9
Cop
yrig
ht P
rism
Tech
, 201
4
DDS Listener & Android Handler10 @Override11 public void onDataAvailable(DataAvailableEvent<Post> dae) {12 final Iterator<Post> i = dr.read();13 14 Log.i(TAG, ">>> DataReaderListener.onDataAvailable");15 if (i.hasNext()) {16 Runnable dispatcher = new Runnable() {17 public void run() {18 while (i.hasNext()) {19 Sample<Post> s = i.next();20 21 if (s.getSampleState() == SampleState.NOT_READ) {22 Post cm = s.getData();23 chatMessages.add(cm.name + " > " + cm.msg);24 }25 }26 }27 };28 handler.post(dispatcher);29 }30 }31 }