Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Connected Mobile and Web Applications with PrismTech Vortex Data Sharing Platform

805 views

Published on

The widespread availability of high-end mobile devices such as smart-phones, tablets and phablets, along with the availability of browser enabled devices, has imposed these platforms as one of the main targets for user interfaces. As a result mobile and web applications need now to be easily connected to the rest of the system. This presentation will showcase how the PrismTech Vortex Data Sharing Platform can be effectively and productively used to create connected mobile and web applications, and take you through the steps required to use Vortex in mobile and web applications.

Published in: Software
  • Be the first to comment

Connected Mobile and Web Applications with PrismTech Vortex Data Sharing Platform

  1. 1. Connected Mobile and Web Applications with Angelo Corsaro, PhD Chief Technology Officer angelo.corsaro@prismtech.com
  2. 2. Connectivity
  3. 3. IaaS analytics operational systems information systems mobile desktop web embedded fog computing integration
  4. 4. Vortex “Connectivity” Model
  5. 5. 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 TopicA QoS TopicB QoS TopicC QoS TopicD QoS Global Data Space
  6. 6. 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 TopicA QoS TopicB QoS TopicC QoS TopicD QoS Dynamic Discovery
  7. 7. 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 TopicA QoS TopicB QoS TopicC QoS TopicD QoS QoS - Enabled
  8. 8. No single point of failure or bottleneck Decentralised Data Space Data Writer Data Writer Data Writer Data Reader Data Reader Data Reader Data Writer TopicA QoS TopicB QoS TopicC QoS TopicD QoS TopicD QoS TopicD QoS TopicA QoS
  9. 9. Connectivity is dynamically adapted to chose the most effective way of sharing data Adaptive Connectivity Data Writer Data Writer Data Writer Data Reader Data Reader Data Reader Data Writer TopicA QoS TopicB QoS TopicC QoS TopicD QoS TopicD QoS TopicD QoS TopicA QoS The communication between the DataWriter and matching DataReaders can be peer-to- peer exploiting UDP/IP (Unicast and Multicast)or TCP/IP The communication between the DataWriter and matching DataReaders can be “brokered” but still exploiting UDP/IP (Unicast and Multicast)or TCP/IP
  10. 10. A domain-wide information’s class A Topic defined by means of a <name, type, qos> Topic DDS Global Data Space ... Data Writer Data Writer Data Writer Data Reader Data Reader Data Reader Data Reader Data Writer TopicA QoS TopicB QoS TopicC QoS TopicD QoS Topic Type Name QoS
  11. 11. 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
  12. 12. 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
  13. 13. Topic types can be expressed using different syntaxes, including IDL and ProtoBuf Topic Type class CarDynamics: constructor: (@cid, @x, @y, @dx, @dy) -> CoffeeScript
  14. 14. 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#
  15. 15. Vortex “knows” about application data types and uses this information provide type- safety and content-based routing Content Awareness struct CarDynamics { @key string cid; long x; long y; float dx; long dy; } cid x y dx dy GR 33N GO 167 240 45 0 LO 00V IN 65 26 65 0 AN 637 OS 32 853 0 50 AB 123 CD 325 235 80 0 “dx > 50 OR dy > 50” Type CarDynamics cid x y dx dy LO 00V IN 65 26 65 0 AB 123 CD 325 235 80 0
  16. 16. 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
  17. 17. 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 Domain Participant offered QoS Topic writes reads Domain Id joins joins produces-in consumes-from RxO QoS Policies requested QoS
  18. 18. Vortex Technology Stack
  19. 19. 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
  20. 20. Available across IT, Consumer and OT platforms Device-2-DeviceDevice-2-Cloud Fog-2-Cloud Device-2-Fog Cloud-2-Cloud Fog-2-Fog
  21. 21. Polyglot and Interoperable across Programming Languages Device-2-DeviceDevice-2-Cloud Fog-2-Cloud Device-2-Fog Cloud-2-Cloud Fog-2-Fog
  22. 22. 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
  23. 23. 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
  24. 24. 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
  25. 25. 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
  26. 26. Device-2-DeviceDevice-2-Cloud Fog-2-Cloud Device-2-Fog Cloud-2-Cloud Fog-2-Fog Secure Data-Level security with Pluggable Authentication Access Control and Crypto
  27. 27. Real-World Example
  28. 28. 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
  29. 29. 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
  30. 30. Vortex Fog efficiently and securely deals with car to car communication
  31. 31. Vortex Fog efficiently and securely deals with cloud connectivity adapting traffic flows and protocols Device-to-Cloud Communication Cloud Analytics Fog Analytics Fog Analytics Fog Analytics
  32. 32. Vortex Cloud efficiently and securely makes data available to any device at an Internet Scale Device-to-Cloud Communication Cloud Analytics Fog Analytics Fog Analytics Fog Analytics
  33. 33. Web and Mobile in Vortex
  34. 34. CopyrightPrismTech,2014 • 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
  35. 35. CopyrightPrismTech,2014 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 TopicD QoS QoS QoS QoS Data Reader Data Reader Data Writer Data Writer dds.js dds.js v-web v-web
  36. 36. CopyrightPrismTech,2014 Vortex-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
  37. 37. CopyrightPrismTech,2014 JS-Client Architecture Control-Link.js Send-Link.js Recv-Link.js dds-runtime.js dds.js main worker (or window context) worker worker worker worker Vortex-Web Server control-protocol data (from browser) data (to browser)
  38. 38. CopyrightPrismTech,2014 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
  39. 39. CopyrightPrismTech,2014 .Net Client Architecture vortex.web.sharp Vortex-Web Server control-protocol data (from browser) data (to browser)
  40. 40. CopyrightPrismTech,2014 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
  41. 41. CopyrightPrismTech,2014 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 TopicD QoS QoS QoS QoS Data Reader Data Reader Data Writer Data Writer dds.js dds.js v-web v-web
  42. 42. CopyrightPrismTech,2014 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 VORTEX Cloud IaaSserver-side dds.jsdds.js
  43. 43. dds.js Overview
  44. 44. CopyrightPrismTech,2014 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”);
  45. 45. CopyrightPrismTech,2014 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:
  46. 46. CopyrightPrismTech,2014 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:
  47. 47. CopyrightPrismTech,2014 DataReader dr = new dds.DataReader(runtime, topic, qos) dr = new dds.DataReader(runtime, topic, qos) CoffeeScript Example:
  48. 48. CopyrightPrismTech,2014 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
  49. 49. CopyrightPrismTech,2014 Binding to User Function dr.addListener((s) -> console.log(JSON.stringify(s))) dr.addListener(f) CoffeeScript Example:
  50. 50. CopyrightPrismTech,2014 Binding to a Cache // Binding bindCell = dds.bind((s) -> s.x + “-” + s.y) ccache = new DataCache(historyDepth) bindCell(ccache, cdr) // Working with the Cache: Compute number of active cells activeCells = 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:
  51. 51. CopyrightPrismTech,2014 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 key readLast() # 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()
  52. 52. CopyrightPrismTech,2014 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 None get: (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()
  53. 53. CopyrightPrismTech,2014 DataCache Operations # Returns a new DataCache whose content is obtained by applying the function # f to each element of the cache map(f) # Executes the function f on each element of the cache forEach(f) # Executes the function f only on the first n samples associated with a key forEachN(f, n) # Returns the element of the cache that match the predicate p filter(p) # Returns the element of the cache that do not match the predicate p filterNot(p)
  54. 54. CopyrightPrismTech,2014 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 + “, “ + v fold(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)
  55. 55. hacking time
  56. 56. CopyrightPrismTech,2014 Let’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
  57. 57. CopyrightPrismTech,2014 The Chat CoffeeScript # Create useful alias for coffez and jQuery root = this z_ = coffez $ = jQuery server = “ws://demo-eu.prismtech.com:9999" # The post type used by the chat application class Post constructor: (@name, @msg) -> # Create the runtime runtime = new dds.runtime.Runtime() # Define the Post topic used to send and receive chat posts postTopic = new dds.Topic(0, "Post") # Define the QoS for the DataReader/Writer drQos = new dds.DataReaderQos(dds.Reliability.Reliable) dwQos = new dds.DataWriterQos(dds.Reliability.Reliable)
  58. 58. CopyrightPrismTech,2014 The Chat CoffeeScriptpostReader = z_.None postWriter = z_.None avatar = "avatar" + Math.floor((Math.random() * 10000) + 1); # Add post to the chat and format it to show it is from me createMyPost = (post) -> ... # Add post to the chat and format it to show it is from others createOtherPost = (post) -> ... # Add post to the chat and format it to show it is from others processPost = () -> msg = $("#ChatMessage").val() post = new Post(avatar, msg) # Publish the post (notice that postWriter is an Option Monad) # Take a look at (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("")
  59. 59. CopyrightPrismTech,2014 The Chat CoffeeScript # Deal with click and keys events… $("#ChatMessage").keyup( (e) -> if(e.keyCode is 13) then processPost() ) $("#SendMsgButton").click( (evt) -> console.log("Send Button has been clicked") processPost() ) $("#SelectAvatarButton").click( (evt) -> s = $("#AvatarName").val() if (s isnt "") avatar = s )
  60. 60. CopyrightPrismTech,2014 The Chat CoffeeScript # Handle the runtime onconnect event runtime.onconnect = () -> # Create DataReader and DataWriter for our posts runtime.registerTopic (postTopic) dr = new dds.DataReader(runtime, postTopic, drQos) dw = new dds.DataWriter(runtime, postTopic, dwQos) # Register a listener with the data reader to post messages # in our chat dr.addListener( (post) -> if (post.name isnt avatar) $("#ChatMessageList").append(createOtherPost(post))) postReader = z_.Some(dr) postWriter = z_.Some(dw) connectRuntime = () -> $("#AvatarName").val(avatar) runtime.connect(server, "uid:pwd") $(document).ready(() -> connectRuntime())
  61. 61. CopyrightPrismTech,2014 Only ~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
  62. 62. some hacking. . .
  63. 63. CopyrightPrismTech,2014 Very close to the JavaScript/CoffeScript API Takes advantage of async /await Pure .Net API without any native dependencies. .NET API for Vortex Web
  64. 64. CopyrightPrismTech,2014 C# 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
  65. 65. CopyrightPrismTech,2014 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;
 }
 }

  66. 66. CopyrightPrismTech,2014 .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 ();
 }
 }

  67. 67. 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)
  68. 68. 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 + " >> " + ms this.messageBoard.Buffer.Text = text;
 }
 public void addPost(Post p) {
 appendToMessageBoard (p.name, p.msg);
 }
 } Async Write
  69. 69. Dashboards
  70. 70. Vortex integrates with Freeboard and makes it supersimple to create dashboards from data coming from Mobile, Web, Embedded, and Cloud apps
  71. 71. Native Mobile Apps
  72. 72. 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.
  73. 73. Vortex Cafe
  74. 74. CopyrightPrismTech,2014 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
  75. 75. Android Chat
  76. 76. CopyrightPrismTech,2014 To 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
  77. 77. CopyrightPrismTech,2014 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 struct Post { string name; string msg; }; #pragma keylist Post name
  78. 78. CopyrightPrismTech,2014 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]
  79. 79. CopyrightPrismTech,2014 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]
  80. 80. CopyrightPrismTech,2014 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); }
  81. 81. CopyrightPrismTech,2014 Application public DataReader<Post> reader() { return this.dr; } public DataWriter<Post> writer() { return this.dw; } @Override public void onTerminate() { super.onTerminate(); this.dp.close(); } }
  82. 82. CopyrightPrismTech,2014 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>
  83. 83. CopyrightPrismTech,2014 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"/>
  84. 84. CopyrightPrismTech,2014 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" />
  85. 85. CopyrightPrismTech,2014 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>
  86. 86. CopyrightPrismTech,2014 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 @Override 13 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
  87. 87. CopyrightPrismTech,2014 Activity 25 26 @Override 27 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 }
  88. 88. CopyrightPrismTech,2014 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 }
  89. 89. CopyrightPrismTech,2014 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 Handler to which we can post Runnable to be executed by the activity thread Let’s see how this works... Receiving Data
  90. 90. CopyrightPrismTech,2014 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
  91. 91. CopyrightPrismTech,2014 DDS Listener & Android Handler 10 @Override 11 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 }
  92. 92. Live Demo
  93. 93. Putting it All Together
  94. 94. CopyrightPrismTech,2015

×