DTU 
 

 

02162: Course on Software Engineering 2 (e14)

In this tutorial, you will learn how to implement an Android App which accesses some web services for reporting sensor information and for showing the current information of a remote sensor in the App. To this end, you will also need to extend the web services in order to make them thread safe and to simulate pushing information from the server to the App.

 

For implementing web clients in an Android App, we use the RestTemplates of the Spring framework for Android.

 

In this assignment, you will implement an App that reports the absolute value of the acceleration sensor to the web server (the sensor number can be chosen by the user); in addition, the App should show the current reading of a sensor, which also can be choosen by the user (which might be different from the one the App reports values for).

 

Tasks

Here are the steps for the tasks of the fourth assignment:

 

  1. In the first part, you will implement an App that reports the absolute values of the accelerator to the web server. The sensor is should be a number that can be freely entered by the user via some text input field (called EditText in Android).

     

    1. In order to make it easier for the App to communicate with the web server, you need to slightly change the web services from tutorial 2, first.

       

      Create another Dynamic Web Project, where you can reuse most of the code from tutorial 2. To start with, you only need to replace the annotations

        @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})

      with

        @Produces(MediaType.APPLICATION_JSON)

      in the implementation of your web services from tutorial 2. The result will be that the web service returns actual JSON representations of the result instead of the XML that we used in tutorial 2.

       

      The reason for this is that RestTemplates work with JSON by default.

       

      You should also change the data type for events, so that each event is assigned a unique identifier, which could be the time when it is registered by the server. We will make some other extensions to this web project later in this tutorial.

       

    2. Next, create another Android Application Project (see Tutorial 3).

       

      In order to use RestTemplates of the Spring framework for Android in your App, you need to download some additional libraries. For your convenience, all the needed jar files are available in the following archive: spring-android-rest-templates-libs.zip. Copy the all jar files from this archive to the lib folder of your new Android Application Project.

       

      Since this App will need access to the internet, you need to add this information to the AndroidManifest.xml in your newly created Android Application Project. The corresponding XML snippet looks as follows:

        <uses-permission android:name="android.permission.INTERNET"/>

       

    3. Next, add a text input field (called a EditText in Android) to the layout of the main activity (actually, its fragment). This field needs to be given a unique identifier, so that its value can be accessed from the program code. This field should be used by the user to enter the sensor id (the default could be 1) for which the values of the accelerator should be reportet.

       

    4. Then, create and register a SensorEventListener (see Tutorial 3) when the main activity starts. When the value of the sensor changes significantly, your listener should register this value to the web server vy invoking the addevent service.

       

      The code for this using RestTemplates could look as follows:

       

        final String url = BASE_URL + "/addevent?id={id}&value={value}";
        final Map parameters = new HashMap();
        parameters.put("id", String.valueOf(id));
        parameters.put("value", String.valueOf(value));
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
        Event result = restTemplate.getForObject(url, Event.class, parameters);

       

      This code will be explained in the tutorial on Friday, September 26. You also find some explanations here or in some of the links below.

       

      The id should be read from the text input field (see Tutorial 3 for how to access the value of such a field); the value should be the current absolute value of the sensor.

       

      Since calling a web service can take some time, it is a good idea to run this part of the code asynchrounusly in a thread (but make sure you do not run too many of these concurrently). If you are not familiar to Thread programming yet, you might (ab-)use the AsyncTask provided by Android to issue an asynchronous task. It is a slight abuse, since in this case the AsyncTask would not need report anything back to the GUI (which is the main purpose of this construct).

       

    5. In order to test your App, you need to deploy your web application to a web server. For now, this will be the localhost; but, each group will be assigned a webserver to which they can deploy their web applications soon. When you use your local host at DTU, it is recommended that you connect both, your phone and the webserver to the internet via eduroam; then, you can use the dynamic IP address assigned to your computer by eduroam in the above BASE_URL (on Windows, you can see this IP address by executing ipconfig on the console after you connected to eduroam).

       

      By entering some URLs to your Web browser for registering events and for looking them up again, check whether the web services are running properly (see Tutorial 2).

       

      Before your test your App, use the admin interface of the web server to increase the maximal number of threads in the pool for http-requests (the default of 5 might not be enough with more than one phone, and services might be stuck for a long time).

       

    6. Next start your App and shake the phone. Use the getEventList web services in the browser to check whether the values are properly registered in your web application.

       

  2. In the second part, you add another feature to your App, which is supposed to show the most current value of some sensor (chosen by the user via another edit text) to the user. Note that the sensor id could be an id of a remote sensor, so the value needs to be obtained via the web server.

     

    1. This part, actually requires some thread programming on the server side as well as on the client side. The reason is that web services follow the client server architecture. This means that the server has no way of pushing a new value to the client. This in turn, means that the client needs to poll the server for new values all the time, which is quite inefficient and causes lots of communication.

       

      Therefore, we try another technique here: a long-running request which we call awaitevent. When a new a awaiteventt request comes in, the server puts this thread on hold (in Java thread programming, this is achieved with a wait()). Once a new value for that sensor comes in (via a call of an addevent service), this thread is woken up (in Java thread programming, this is achieved with a notifyAll()), the service can than look up the value and return that value to the client. Note that this means, that a request is open for an extremely long time; the implementation must therefore make sure that not too many of such requests are open at the same time; and it might be a good idea to build in a timeout.

       

      The details of the thread programming will be discussed in the tutorial, and you will find much more information on concurrent programming in Java here and specifically on the wait/notify mechanism and here.

       

      Now add a web service awaitevent which takes the sensor id as a parameter. This should be implemented as a long-running request, which returns when the next event for that sensor is reported to the server.

       

    2. Deploy the extended web application to the web server and check via URL interactions whether the services awaitevent and addevent properly work together.

       

    3. Next, you should extend the App, so that the user can select a sensor id (which can be different from the sensor id that it reports values for). The App should then show the current value for this sensor, and that value should be updated whenever the server receives a new value for the respective sensor. This can be done by calling the awaitevent service.

       

      Since the awaitevent service can take very long time. It needs to be invoked from an independent thread. In Android, however, an independent thread should not update the Android GUI (the textfield showing the current value). In order to properly update the GUI from another thread, you can issue the actual update in the following way:

       

        textview.post(new Runnable() {
          public void run() {
            textview.setText(text);
          }
        });

       

      This makes sure that the textfield will be updated by the GUI thread at an appropriate time.

       

      Also make sure that your thread is properly shut down when the activity stops. This and some other issues will be discussed in some more detail in the tutorial.

       

    4. Test your App together with the server. Also enter some events (for a different sensor id) via your web browser or use a second phone reporting values for another sensor id.

       

  3. Note that some of the techniques of thread programming and having long-running request require careful design. Some of them will be discussed in the tutorial. In you project later, you should be aware of the following issues:

     

    • Make sure that the web server is configured with enough threads in the pool of HTTP requests (increas the maximum number).

       

    • Make sure that you do not leave behind too many open connections/request when programming the client (when abandoning a request).

       

    • The implementation of "pushing a value" from the server to the client via an open long-running request can be improved (you could use another channel to change the events you would like to be notified about).

       

    • For the real project, you should pre-process the low-level events on the smart phone and only send higher-level (and less frequent) events to the server in order to avoid too much communication.

       

    • In the real project, you need to think about some reasonable timeouts.

       

Useful links

Here are some links that might be helpful:

 

 

Ekkart Kindler (), Sept 24, 2014 (last updated Sept 29, 2014)