Example Driver to Connect to Android Devices

Last modified by Jan Lapp on 2017/01/20 18:38

Generally there are two types of interactions between OGEMA systems and mobile systems like devices powered by Android or iOS:

  • User interaction - using the mobile device to display a GUI and allow the user to interact with an OGEMA app. This can be done via a native mobile app or via a web browser installed on the mobile device that displays the usual OGEMA web interface
  • Using the mobile device as a sensor / actor device or other source/recipient of data. This means e.g. using the mobile device to regognize a user entering the local WLAN, using the device's speaker as an alarm actor or accessing the database of the device. Such interaction requires a specific mobile app on the device, but also a driver on the OGEMA side that puts the data into an appropriate OGEMA data model.

In this tutorial we will deal with the second case. The interaction via the OGEMA REST interface can also be used for pure user-interaction-oriented mobile apps, though.

Setting up your Android development environment

This is a very brief introduction how install Android Studio and how to start a mobile app there. A tutorial on Android development is provided on the Android Developer page.

First we assume that you have installed Android Studio as described on the Android Developer Page. You will probably need a Java 64-bit SDK to run it.
Installation of Studio, SDK and starting Android Studio up for the first time took aprox. 1,5 hours on my PC, so be patient. Getting additional modules and updates during first start up took quite some time.

Check that your Android studio has installed all updates as described on the Android Update page. Install additional components via the SDK manager as described here. You should get the platform packages for the minimum API level supported (in our example API level 15, see below) and for the most important platforms you want to support. The following packages we also recommend to get:

" width="900">AndroidStudioConfig1.png

and

AndroidStudioConfig2.png

Open the Android sample application provided at Github with Android Studio. Try to build and run it with 'F10' or the button with the green play icon. You might have to set Tools->Android->Enable ADB Integration before it works correctly. We tested the application mainly with a simulated Nexus 5, API 23 (Android 6.0, Marshmellow). Instead of a virtual device you can also connect a real android device to your development PC and run the app there. Just choose the connected device instead of a virtual device in the Build&Run process. To enable an Android device for running/debugging an application from Android Studio read this. Very important: To access the developer settings, open the Developer options in the system Settings. On Android 4.2 and higher, the Developer options screen is hidden by default. To make it visible, go to Settings > About phone and tap Build number seven times. Return to the previous screen to find Developer options at the bottom. Especially for windows users it may be difficult to get the specific ADB driver for the Android device connected, so we recommend to use one of the manufacturers listed on the windows ADB installation page.

Functionality Overview

The mobile device checks whether it is connected to a WLAN. If so it scans the local IP addresses (last byte of the IPv4 address) and checks whether it can connect to an OGEMA REST interface on port 8443. Username and passwort can be provided by the user in a simple App GUI. It tries to write to a certain resource on the OGEMA framework to register.This information allows the OGEMA Android driver to detect that the mobile device is present in the local WLAN (presence detection).

The OGEMA driver shall generate an entry in a ResourceList of element type PersonalDevicePresenceInfo from where the mobile app can read messages and react on them, e.g. start the ring tone of the device or send back some information.

Developing combined OGEMA / Android solutions

When you want to test and develop solutions where you change OGEMA apps as well as an Android app you will most likely want to run both systems from your development PC. This is well possible:

  • Setup Android Studio first as described before. If your PC is not very strong you might want to close it as long as you setup your Eclipse-based OGEMA SDK environment.
  • Start the OGEMA SDK (Eclipse) and get the Rundirectory operating with the apps you need.
  • Connect an Android device to your PC. You could also use a virtual Android device on the PC, but these devices usually consume a lot of computing resources and cannot emulate Wifi/Network connection, so you should really use a separate hardware device
    Make sure the Android device is connected to the same Wifi network as your development PC
  • Start Android studio and Build/Run the App on the Android hardware device.
    Check if all communication and interaction works as intended.

OGEMA Driver

Create an OGEMA driver with the following settings:

AndroidSampleDriverCreate1.png

and

AndroidSampleDriverCreate2.png

This driver does not connect to the remote device actively, but waits for the mobile device to connect. Still it could be possible to provide configuration information for certain mobile devices (based on the mobileId used here) even if they have not yet connected. Still the driver does not have to look for existing configurations that would trigger communication operations, so we can delete the pattern and the listener here (packages ending on pattern and patternlistener). This also means we have to remove some references to the listener from the class SampleAndroiddriverApp.

As next step we add a StringResource to which the mobile app can write and a list of known devices. The resource type PersonalDevicePresenceInfo is intended to represent a mobile device that is used for personal presence detection, but also further interaction with OGEMA. The code for the class SampleAndroiddriverConfig should then look like this:

package com.example.androiddriver.drivermodel;

import org.ogema.core.model.ResourceList;
import org.ogema.core.model.simple.StringResource;
import org.ogema.model.prototypes.Configuration;
import org.ogema.model.user.PersonalDevicePresenceInfo;

/**
 * The global configuration resource type for this app.
 */

