Connected world in android Local data sharing and service discovery Intro, welcome and other PMD things Presented by: Kaushal Dhruw Naval Barthwal
About PMD Started in August 2013 “Increase awareness of fast growing mobile technology among Developers” Currently has 3000+ members 21 meetups so far
Team Ashutosh Tarun Arvind Kaushal Suyash Vijendra Talentica Mobile Community
Agenda Network interfaces. Basic socket communication. Network service discovery. Wi-Fi direct. Wi-Fi direct service discovery. Bluetooth low energy (BLE). Demos (wherever needed)
Network interfaces Introduction
Network interface A Network interface is a point of interconnection between a device and a public or private network. It can be a hardware (Network interface card). Or can be implemented in software. Some network interfaces: wlan: wireless networking interface. lo: loopback interface (localhost, usually 127.0.0.1). rmnet: usually associated with mobile data and USB tethering. p2p: a peer-to-peer interface. eth, en: Ethernet card interface. dummy: alternative for loopback interfaces. NetworkInterface.getNetworkInterfaces() //gets list of all available network interfaces Why it is important to know about network interfaces? Show ifconfig adb command And java program
Network interface methods isUp(): Whether the network interface is up and running. isVirtual(): Whether the network interface is virtual or sub-interface. getSubInterfaces(): gets all the sub interfaces bound to this network interface (like eth0:1 for eth0) supportsMulticast(): checks multicast support. getInetAddresses(): get all the addresses bound to this network interface. getHardwareAddress(): usually MAC. getByName(): getByInetAddress(): getByIndex(): Show ifconfig adb command And java program
Network interface selection When a socket is created it automatically determines which network (that is currently up and running) to use. Most of the times you will not have to worry about the network interface. When you want to use the address of a particular network interface, use the get methods discussed in previous slide. To listen to all the network interfaces, bind your socket to “0.0.0.0” Loopback and dummy interfaces are used for localhost connection testing. use adb shell ifconfig to list all available network interfaces.
Agenda Network interfaces. Basic socket communication. Network service discovery. Wi-Fi direct. Wi-Fi direct service discovery. Bluetooth low energy (BLE). Demos (wherever needed)
Basic socket communication Generic java not specific to android
Basic socket communication A socket is basically an end point for two-way communication link between two devices. In a typical client-server architecture. Server runs on a specific computer and has a socket that is bound to a specific port, the server listens for a client to make connection request in that socket. Client knows the host name of server and port it is listening on. The client system usually assigns a port to rendezvous with server’s machine and port. Client receives confirmation of connection acceptance and can use the socket for communicating with server. Listening on a port for client requests is done via ServerSocket. A ServerSocket class provides a system independent implementation of the server side of client/server socket connection. ServerSocket serverSocket = new ServerSocket(port); Socket s = serverSocket.accept();
Basic socket communication contd…
Steps involved in socket communication Create a ServerSocket. This socket waits for a connection from a client on a specified port and blocks until it happens, so do this in a background thread. Create a client Socket. The client uses the IP address and port of the server socket to connect to the server device. Send data from the client to the server. When the client socket successfully connects to the server socket, you can send data from the client to the server with byte streams. The server socket waits for a client connection (with the accept() method). This call blocks until a client connects, so call this in another thread. When a connection happens, the server device can receive the data from the client. And carry out any actions with this data, such as saving it to a file or presenting it to the user.
Client/server sockets ServerSocket mServer = new ServerSocket(mPort); While(true){ Socket s = mServer.accept(); //process s and streams and return response if required } socket = new Socket(host, port); OutputStream outputStream = socket.getOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(outputStream); oos.writeObject(transferObject); oos.close(); Question about port sharing between android devices. Why port number should not be prefixed? mPort = (new ServerSocket(0)).getLocalPort()
Use case we are solving (Local chat) Device 1 Device 2 Share files & Send chat Receive chat and file from other devices Share files & Send chat Receive chat and file from other devices
Agenda Network interfaces. Basic socket communication. Network service discovery. Wi-Fi direct. Wi-Fi direct service discovery. Bluetooth low energy (BLE). Demos (wherever needed)
Network service discovery (NSD) Discover services and devices in the same network
Network service discover (NSD) android.net.nsd.* package is used. It helps with many use cases like file sharing, multi-player games etc. Android network service discovery allows your app to identify other devices in the same network that support the services your app requests. NSD allows us to register our service(s) on the network, discover it, and connect with it. Important classes: NsdManager NsdServiceInfo Although internet is not used, INTERNET permission is required for socket communication. Define service
Basic steps in NSD
NSD Service registration Creating NsdServiceInfo Object serviceInfo.getPort() will not give the port info unless resolved Service type = “_<protocol>._<transportlayer>” International Assigned Numbers Authority (IANA) http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
NSD Service registration Listener Explain error code = 2 (Wi-Fi is not on or not connected) Wi-Fi is either off or not connected
NSD Service discovery Single service discovery method with discovery listener call back
NSD Service discovery Listener Now after the services are discovered, either show it in UI or resolve it to get entire service information
Resolving discovered NSD service NsdManager.ResolveListener Note**: Do not forget to stop discovery and unregister service when app closes
NSD Demo plus code walkthrough
Agenda Network interfaces. Basic socket communication. Network service discovery. Wi-Fi direct. Wi-Fi direct service discovery. Bluetooth low energy (BLE). Demos (wherever needed)
Wi-Fi direct Connect with devices in vicinity (Wi-Fi p2p in android)
Wi-Fi direct Wi-Fi direct is a Wi-Fi certified standard enabling devices to connect with each other without requiring a wireless access point. Using this devices can communicate with each other at typical Wi-Fi speeds, unlike ad-hoc wireless connections (which allows two or more devices to connect and communicate, and has a limit of 11Mbps). And Wi-Fi direct has much simpler setup that ad-hoc network. Wi-Fi direct assigns each member a limited access point (if it is Wi-Fi direct enabled). Wi-Fi direct uses WPS and WPA2 to prevent unauthorized access and keep communications private.
Wi-Fi direct contd… Wi-Fi direct allows devices to connect to each other and form groups. Not only one-to-one, but also one-to-many. Compatible devices negotiate their roles in the connection: One of these assumes role of a traditional access point. Called Group Owner (GO). Other devices including non-Wi-Fi direct devices connect to the Group owner or Access point as P2P clients. Any P2P device can assume the role of a Group owner and P2P client. The purpose of role negotiation is to determine which of the peer devices will exchange group characteristics (like operating channel, WPS configuration, is the group persistent etc.). Devices can communicate their willingness to become group owner with the GO intent attribute (0-15). After the role negotiation a confirmation is sent and devices move to their specified roles. GO starts operating in Access point mode.
Wi-Fi direct and android Android’s Wi-Fi P2P framework complies with the Wi-Fi direct certification program. It allows devices running android 4.0+ (API 14+) with appropriate hardware to connect easily without an intermediate access point. Android Wi-Fi P2P API consists of: Methods that allows us to discover, request and connect to peers (android.net.wifi.p2p.WifiP2pManager). Listeners that notifies us of success and failure of WifiP2pmanager’s method calls. Intents to notify specific events, such as new peer joined, connection dropped etc. (like WIFI_P2P_PEERS_CHANGED_ACTION and WIFI_P2P_CONNECTION_CHANGED_ACTION) A single call to WifiP2pManager’s discover peers is enough for Wi-Fi direct peer discovery. Connection however with Wi-Fi direct group requires user’s consent. This is unlike NSD.
Wi-Fi direct – Permissions
Wi-Fi direct – starting peer discovery We will discuss important methods of WifiP2pManager in coming slides
Wi-Fi direct – getting peer list This broadcast receiver needs to be registered dynamically. It notifies when peer list has changed so peer list can be requested from WifiP2pManager
Wi-Fi direct – getting peer list contd… When WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION is received in the broadcast receiver, peer list can be requested. With WifiP2pManager.requestPeers() method. Gives a list of all available peers, not just new ones. So clear old list and repopulate with new list Take a look at WifiP2pDeviceList, WifiP2pDevice & WifiP2pManager
Wi-Fi direct – WifiP2pDevice Important method in WifiP2pDeviceList is getDeviceList() which gives a collection of WifiP2pDevice, it has the following important fields There you go, a list of peer’s is available
Wi-Fi direct – Connecting to a peer Once a peer is discovered, connection request can be sent This sends a connection request to the peer device. Invitation request to peer device. User has to manually accept the request.
Connecting to a peer – WifiP2pInfo Once connection is successful a connection info request can be issued via WifiP2pManager. Which send callback to WifiP2pManager.ConnectionInfoListener. It has only one method described below: WifiP2pInfo From here onwards we can continue our socket communication.
WifiP2pManager - createGroup This method is to support older devices that do not support Wi-Fi direct. It creates an Access point which non-Wi-Fi direct can connect to (like a regular Wi-Fi), and continue communication. The device that calls this method must support Wi-Fi direct. The method creates a p2p group with the current device as its group owner. In addition to hosting an access point, it also allows other Wi-Fi direct enabled devices to connect with it in regular fashion. Connecting with a Wi-Fi programmatically (if SSID and password are known): This is important because it can connect to both Wi-Fi direct and non-Wi-Fi direct legacy devices (those connect to Group owner as regular access point) The network name starts with “Direct-xy”
Wi-Fi direct demo Plus code walkthrough for our use case
Agenda Network interfaces. Basic socket communication. Network service discovery. Wi-Fi direct. Wi-Fi direct service discovery. Bluetooth low energy (BLE). Demos (wherever needed)
Wi-Fi direct service discovery Discover devices and services in vicinity (Irrespective of device connection status)
Wi-Fi direct service discovery Similar function as NSD. Similar code like Wi-Fi direct. Kind of like a combination of both. And also more complex than BOTH. Same classes and listeners are used as in Wi-Fi direct. Here we find services in nearby devices. (Can work for devices in the same network too). In this WifiP2pManager’s addLocalService() method is used. There is an additional option for adding key value pairs in a map (100-200 bytes). This map can be received with service discovery. Any small additional data can be shared with service (like device’s port it is listening to, name, device info etc.) This is used in nearby device discovery such as printers and other smart devices. This has a wide variety of applications. Right from xbox controllers to wireless printers to IOT systems
Wi-Fi direct adding local service WifiP2pManager’s addLocalService(): WifiP2pServiceInfo is a class for storing service information that is advertised over a Wi- Fi peer-to-peer setup. It has two direct subclasses. Both are bonjour service info: WifiP2pDnsSdServiceInfo – domain name system service discovery (service info) WifiP2pUpnpServiceInfo – Universal plug and play (service info) For our use case we will be using the former in place of WifiP2pServiceInfo. With DNS- SD service info we have an option to advertise additional data (relatively small 100-200 bytes). For this use case we will advertise port information. Once the port and IP information is determined, rest of the work is similar (socket programming). WifiP2pServiceInfo is a class for storing service information that is advertised over a Wi-Fi peer-to-peer setup. Universal Plug and Play (UPnP) is a set of networking protocols that permits networked devices, such as personal computers, printers, Internet gateways, Wi-Fi access points and mobile devices to seamlessly discover each other's presence on the network and establish functional network services for data sharing, communications, and entertainment. UPnP is intended primarily for residential networks without enterprise-class devices
Setting WifiP2pDnsSdServiceInfo
Wi-Fi direct service discovery request WifiP2pManager’s addServiceRequest(): Since we are searching for DNS-SD service the WifiP2pServiceRequest will be of NDS-SD type. Setting service discovery response listeners to WifiP2pManager
Wi-Fi direct service response listeners WifiP2pManager.DnsSdServiceResponseListener interface has only one method: WifiP2pManager.DnsSdTxtRecordListener interface: Other callbacks and broadcasts are same as Wi-Fi direct
Wi-Fi direct… rest of it and more Rest of the flow in Wi-Fi Direct service discovery is same as Wi-Fi direct. A device will call connect. Other device will receive an invitation to connect. There will be role negotiation based on GO intent parameter. A group will be formed with one group owner and others as clients. After that information can be exchanged. If we look at our use case the only difference is instead of pre-fixing a port, we are adding the port information when adding service request. So no listeners on pre-fixed port. All the services should be unregistered and discovery request must be stopped when exiting an application. We don’t want to drain the battery for no reason. Use createGroup() method discussed in Wi-Fi direct section only when supporting legacy devices.
Wi-Fi direct service discovery demo And a glance at some of the important methods and classes in demo code
Agenda Network interfaces. Basic socket communication. Network service discovery. Wi-Fi direct. Wi-Fi direct service discovery. Bluetooth low energy (BLE). Demos (wherever needed)
Bluetooth Low Energy In Android Before we dig deeper into Android. Few things we need to understand about BLE protocol stack
In Android, BLE stack was introduced in API 18 Jelly Bean 4 In Android, BLE stack was introduced in API 18 Jelly Bean 4.3, in July 2013. Android introduced BLE stack in Jelly Bean 4.3 <pause> API level 18 <pause><enter> Though became stable and reliable from Android Lollipop 5.0 <pause> API level 21 <enter> Next we will look into<pause> certain API calls and steps <pause>that android framework specifies<pause> to work with BLE devices.<enter> http://www.electronicsweekly.com/blogs/eyes-on-android/what-is/what-is-bluedroid-2014-01/ BlueDroid was introduced in 4.2 http://www.argenox.com/blog/android-5-0-lollipop-brings-ble-improvements/ The story of Android’s Bluetooth support is long. Android originally used the open source BlueZ stack that is common in Linux. But Google removed the bluez stack that was originally in Android because of its GPL license. Instead it decided to develop its own BlueDroid Bluetooth stack with Broadcom. BlueZ is GPL BlueDroid Apache License Improved Scanning Scanning, and in particular background scanning, was a big problem in Android for two reasons. The first is that scanning drains a battery tremendously. BLE scanning in Android was stopping the device from going into standby mode and would quickly drain batteries. The normal reaction of users was to disable Bluetooth to save on battery life, but this caused the phone to lose connection with BLE devices. The end result was that communicating with BLE enabled devices and getting data would take much longer, frustrating users. With Android L, the scanning process has been offloaded to lower layers which allows the smartphone to go to sleep. Users don’t have to disable Bluetooth when not using it actively. Support for BLE Peripheral and Broadcaster Modes Till 4.4 android framework supported only central mode.
Scene Peripheral Device will scan for near by peripheral to connect
Scene Central Peripheral Connection Object CONN_REQ Device will scan for near by peripheral to connect Central will initiate connection Peripheral will respond to accept CONN_REQ
Generic Access Profile Roles Observer Broadcaster A device could be a broadcaster or an observer.
Generic Access Profile Roles Central aka Master Peripheral aka Slave A device could be a broadcaster or an observer. connect
GATT Server-Client Client (asking data) Server (holding data) transact
Class { Services } Characteristics attributes; get(); set(); Read Write Characteristics Server is hosting services . Each service can have one or more characteristics And Each characteristic could read and written. Analogy is similar to a Class its attributes which can be get or set
BluetoothManager manager = (BluetoothManager) context .getSystemService( Context.BLUETOOTH_SERVICE); <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" /> mBluetoothAdapter = manager.getAdapter(); get BluetoothManager<enter> from application context using getSystemService method. To ensure your application has proper device compatibility <enter>. Declare ble hardware feature requirement in manifest file<pause><enter> Grab BluetoothAdapter from the manager object.<enter> The purpose of a <uses-feature> declaration is to inform any external entity of the set of hardware and software features on which your application depends. The element offers a requiredattribute that lets you specify whether your application requires and cannot function without the declared feature, or whether it prefers to have the feature but can function without it. BluetoothManager High level manager used to obtain an instance of an BluetoothAdapter and to conduct overall Bluetooth Management. The BluetoothAdapter is required for any and all Bluetooth activity. luetoothManager what does it manages?? BluetoothAdapter purpose??
Provide a callback object to receive scan results.. mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); mBluetoothLeScanner .startScan(callback); <uses-permission android:name= "android.permission.BLUETOOTH_ADMIN" /> get BluetoothLeScanner<enter> from BluetoothAdapter<pause> BluetoothLeScanner<pause> provides methods<pause> to perform scan related operations <pause>for Bluetooth LE devices Now execute startScan<enter> method It will run asynchronously Provide a callback object to receive scan results.. To perform device discovery get hold of bluetooth admin permission Note: <pause>To enable device discovery <enter> get hold of Bluetooth_Admin permission<enter> If you want your app to initiate device discovery or manipulate Bluetooth settings, you must also declare theBLUETOOTH_ADMIN permission. Note: If you use the BLUETOOTH_ADMIN permission, then you must also have theBLUETOOTH permission. Allows applications to discover and pair bluetooth devices. callbackType Determines how this callback was triggered. Could be one of * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, * {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} or * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST} Bluetooth_admin what doors does this permission opens?? What do we need this particular permission
ScanResult <enter> contains ble device information ScanCallback{ public void onScanResult(int callbackType, ScanResult result) { } public void onScanFailed(int errorCode) { After a successful device discovery You will receive ScanResult <enter> in your ScanCallback implementation.<pause> ScanResult <enter> contains ble device information ScanResult Device BluetoothDevice: Remote bluetooth device that is found. scanRecord ScanRecord: Scan record including both advertising data and scan response data. Rssi int: Received signal strength. timestampNanos long: Device timestamp when the scan result was observed. http://www.metageek.com/training/resources/understanding-rssi.html callbackType Determines how this callback was triggered. Could be one of * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}, * {@link ScanSettings#CALLBACK_TYPE_FIRST_MATCH} o * {@link ScanSettings#CALLBACK_TYPE_MATCH_LOST}??? How rssi calculates?? ScanResult contains what?? And what errorCode could be produced?? When you have multiple ble devices you will feed your list adapter with scan result and add on the basis of uuid
mBluetoothGatt = mBluetoothDevice.connectGatt( mBluetoothDevice = bleScanResult.getBluetoothDevice(); mBluetoothGatt = mBluetoothDevice.connectGatt( context, autoConnect, gattCallback) ; get bluetooth device <enter> from scan result. We will connect to the ble device, which is at this moment is acting as a GATT server. <enter> connectGatt method returns BluetoothGatt object.<pause> mBluetoothGatt is used to conduct GATT <loud>client operations. To automatically connect as soon as the remote device becomes available pass autoConnect true<pause> GattCallback will receive connection related responses.<pause> optional while waiting for callback Show intermediate progress bar. Optional It could be understood as mysql driver connection object is used to communicate mysql database server. BluetoothGatt functionality to enable communication with Bluetooth Smart or Smart Ready devices. /** * Connect to GATT Server hosted by this device. Caller acts as GATT client. * The callback is used to deliver results to Caller, such as connection status as well * as any further GATT client operations. * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct * GATT client operations. * @param callback GATT callback handler that will receive asynchronous callbacks. * @param autoConnect Whether to directly connect to the remote device (false) * or to automatically connect as soon as the remote * device becomes available (true). * @throws IllegalArgumentException if callback is null */
Check if it was connected <enter> successfully BluetoothGattCallback { public void onConnectionStateChange( BluetoothGatt gatt, int status, int newState) ; } if( newState == BluetoothProfile.STATE_CONNECTED) Whatever happens to connection is communicated <enter> through onConnectionStateChange callback Check if it was connected <enter> successfully Gatt is the connection object Status is like 200ok where operation was successfull newState tells our current connection state /** * Callback indicating when GATT client has connected/disconnected to/from a remote * GATT server. * * @param gatt GATT client * @param status Status of the connect or disconnect operation. * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. * @param newState Returns the new connection state. Can be one of * {@link BluetoothProfile#STATE_DISCONNECTED} or * {@link BluetoothProfile#STATE_CONNECTED} */ Note this would be called in separate thread
bluetoothGatt.discoverServices(); BluetoothGattCallback { public void onServicesDiscovered( BluetoothGatt gatt, int status); } List<BluetoothGattService> serviceList = gatt.getServices(); Once we are connected successfully to GATT server , we will <enter> discover services. When service discovery is completed <enter> onServicesDiscovered is called in GattCallback implementation Retrieve services <enter> and obtain desired service using particular UUID<enter> Once service discovery is completed, * the {@link BluetoothGattCallback#onServicesDiscovered} callback is * triggered. /** * Callback indicating when GATT client has connected/disconnected to/from a remote * GATT server. * * @param gatt GATT client * @param status Status of the connect or disconnect operation. * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. * @param newState Returns the new connection state. Can be one of * {@link BluetoothProfile#STATE_DISCONNECTED} or * {@link BluetoothProfile#STATE_CONNECTED} */ Note this would be called in separate thread What is ble service?? Example??
Retrieve desired characteristic using UUID. List<BluetoothGattCharacteristic> list = bluetoothGattService.getCharacteristics(); bluetoothGattCharacteristic.setValue( intToByteArray(color)); bluetoothGatt.writeCharacteristic( bluetoothGattCharacteristic) A particular service may hold multiple characteristics<enter><pause> Retrieve desired characteristic using UUID. Now set color value<enter> by moving seekbar on application. And write <enter> this characteristic onto server. /** * Callback indicating when GATT client has connected/disconnected to/from a remote * GATT server. * * @param gatt GATT client * @param status Status of the connect or disconnect operation. * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. * @param newState Returns the new connection state. Can be one of * {@link BluetoothProfile#STATE_DISCONNECTED} or * {@link BluetoothProfile#STATE_CONNECTED} */ Note this would be called in separate thread
We will receive A callback<enter> onCharacteristicWrite BluetoothGattCallback { public void onCharacteristicWrite( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) ; } if( status == BluetoothGatt.GATT_SUCCESS) We will receive A callback<enter> onCharacteristicWrite And <enter> if write is Successful <enter> we will see Led strip changed its color /** * Callback indicating the result of a characteristic write operation. * * <p>If this callback is invoked while a reliable write transaction is * in progress, the value of the characteristic represents the value * reported by the remote device. An application should compare this * value to the desired value to be written. If the values don't match, * the application must abort the reliable write transaction. * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic} * @param characteristic Characteristic that was written to the associated * remote device. * @param status The result of the write operation * {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds. */
Video removed…
Demo code available at… https://github.com/drulabs/LocalDash https://github.com/navalkishoreb/IoT/tree/zone_discovery/Android
References https://docs.oracle.com/javase/tutorial/networking/nifs/index.html https://docs.oracle.com/javase/7/docs/api/java/net/NetworkInterface.html http://www.tldp.org/LDP/nag2/x-087-2-hwconfig.tour.html http://adbshell.com/commands/adb-shell-netstat https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ https://docs.oracle.com/javase/tutorial/networking/sockets/definition.html https://developer.android.com/guide/topics/connectivity/wifip2p.html
BLE has 40 channels of 2Mhz bandwidth Out of which 37 are Data channels Only 3 are for Advertising data
Take arduino uno<enter> Take breadboard<enter> +3.3 Volt +5Volt _Tx_ _Rx_ _Tx _ _Rx_ GND PIN 6 Now we will make few <loud>connections step by step<pause><enter> Take arduino uno<enter> Take breadboard<enter> Take Led strip<enter> Now connect 5Volt output from arduino to led strip power supply pin<enter> Connect ground pin from arduino to breadboard<enter> Connect Pin 6 from arduino to led strip Data input pin<enter> Take HM-10 Module , connect the ground wire with breadboad <enter> Now connect 3.3Volt output from arduino to power pin supply of HM -10<enter> Connect Pin 10 the Receiving end of arduino <enter> to Transmitting end of HM-10 <enter> Connect Pin 11 the Transmitting end of arduino to Receiving pin of HM -10