public interface SampleAndroiddriverConfig extends Configuration {
/** Connection information kept separate from mobile devices for compatibility with standard driver model*/
 ResourceList<SampleAndroiddriverModel> connections();

/** Device information. The mobile device will also read/write with this resource via the REST interface*/
 ResourceList<PersonalDevicePresenceInfo> mobileDeviceConfig();

/**Receive initial information from mobile device here*/
 StringResource dataInflow();
}

The controller needs to listen to new data in dataInflow. This may be realized at the end of the constructor of SampleAndroiddriverConectionManager like this:

   public SampleAndroiddriverConectionManager(ApplicationManager appMan) {
 this.appMan = appMan;
 this.log = appMan.getLogger();
 
        initConfigurationResource();
       
  ResourceValueListener<StringResource> listener =
   new ResourceValueListener<StringResource>() {
  @Override
  public void resourceChanged(StringResource resource) {
    System.out.println("dataflowIn changed:"+resource);
    String val = resource.getValue();
   int i = val.indexOf("mobilid=");
   int j = val.indexOf("&ssid=");
    String mobilId, ssId;
   if(j<0) {
    if(val.length() > (i+8)) mobilId = val.substring(i+8);
    else mobilId = null;
     ssId = null;
   } else {
     mobilId = val.substring(i+8, j);
     ssId = val.substring(j+6);
   }
    processInflow(mobilId, ssId);
  }
 };
  appConfigData.dataInflow().addValueListener(listener, true);
 
 }
   
private PersonalDevicePresenceInfo processInflow(String mobilId, String ssId) {
 if(mobilId == null) {
  return null;
 }
  PersonalDevicePresenceInfo mcToUse = null;
 for(SampleAndroiddriverModel deviceData: appConfigData.connections().getAllElements()) {
  if(deviceData.target().mobilSerialId().getValue().equals(mobilId)) {
    mcToUse = deviceData.target();
   break;
  }
 }
 if(mcToUse == null) {
  //create new
  String mobilIdName = ResourceUtils.getValidResourceName(mobilId);
  //mcToUse = appConfigData.connections().addDecorator(mobilIdName, SampleAndroiddriverModel.class).target();
  mcToUse = appConfigData.mobileDeviceConfig().addDecorator(mobilIdName, PersonalDevicePresenceInfo.class);
   mcToUse.mobilSerialId().create();
   mcToUse.mobilSerialId().setValue(mobilId);
   mcToUse.trackPresence().create();
   mcToUse.trackPresence().setValue(true);
   mcToUse.messageToDevice().create();
   mcToUse.messageToDevice().setValue("");
   mcToUse.lastMessageIdReceivedByDevice().create();
   mcToUse.lastMessageIdReceivedByDevice().setValue("");
  if(ssId != null) {
    mcToUse.ssId().create();
    mcToUse.ssId().setValue(ssId);
  }
   mcToUse.lastMessageReceived().create();
   mcToUse.presenceDetected().create();
   mcToUse.presenceDetected().setValue(false);
   mcToUse.activate(true);
  
  //create driver configuration resource
  SampleAndroiddriverModel comRes = appConfigData.connections().addDecorator(mobilIdName, SampleAndroiddriverModel.class);
   comRes.target().setAsReference(mcToUse);
   comRes.activate(true);

 }
  mcToUse.lastMessageReceived().setValue(appMan.getFrameworkTime());
 //mcToUse.presenceDetected().setValue(true);
 return mcToUse;
}

Android App

For the development of further OGEMA-related apps the Util classes of the Android App are most important:

The class WLANOGEMAService implements a service (that continues to run once the app has been opened once even if the app is not visible on the screen). The service scans the local Wifi network for OGEMA instances and performs write and read operations. The ServletWLANActivity, which generates the screen shown initially, starts this service. When the app is started in the emulator it should look like this:

AndroidSampleApp.png

Additional information and recommendations

As recommended by F-Droid you should set the minimum Android API level to 4 (Android 1.6) or higher for your applications. In our driver we use a minimum API level of 15 (Android 4.03) and a target API level of 22 (Android 5.1).

Notes on Getting Started with Android Studio

  • After installation the XML-viewer did not work, said I should update Android Studio. There was an update of Android Studio available that was not part of the initial download (though 2 days old). Then I still had to start a rebuild via a link provided with the error and re-open the file
  • The x86 hardware acceleration was not activated on my machine => I could only run virtual devices with an ARM emulator
    To run also x86 emulators changes in BIOS were required. During change in BIOS Windows Bitlocker had to be deactivated
  • Tested Debugging: Works fine, but at some point could not connect anymore, probably have to restart machine
    Generally debugging and logging are sometimes quite confusing.Log Messages sent with the Android Log class can be viewed in Android Studio:"6:Android", "logcat" (in Debug and normal Run mode)
    Debug mode does not really work for server/client communication debugging
    To be sure that messages are really sent to the console, log them with Log.e help
  • When opening the Android Device Monitor be very patient! It may ask for certain Google permission in a separate windows that may be hidden. So if it does not open at all minize other windows to find the Google window.
  • To store the logcat file from the device: Go to logcat window -> Strg+A -> Strg+C -> Paste into some text file (see also Zendesk
Tags:
Created by Jan Lapp on 2017/01/11 22:07