Global System for Mobile Network Architecture GSM Architecture 2G … … 16 [621797]

1
Contents
1 Rezumat ………………………….. ………………………….. ………………………….. ………………………….. ……………………. 3
Introducere ………………………….. ………………………….. ………………………….. ………………………….. ……………….. 3
Implementa re ………………………….. ………………………….. ………………………….. ………………………….. ……………. 4
Rezultate ………………………….. ………………………….. ………………………….. ………………………….. ………………….. 8
Interpretări ………………………….. ………………………….. ………………………….. ………………………….. ……………….. 9
2 Work planning ………………………….. ………………………….. ………………………….. ………………………….. …………. 10
3 State of the art ………………………….. ………………………….. ………………………….. ………………………….. …………. 11
Open Signal ………………………….. ………………………….. ………………………….. ………………………….. …………….. 11
Sensorly ………………………….. ………………………….. ………………………….. ………………………….. ………………….. 13
4 Theoretical Fundamentals ………………………….. ………………………….. ………………………….. ………………………. 15
Early technologies ………………………….. ………………………….. ………………………….. ………………………….. ……. 15
Mobile networks ………………………….. ………………………….. ………………………….. ………………………….. ……… 15
Netw ork architectures ………………………….. ………………………….. ………………………….. ………………………….. . 15
Global System for Mobile Network Architecture – GSM Architecture – 2G ………………………….. ……………. 16
Universal Mobile Telecommunication System – 3G ………………………….. ………………………….. ………………… 19
Long Term Evolution – Architecture – 4G ………………………….. ………………………….. ………………………….. …. 21
Parameters defined in Android API for handling radio interface measurements in idle mode in 2G, 3G and
4G networks ………………………….. ………………………….. ………………………….. ………………………….. ……………………….. 23
5 Implementation ………………………….. ………………………….. ………………………….. ………………………….. ……….. 26
Technologies ………………………….. ………………………….. ………………………….. ………………………….. …………… 26
Tools ………………………….. ………………………….. ………………………….. ………………………….. ………………………. 28
General Implementation ………………………….. ………………………….. ………………………….. ……………………….. 30
Client implementation – Mobile Network Scanner Application ………………………….. ………………………….. .. 32
Server implementation – Mobile Network ………………………….. ………………………….. ………………………….. .. 35
Database implementation – MariaDB ………………………….. ………………………….. ………………………….. …….. 39
6 Experimental Results ………………………….. ………………………….. ………………………….. ………………………….. … 41
Database Content ………………………….. ………………………….. ………………………….. ………………………….. ……. 41
Filtered Results ………………………….. ………………………….. ………………………….. ………………………….. ………… 41
Rendered Type ………………………….. ………………………….. ………………………….. ………………………….. ………… 45
Offlin e measure samples ………………………….. ………………………….. ………………………….. ……………………….. 48
7 Conclusions ………………………….. ………………………….. ………………………….. ………………………….. ……………… 50
8 References ………………………….. ………………………….. ………………………….. ………………………….. ………………. 51

2
9 Appendix ………………………….. ………………………….. ………………………….. ………………………….. …………………. 53
Server Source code ………………………….. ………………………….. ………………………….. ………………………….. …… 53
Server Javadoc ………………………….. ………………………….. ………………………….. ………………………….. ………… 79
Client Source code ………………………….. ………………………….. ………………………….. ………………………….. ……. 79
Client JavaDoc ………………………….. ………………………….. ………………………….. ………………………….. ……….. 123
Database development ………………………….. ………………………….. ………………………….. ……………………….. 123
10 CV-ul autorului ………………………….. ………………………….. ………………………….. ………………………….. ……….. 125

3
1 Rezumat
Introducere
Această lucrare propune o soluție îmbunătățită pentru măsurarea parametrilor rețelelor mobile
și monitorizarea acestora.
Rețelele mobile au fost întotdeauna un punct de interes pentru omenire, iar dezvoltarea
comunicării radio reprezenta un mare obiectiv în secolu l anterior. În acest sens, doi ingineri de la
laboratoarele Bell au propus o arhitectură de celule hexagonale în anii 1950. Este vorba despre
William Rae Young și Douglas H. Ring, însă, din nefericire în perioada respectivă tehnologiile nu
erau destul de a vansate pentru a putea implementa arhitectura.
Abia după douăzeci de ani, alți trei ingineri de la laboratoarele Bell, Joel Stanley Engel, Richard
H. Frenkiel și Philip Thomas Porter au finisat propunerile anterioare, definind astfel un plan cu
mult mai vi abil.
Printre ideile cuprinse în propunere, este enumerată și folosirea în turnurile de semnal, a
antenelor bidirecționale, ce au fost dezvoltate între timp.
Cu toate acestea, în timpul acestei tehnologii mobile, dispozitivul mobil era nevoit să nu
prăseas că zona deservită de celula în care s -a inițiat apelul pentru că se pierdea conexiunea,
neexistând opțiunea de management al mobilității.
O rețea mobilă este definită de un ansamblu de sisteme hardware și software în care conexiunea
între stația mobilă și restul rețelei este reprezentată de o legătură radio.

Arhitectura de baza a unei rețele mobile este definită mai jos în Figura 1.Arhitectura generală
a rețelelor mobile .

Stația Mobilă sau Mobile Station (MS – temen folosit în rețelele 2G)/ Echipamentul
Utilizatorului sau User Equipment ( UE – termen folosit în rețelele 3G/4G) este alcătuit din
componentele harware si software pentru a asigura comunicațiile radio cu o stație de bază, plus o
cartele SIM (Subscriber Idenity Module) care deține informații despre un anumit abonament. De
asemenea cartela SI M realizează funcții de sec uritate și autentificare în re țea.
Rețeaua de Acces Radio (Radio Access Network) este definită de secțiunea din rețea care face
legătura între toate dispozitivele mobile aflate în zona de acoperire cu rețeaua de bază (Core
Networ k). De obicei, are în componența sa turnurile de semnal împreună cu antenele aferente
acestora și are rolul de a furniza acces radio pentru ca terminalele mobile să fie capabile să acceseze
rețeaua de bază.
Rețeaua de Baza (Core Network) este responsabilă de rutarea apelurilor în rețea, dar are și alte
roluri precum autorizarea și/sau autentificarea terminalelor mobile în sistem.

În ultimii ani rețelele mobile s -au dezvoltat în repetate etape, pe care le vom numi mai departe
generaț ii. În ordine cronologică, au fost definite următoarele tehnologii:
 2G- reprezintă generația a doua de rețele mobile. Aduce îmbunătățiri rețelei existente,
dar și noi servicii, ca de exemplu Short Message Service (SMS). Este mai securizat,
astfel că apelurile telefonice sunt încriptate și apoi trimise către rețea prin interfața
radio;
MS/UE
RAN
CN
PSTN/
ISDN
Figura 1.Arhitectura generală a rețelelor mobile

4

 3G- definește un standard înalt prin noile caracteristici pe care le adaugă. Când această
tehnologie este folosită, abonatul are acces la navigarea pe internet și să descarce video –
uri cu viteza de transfer de pana la 2 Mbps;
 4G- este caracterizată prin viteză mare de transfer, aceasta este de 100 Mbps și poate
ajunge pana la 1 Gb/s. Suportă apeluri video live și televiziune live.

Pentru ca toate aceste evoluții ale tehnologiilor să fie po sibile, a fost nevoie de nenumărate
experimente și măsurători ale caracteristicilor rețelelor mobile. În funcție de tehnologia
monitorizată se pot măsura:
 Indicatorul de intensitate a semnalului sau Received Signal Strength Indicator (RSSI)
în rețele 2G. A cest indicator definește puterea semnalului recepționat și este de obicei
măsurat în DBm sau Decibeli -miliwați și valorile folosite în rețelele mobile se situează
între -140 DBm și -51DBm, echivalentul a 0,1 pW respectiv aproximativ 10 μW. Pe
baza indica torului se ia decizia în privința procesului de handover;
 Puterea codului semna lului recepționat sau Received Si gnal Code Power (RSCP) în
rețelele 3G. Definește puterea recepționată de dispozitivul receptor pe un canal de
comunicare fizic. Definește putere a semnalului și este folosit în decizia de handover.
 Puterea recepționată a semnalului de referință sau Reference Signal Received Power
(RSRP) și calitatea recepției semnalului de referință sau Reference Signal Received
Quality (RSRQ) sunt parametrii speci fici rețelelor mobile din generația a 4 -a. RSRP
este în principiu folosit pentru deciz ia în handover iar RSRQ se foloseș te pentru a clasa
celulele învecinate după calitate semnalului.
Implementare
Aplicația este caracterizată de o arhitectură server -client . Este structurată pe baza unei aplicații
pe trei niveluri enumerând client, server și baza de date.

Partea de Client Partea de Server Partea de Bază de Date

Figura 2. Arhitectura Server -Client pe trei niveluri

Operația de bază îndeplinită de client este de a eșantiona valorile parametrilor din interfața
radio, apoi urmând ca acestea să fie trimise via HTTP c ătre server. Odată pornit serviciul,
eșantionarea se execută la intervalul stabilit în setările aplicației .Tot cu această frecvență se
updateaz ă și interfața utilizatorului cu noile valori împreună cu locația GPS a dispozitivului urmând
să fie trimise către server.

Obiectele ajunse la server sunt procesate, validate și stocate în baza de date la care este con ectat.

DB

5

Figura 3.
Activitatea principală a
clientului
Figura 4. Diagrama de secvență la trimiterea unui eșantion

Pentru afișarea datelor colectate, este folosită metoda HTTP GET, trimisă de browser -ul WEB
către server care va r ăspunde cu o pagina HTML generat ă pe baza detaliilor extrase din baza de
date conform filtrelor implementate.

Figura 5. Interfața WEB – Accesarea datelor

Clientul este dezvoltat în Android și implementează? următoarele funcții :
 Furnizează informații despre dispozitivul mobil precum:
 Identitatea echipamentelor mobile internaționale sau International Mobile
Equipment Identity (IMEI);
 Operatorul de bază al cartelei SIM (Subscriber Identity Module);
 Țara ISO a operatorului de bază al cartelei;
 Identitatea abonatului mobil internațional sau International Mobile Subscriber
Identity (IMSI);
 Modelul dispozitivului;
 Producătorul dispozitivului;
 Identificatorul terminalului.
 Informații privind valo rile măsurate a interfeței radio pentru sistemul la care este
conectat precum:
 Nivele de semnal recepționat în dBm;
 Nivele de semnal recepționat în indicatori de calitate;
 Numele operatorului la care este conectat dispozitivul;
 Clasa de rețea la care este conectat dispozitivul;
 Tipul de tehnologie la care este conectat dispozitivul.

6
 Informații privi nd locația GPS a dispozitivului:
 Coordonate de longitudine;
 Coordonate de latitudine.
 Afișează Informațiile relevante în interfața aplicației:
 Nivelul de semnal general;
 Valoare dBm a semnalului recepționat;
 Unitatea de putere arbitrara sau Arbitrary Strength Unit (ASU);
 Numele operatorului;
 Clasa rețelei;
 Tipul rețelei;
 Informații despre dispozitiv;
 Coordonate GPS longitudine și latitudine actuale ale dispozitivu lui.

 Eșantionează nivelele de putere ale semnalului la intervalul setat, împreună cu locația
curentă a dispozitivului la un moment specific;
 Trimite eșantionul către server prin clientul HTTP;
 Salvează eșantioanele care nu au fost trimise cu succes;
 Reînc earcă trimiterea eșantioanelor eșuate la trimitere;
 Execută funcții de testarea vitezei de transfer și trimiterea rezultatelor către server, via
clientului HTTP;

Figura 6. Măsurarea vitezei de transfer

Serverul este dezvoltat în Java, utilizând Spring framework și implementează următoarele
funcții:
 Tratează cererile de tip POST primite prin HTTP. În funcție de endpoint -ul folosit
manipulează:
 Cereri în care sunt definite proprietățile dispozitivului;
 Cereri în care sunt definite vitezele de transfer măsurate;

7
 Cereri în care sunt definite caracteristici ale interfeței radio;
 Salvează detaliile primite prin HTTP în baza de date, diferențiind între tipurile de cereri
primite;
 Tratează cererile de tip GET primite prin HTTP. A fișează pagina WEB în care sunt
încărcate următoarele:
 Fragment al hă rților de la Google, pe care sunt suprapuse datele colectate;
 Mai multe opțiuni de filtrare pentru a reduce setul de rezultate afișate pe hartă:
 Filtrare după modelul terminalului;
 Filtra re după producătorul terminalului;
 Filtrare după operatorul mobil;
 Filtrare după tehnologia rețelei;
 Filtrare după clasa rețelei
 Filtrare după perioada în care s -au eșantionat valorile;
 Filtrare după tipul parametrului măsurat.
 Interoghează baza de date pe ntru lista de eșantioane stocate. Reduce
dimensiunile rezultatelor pe baza filtrărilor.
Baza de date este reprezentată de o instanța de MariaDB structurată pe doua tabele. Relațiile
dintre tabele sunt definite în Figura 9. Bază de date – relații tabele .
 Tabel SIGNAL_LEVELS în care se regăsesc valorile eșantionate ale parametrilor
rețelei;

Figura 7.Rând în tabel SIGNAL_LEVEL

 Tabel DEVICE_ PROPERTIES în care se regăsesc informații despre identitatea
dispozitivului mobil care a eșantionat parametrii;

Figura 8. Rând în tabel DEVICE_PROPERTIES

Figura 9. Bază de date – relații tabele

8

Rezultate
Din momentul în care varianta BETA a aplicației a fost lansată. Serverul a primit și procesat
peste 3200 de eșantioane. Numărul de abonați care au contribuit la crearea acestei baze de date este
de 8 clienți și este în creștere. La momentul când această lucrare a fost scrisă, o parte din conținutul
tabelelor din baza de date este următorul:

Figura 10. Fragment din conținutul tabelei SIGNAL_LEVEL

O parte din conținutul tabelei DEVICE_PROPERTIES este prezentat mai jos:

Figura 11. Fragment din conținutul tabelei DEVICE_PROPERTIES

Datorită modului în care sistemul a fost implementat, prin intermediul interfeței WEB pe care
serverul o expune, aceste date pot fi repr ezentate peste un fragment al hărților Google.

Figura 12. Interfața WEB de afișare a informaț iilor

9
Îmbunătățirea pe care sistemul propus le implementează , este folosirea câmpurilor de filtrare
pentru a putea vizualiza un set de date cât mai specific bazat pe modelul dispozitivului , operatorul
de rețea, clasa reț elei. Așadar, un aspect important este repr ezentat de posibilitatea ca numă rul
rezultatelor afișate să fie restrâns, bazat pe in tervalul de timp în care s -au făcut mă surătorile.

Figura 13. Afișarea rezultatelor corespunzător filtrării
Interpretări
Din rezultatele obținute se poate conclude faptul că rețelele mobile sunt prezente peste tot în
jurul nostru, oferind serviciile de care lumea modernă are nevoie. Se ob servă, totuși că, în ciuda
faptului că se folosesc tehnologii extrem de avansate, există zone care nu beneficiază în totalitate
de acoperirea rețelelor mobile fie prin prisma faptului că în aria respectivă nu sunt instalate
tehnologiile necesare, fie că de și acestea există, nu sunt suficient de bine optimizate pentru a oferi
acoperire absolut totală.

10
2 Work planning

11
3 State of the art
Given the people need for communications, the cellular networks technology and the user
equipment tends to be more and more reliable and provide various services that suits entire world
requires.
The p eople are on active move every second and that requires high technologies to sustain all
the services for every place in the world. This is the purpose of every mobi le services provider, to
have a reliable network, large coverage with decent signal quality that qualifies for all the end user
needs, even there are need for live streaming, or large upload and download bandwidths, instant
messaging and others.
In order to achieve these goals , the operator has to put together a well -planned business
portfolio regarding the network capabilities, quality, platform features and provided services using
all these components mentioned.
Supposing all crowded areas are already c overed, naming here large cities where the network
is loaded with countless request coming from the end user equipment and yet, these request are
handled well by existing platform, still, we can find specific places where we cannot find cell signal
coverag e from all or specific services operator, like: elevators, subways tracks and stations, tunnels,
underground passages, underground parking lots, interiors fire stairs and the list may continue.
In order to provide the best services, the mobile operator companies are continuously in
searching of solution that can find coverage leaks on their networks with the purpose to fix them,
offering their clients the best experiences.
Some companies already developed enterprise solutions for collecti ng and analyze the signal
coverage, the signal power, the signal quality and other such indicators on general places or
particular spaces.
These measurements results are able to determine a mobile operator if there are needs for more
hardware on specific l ocations or if there is enough signal power to sustain day by day access of
network at specific time and position.
Open Signal
Claiming to be the “Global #1 signal tool – over 10 million users” [1] conform their advert ising
on Google Play, Open signal set of applications , tents to be one of the preferred free to use
application for mobile networks measurements and monitoring.
Open Signal application has over 10 million installs and a note of 4.2 out of 5, based on 361.941
total reviews on Google Play, at the time when this paper is written .

Figure 14. Open Signal on Google Play [2]

12

However, the information at which the user has access on mobile phone are limited to
registered Network Name and direction of nearest Cell Tower, not necessarily the one on which
mobile terminal is connected to. Also in the app is exposed a speed test feature, wit h the mentions
that the “OpenSignal’s TRUE Speed test measures the real speed that you see on you network” [2]
and includes a view containing a google map fragment with rendered collected data on specific
area with option to filter by operator and network type (e.g. 2G/3G or 4G) and a small legend on
bottom -left corner for coverage colors.

Figure 15. Main Activity
Open Signal [2]
Figure 16. Speed Test
Activity Open Signal [2]
Figure 17. Coverage
View Open Signal [2]

On the web application, we have the option to render the google maps with collected data
overlay on it, together with the scale legend for data strength. Also there are filters on location,
operator and the Network type.

Figure 18. Coverage signal for Cluj -Napoca on Open Signal coverage Platform [3]

On the OpenSignal platform can be found several long period reports regarding 4G Availability
and 4G Speed ranked on countries where th e application has harvested data .

13

Figure 19. 4G Availability
Comparison Open Signal [3]
Figure 20. 4G Speed Comparison
Open Signal [3]

Sensorly
The Sensorly application enables the users to actively measure the parameters during a trip.
The feature allows the users to monitor their interest area and understand better how mobile
network works. By definition, Sensorly is a community sustained application.

Figure 21. Sensorly on Google Play [4]

The Sensorly is claiming that : “is the only app on the market that actively lets you map a trip”,
[5] and this re presents a nice to have feature , so that data to be harvested seamless whatever the
user is going.

14

Figure 22. Main Activity Sensorly [4]
Figure 23. Speed Test Sensorly [4]

On the web platform we have the option to filter coverage map result by location and operator,
also by the Network Type or switch to the Speed tests view with the same filters .

Figure 24. Coverage Signal for Paris on Sensorly [5]

Considering the features of above described products, it is easy to say they represents a
powerful signal measuring tool and speed test runner, but there is no information about samples,
like the sampling time, mobile device. Also there are situation when the subscriber may not be
connected to a cell tower, if the user is located on elevators or in the underground or even in remote
areas where there is no cell coverage. In this situations there is needed to handle this data and drawn
it to the map. This way will be easy to clarify where the area without signal is located.

With respect to the above mentioned applications, the system developed in this thesis add
supplementary features such as: the ability to sample the areas with no coverage, even that the
samples cannot be sent to server immediately, the client will store them until internet ac cess is
provided. Also the developed system features a more complex set of filters allowing to narrow the
results to a high level of specifications or the samples can be displayed by their sampling
timestamp.

15
4 Theoretical Fundamentals
Early technologies
There is a long history on transmissions by radio, but, a milestone has been set in December
1947, when William Rae Young and Douglas H. Ring, two engineers working at Bell Labs,
proposed an architecture of hexagonal cells for mobile phone usage in vehicle s that served as the
basis for modern cell phones. Unfortunately, at this stage, the technology to implement the
architecture did not exist.
It was needed twenty years to pass and another three engineers from Bell Labs, Joel Stanley
Engel, Richard H. Frenk iel and Philip Thomas Porter exploit the early proposals and developed a
more detailed system plan.
These new approaches were proposing that the cell towers use the directional antennas, which
had been developed meantime, to increase the channel reuse and to reduce the interferences.
In above approaches, the portable device had to stay in the geographic area within the coverage
is serviced by a one and only base station through the entire phone call time. This mean that there
is no continuity of service if the phone left the original cell area and moved to the another one.
Mobile network s
A mobile network consists of several systems where the last transmission leg is through radio
waves operating on a cellular network in which coverage areas are denoted cells. Every of these
area is served by at least one fixed transceiver, but in general these locations have three cells sites
or base transceiver stations (BTS). A mobile network handles user mobility through handovers,
switching the communication path fro m one cell to another, in an automatic manner.
The base transceiver stations are capable to provide the cell area with the network coverage
which will be used for voice transmission, data transmission and others.
By joining together these cells , is obtaine d a radio coverage over a large geographic area, that
resulting in capability of wide variety and number of portable transceivers equipped with mobile
broadband modems, l ike mobile phones, laptops, tablets to communicate between themselves,
fixed transceiv ers and telephones wherever these devices are in the network, via the base stations.
Even if the portable transceivers are moving though area of more than one cell during the
transmission, the connections will not be lost, it will be handed over from cell to cell to maintain
the wireless link.
In order to avoid the interferences and provide high quality services, typically, adjacent cells
are using different set of frequencies, however there is problem for two cells at distance operating
in the same frequen cy.
Network architectures
4.3.1 General architecture of a Mobile Network

Figure 25. General architecture of mobile network

MS/UE
RAN
CN
PSTN/
ISDN

16
The f igure represents the general architecture of a mobile network i n its simplified form it
includes Mobile Station s (MS) in 2G, or pieces of User Equipment (UE ) in 3G and 4G term inology ,
a Radio Access Network (RAN) and a Core Network (CN).
The MS/UE typically include all the necessary hardware , and software to ensure radio
communications over a base station and a SIM (Subscriber Identity Module) holding information
about a particular subscription and implementing security functions A Mobile Equipment (ME) is
unique identified by International Mobile Equipment Identity (IMEI) which is used during the
network registration.
Other terms referring to mobile stations are User Equipment or Terminal Equipment.
In order to establish a connection with mobile network, a mobile statio n should be equipped
with a Subscriber Identity Module (SIM). The SIM card holds information that is use at the mobile
station subscribing and identifies the requesting account. Along other details, in the SIM card it is
being stored the International Mobile Subscriber Identity (IMSI), a uniqu e number that enable other
users to contact a specific subscriber.
The Radio Access Network (RAN) represents the technology that links individual mobile
stations devices to a Core Network by using radio connections and wired interfaces . Usually a RAN
inclu des base statio ns connected to a ntennas that are designed to cover a specific area based on
their technical specifications , controllers and standardized interfaces connecting them.
The RAN’s main responsibility is to provide radio access, manage the resources along the radio
sites and transmit signals between MSs/UEs and CNs.
The Core Network (CN) defines as a telecommunication network’s core segment, which is in
charge of providing numerous services for accounts which are interconnected vi a the access
network. The p rimary function s that the core network has to provide are to control and route call s
and to implement security mechanisms such as authentication and encryption. Based on called
number the core network using its switching function ality has to decide the path through the call
will be routed.
Along with the above features, the core networks usually provide other functions like operation
and maintenance, allowing authorized operators to configure the network and gather different sort
of metrics and behaviors in the network or even to support a subscriber database that holds data
necessary on authentication process.
Global System for Mobile Network Architecture – GSM Architecture –
2G

Figure 26. 2G Network Architecture

The Base -Station Subsystem is the GSM’s RAN and it is composed of the following pieces of
equipment : the Base Transceiver Station (BTS) and the Base Station Controller (BSC)
A BTS consists o f several radio transmitters and receivers and their associated antennas that
communicate through radio link with device terminals. For each cell, there is a BTS that provides
radio coverage within that area.
MS/UE
BTS
BTS
BTS
BSC
MSC
VLR
EIR
HLR
AuC
BSS
NSS
PSTN
/ISDN

17
A BSC usually can be found in the same site as one of the BTSs ; it supervises them by
controlling their radio resources: allocating and deallocating channels and handling handover
procedures.
The Network Switching Subsystem (NSS) provides the key c ontrol and get together interfaces
for the mobile network. The NSS consists of: Mobile Services Switching Centre (MSC), Home
Location Register (HLR), Visitor Location Register (VLR), Equipment Identity Register (EIR),
Authentication Centre (AuC).
Mobile Se rvices Switching Centre is acting like a switching node in Public Switched
Telephone Network, but also provides several features in order to accommodate the user requests,
this way enabling call recording, authentication, call routing through a mobile devi ce or land line
telephone. Also interface to other MSC are implemented so that call destination located in another
network will still be able to reach the user.
The Home Location Register holds the information about each subscriber and their connection
state so that any incoming call to be correctly routed through the network and reach required
subscriber by originating terminal.
The Visitor Location Register defines as a temporary copy of the data stored in HLR, this data
is only available at the time when user is active registered to particular are covered by VLR.
The Equipment Identity Register determine whenever a specific mobile terminal is allowed to
register on network, based on IMEI, co ntained by SIM card as described earlier.
The Authentication Cent re is defined as a private database storing secret keys. Matching center
keys with SIM keys are needed in order to authenticate and cypher scripting signaling on radio
interface.
A GSM architecture also includes an Operation and Support Subsystem (OSS) describe an
element within the GSM network. Permanently connected to BSC and NSS, its role is to control
and monitor the overall network.
4.4.1 GSM Radio Access – Frequency Division Multiple Access (FDMA)
Frequency Division Multiple Access represents the most common analog system. Via this
access technique the spectrum is divided up into frequencies and assigned to subscribers. When
using FDMA only one user is assign ed to a channel at a given time and the channel will not be
reassigned until the initial call fi nished or it is handed -off to a different channel. [6] In GSM the
technique has been borrowed, allowing for a division of the frequency spectrum into distinct 124
carriers.

4.4.2 GSM Radio Access – Time Division Multiple Access (TDMA)
Call 1
Call 2
Call 3
Call 4
time

Figure 27. FDMA radio access

18
Time Division Multiple Access is an analog and digital compatible radio access technique.
TDMA optimize s spectrum usage and improve s its capacity by slicing each cellular communication
channel (frequency band) into a series of time segments. Using this scheme each user is assigned a
specific slice and is able to transmits information only during slot.
Given the high splitting frequen cy and small duration of time segments, the user perceives a
continuous communication channel.

Figure 28. TDMA r adio access

In GSM the TDMA concept imposes the division of a frame into 8 timeslots.
4.4.3 2G Radio Interface characteristics – GSM

Table 1. Some of the GSM ’s characteristics [7]
Metric Value
Data Rate for digitized speech 13 kbps full rate
6.5 kbps half rate
Traffic channel data rate 22.8 kbps full rate
11.4 kbps half rate
User data rate
(max) 9.6 kbps
14.4 kbps
Operating frequencies 800 MHz
900 MHz
1800 MHz
Number of carriers/Carrier spacing
124/200 KHz
4.4.4 Mobility Management in Global System for Communication (GSM)
From the RANs point of view in GSM, the mobile station has two defined states: idle and
connected. On both states the mobile station is able to perform the Radio Signal Strength (RSS)
measurement s. The RSS indicators measured are: RXLEV (the received signal strength measured
in dBm), and supplementary, in connected mode , RXQUAL (a measure of quality accounting for
the bit error rate). An alternate manner to represent in GSM the RXLEV value i s through the
Received Signal Strength Indicator (RSSI) , representing essentially labels ranging from 0 to 31,
associated each to some RXLEV intervals. The Android API is referring to this indicator as the
ASU level (Arbitrary Strength Unit) that can be computed using the CellSignalStrength class please
Call 1

Call 2
Call 3
Call 4
time
frequency

19
refer to Table 6. ASU level mapping in GSM below.
For cell selection and reselection purposes only the RXLEV measure is used whereas for
handovers in connected mode both of the aforementioned RSS measurements are computed. GSM
employs hard handover mechanisms.
The thesis aims to provide a monitoring solution mostly for the idle state, allowing
measurement for the RXLEV value through its expression in Android.
The GPRS system (General Packet Radio Service) was later introduced in 2G net works a
packet mode extension allowing end -to-end transport of packet switched data. Essentially it
includes an overlay of a packet –based air interface on the existing circuit switched GSM networks
and an introduction of a new GPRS core network. We refer t o [9] to a complete description.
From the RANs point of view, a GPRS MS can be in one of two states: idle and packet transfer
mode. On the radio interface the same two aforementioned parameters can be measured.
Universal Mobile Telecommunication System – 3G

Figure 29. 3G Network Architecture

The access network UMTS Terrestrial Radio Access Network (UTRAN) introduced a new
radio access technique there for it does no reuse elements of existing GSM radio network, yet there
are some useful comparisons.
Node -B is defined as a base station equivalent assuring broadly the same purpose,
communicate to subscriber terminal via radio link and with network using line links. It’s in charge
of providing radio resource for UMTS network and in order to fulfill this requirements UMTS
channel allocation technique is used. Also serves as processing power for all radio frequency
operations which are enabling communication to and from subscriber mobile device.
Radio Network Controller has the main purpose to control multiple Node -Bs by managing
resources for data calls, offer signaling services like call set -up and beside that also manages
switching and traffic routing function alities. RNCs are linked between via IuR interface, even if
mobile terminal moves between areas controlled by different RNCs, the handover processes are
now more performant because its kept within the UTRAN.
The Core Network of UMTS is defined by two domai ns circuit switched (CS) and packet
switched (PS).
Key elements of the Circuit Switched domain are represented by Mobile Services Switching
Centre (MSC) and Gateway MSC. Mobile Services Switching Center is defined as the switching
node that hookup the core network to network access part in which the mobile terminal is located.
Also may include or be in contact with Visitor Location Register (VLR) that temporarily holds
subscriber details regarding the mobile station currently served.
Gateway MSC re presents the switching node connecting UMTS core network to foreign circuit
switched network, public switched telephone network (PSTN) or integrated services digital MS/UE UTRAN Core
Network
GGS
N Node -B
Node -B
Node -B SGS
N RNC PS
Domain
HSS, OSA ,
CSE
GMS
C Node -B MSC/VL
R
VLR RNC CS
Domain
IuB
IuR
IuPS
IuCS

20
network (ISDN).
Key elements founded in Packet Switched domain are represented by Serving GPRS Support
Node (SGSN) and Gateway GPRS Support Node (GGSN).
Serving GPRS Support Node , main component of General Packet Radio Service(GPRS)
network which handles packets data around network like mobility management and authentication
process. SGSN repre sents for the user the access point to GPRS network and handles the protocol
conversion from Internet Protocol (IP) used in backbone network to the subnetwork dependent
coverage protocol (SNDCP), also the Logical Link Control (LLC) protocols used between S GSN
and mobile terminals.
The Gateway GPRS Support Node is responsible to link GPRS with external packet switched
networks, like Internet. GGSN allocates IP and holds temporarily information about active users
related with SGSN within mobile devices are cu rrently attached to.
4.5.1 UMTS – Code Division Multiple Access (CDMA)
Code Division Multiple Access is a multiple access technique based on the spread spectrum
technology. Transmissions are spread over the entire radio band, for each voice or data requests is
assigned a unique variable length code, by this assuring the differentiation between calls carried
over the same spectrum. CDMA increases efficiency usage of the spectrum capacity by allowing
all terminals to use all channels at any given time , but the pri ced paid is an increased interference
level.

Figure 30. CDMA radio access

4.5.2 Main 3G Radio Interface characteristics

Table 2. 3G. characteristics [10]
Value Observations
Data Rate 384 Kbit/sec
Up to 2Mbit/sec On in moving vehicules
Stationary or walking
Bandwith 5 MHz
3.84 MHz Considered
effective
Operating
frequencies Typically 2100 MHz –

Call 1
Call 2
Call 3
Call 4
Call 5

time
frequency

21

4.5.3 Mobility Management in Universal Mobile Telecommunications System
(UMTS)
From the RANs point of view in UMTS, the user equipment has two defined states: idle and
RRC _CONNECTED . For the idle state and the RRC connected state on dedic ated channels, the
UMTS’s RXLEV equivalent is called Received Signal Code Power (RSCP) . It is measured on dBm
and it represents power measured on a specific UTMS physical channel. As in GSM this value can
be measured in Android applications through an indi rect parameter called also ASU Level . Please
refer to Table 7. ASU level mapping in UMTS below.
The RSCP is also used in handovers. There are three types of handover in UMTS : hard
handover, soft handover and softer handover. In the situation where on the mobile station is in the
overlapping cell coverage area of two different base stations, soft handover allows for macro –
mobility ensuring more than one communication path between the UE and the RAN. During the
hard handover , as in GSM, the radio links are destroyed and then re -established.
Long Term Evolution – Architecture – 4G

Figure 31. 4G Network Architecture

4G represents the newest generation of high speed wireless broadband technology, at the point
when this paper is written, which offers a higher rate of data transfer that any of earlier technologies
so far. It accommodates more application that demands high speed connec tion in order to run as
designed.
Evolved Node -B (eNode -B) represents a combination of Node -B and RNC from 3G, and is the
only network hardware defined as part of radio access network E -UTRAN. This means there is no
need for dedicated RNC anymore. The eNod e-B is in charge of radio management functionality,
making this feature faster and goes to a simpler architecture.
The Serving Gateway (S -GW) is in responsible to route and forward data packets . Also has to
represent anchor point during inter -eNodeB handov ers also for mobility between LTE technology
and other networks.
Packet Data Network Gateway (P -GW) is the node that act as the interface between LTE
System Architecture Evolution network and other packet data networks, such as Internet or IP
Multimedia S ubsystem (IMS) networks. The PDN -GW provides connectivity to the user
equipment to external packet data network by being the point of exit and entry of all traffic
requested. [11]
MS/UE
E-UTRAN
Core Network
HSS
PCRF
IMS/
Internet
S-GW
P-GW
MME
eNode -B
eNode -B
SAE Gateway

22
The Mobility Management Entity (MME) is in charge of handling signaling messages for LTE
access -network. By interacting with Home Subscriber Server (HSS), is responsible to authenticate
the subscriber also selects the S -GW for mobile terminal at attach or during the intra -LTE handover.
The Home Subscriber Server is defined as a central database storing user and subscription plan
information. Provides functionalities for user authentication and access authorization.
Policy and Changing Rules Function (PCRF) is a node which determine policy rules in the
network and aggregates information to and from the network in order to fulfil several features.
Based on rules and policies it is able to efficiently and dynamically route and prioritize network
traffic.
4.6.1 4G LTE Radio Access – Orthogonal Frequency Division Multiplex (OFDM)
FDM forms the basic signal format used within 4G. This is modified to provide the multiple
access scheme: Orthogonal Frequency Division Multiple Access used in downstream. For upstream
it is use another alteration: Single Carrier Frequency Multiple Access (SC -FDMA)

Figure 32. OFDMA vs SC -FDMA

Orthogonal Frequency Division Multiple Access it’s a technique of data multiplexing used in
4G mobile networks and combines frequency and time multiplexing access modalities.
It’s optimized for multiple access in order to allow sharing spectrum resources b etween mobile
terminal.
Single Carrier Frequency Multiple Access is similar to OFDMA, divides bandwidth into
multiple parallel subcarriers maintaining the orthogonality of the subcarriers by addition of the
cyclic prefix as a guard interval. The signal whi ch is assigned to each subcarrier is a linear
combination of all modulated data symbols transmitted at the same time instant. [12]
Main difference between it that SC -FDMA has an additional Discrete Fourier Transform
(DTF) proces sing step added before OFDMA processing. A DTF is performed by pre -coder before
the channel is multiplexed with the reference signal subcarriers by first mapping them to the
properly physical resources and then to OFTM symbol and slots within each frame. [12]
4.6.2 4G Radio Interface characteristics
Table 3. 4G Radio Interface Characteristics [13]
Value Observations
Data Rate 100 Mbps
50 Mbps Max downlink
Max uplink
Channel
Bandwidth 1.4 MHz
3 MHz
5 MHz –


time
symbol

OFDMA
SC-FDMA
frequency
frequency

23
10 MHz
15 MHz
20 MHz –


Operating
frequencies 850 MHz
1800 MHz –

4.6.3 Mobility Management in Long Term Evolution
A mobile station , from the E -UTRAN’s point of view is considered to be in one of the two
states: RRC_IDLE and RRC_CONECTED. When in RRC_IDLE state, the user equipment is not
connected to any cell and the eNode -B has no Radio Resource Control (RRC) context. In the other
side, when the mobile station is in RRC_CONNECTED state the mobile terminal is connected to
a specific cell and the eNode -B has the RRC context.
The measurements that the mobile station is performing when in RRC_ IDLE state, are one of
both of following: Reference Signal Received Power (RSRP) and Reference Signal Received
Quality (RSRQ). For a particular cell, RSRP is defined as the average power of the Resource
Elements (RE) that carry cell -specific Reference Signals (RSs) within the considered bandwidth.
Similar to RSRP measurement, the RSRQ metric is mainly used for ranking candidate cells in the
neighbor in accordance with their signal quality. [14]
As for other networks the RSRP value can be measure in Android using the indirect parameter
named ASU level. Further reference are defined at Table 8. ASU level mapping in LTE below.
A UE must monitor the persistence of multiple cells and perform cell reselection to ensure it is
camped to the suitable cell. During the “camped” state, the mobile still monitor RSRP and RSRQ
of the other cells to proceed on cell reselection if needed. The RSRQ measurement provides extra
information when the handover or cell selection cannot be performed only on RSRP.
Parameters defined in Android API for handling radio interface
measurements in idle mode in 2G, 3G and 4G net works
4.7.1 Signal Strength as dBm – dBm Level
The DBm signal strength level represents the power of received signal (including noise power
and unwanted signals) . DBm stands for decibel milliwatts , and is used as a conversion to measure
power. The formula is:

𝑝[𝐷𝐵𝑚 ] = 10 · 𝑙𝑜𝑔10( 𝑃[𝑊] / 1𝑚𝑊 ) (1)

Valid values in mobile networks are bounded by -120 DBm, at lower end and -51 DBm on
higher end. Based on DB m level there is a signal strength equivalency table.

Table 4. Signal Strength Classification [15]
𝑫𝑩𝒎 𝑽𝒂𝒍𝒖𝒆 𝑪𝒍𝒂𝒔𝒔𝒊𝒇𝒊𝒄𝒂𝒕𝒊𝒐𝒏
-101 or less Very weak
-100 … -91 Weak
-91 … -81 Average
-80 or more Good

24
4.7.2 Arbitrary Strength Unit – ASU Level
Arbitrary Strength Unit (ASU) is an Android integer value proportional to the received signal
strength measured by the mobile phone.
The ASU level indicate the measured parameters depending on technology generation as
below, in Table 5. ASU level mapping .

Table 5. ASU level mapping on technologies
Technology Measure Parameter
2G RXLEV
3G RSCP
4G RSRP

In GSM the ASU Level defines the Received signal strength indication (RSSI), as defined in
below in Table 6. ASU level mapping in GSM in GSM, comply to [8].

Table 6. ASU level mapping in GSM [8]
𝑫𝑩𝒎 𝑽𝒂𝒍𝒖𝒆 [𝒅𝑩𝒎 ] 𝑨𝑺𝑼 𝑳𝒆𝒗𝒆𝒍
-113 or less 0
-111 1
-109 … -51 2 … 30
-51 or greater 31
not known or not detectable 99

Valid values are between 0 and 31, ASU=99 represents a special situation where signal
strength is unknown.
In UMTS the ASU level defines Received signal code power (RSCP), as defined in below
in Table 7. ASU level mapping in UMTS comply to [8].

Table 7. ASU level mapping in UMTS
𝐃𝐁𝐦 𝐕𝐚𝐥𝐮𝐞 [dBm] 𝑨𝑺𝑼 𝑳𝒆𝒗𝒆𝒍
-120 or less 0
-119 1
-118 … -25 2 -95
-24 96
not known or not detectable 255

Valid v alues are between 0 and 34, ASU =255 represents a special case where the
measurement cannot be performed.

In the case of LTE connection, ASU level valid values is between 0 and 97. The ASU level
is computed as below in Table 8. ASU level mapping in LTE comply to [8].

Table 8. ASU level mapping in LTE [8]
𝑫𝑩𝒎 𝑽𝒂𝒍𝒖𝒆 [dBm] 𝑨𝑺𝑼 𝑳𝒆𝒗𝒆𝒍
-140 or less 0
-139 1
-138 … -44 2 … 96
-43 or greater 97
not known or not detectable 255

25
4.7.3 Reference Signal Received Quality (RSRQ)
In the case of LTE mobile networks, the RSRQ value can be obtained. The values for the
parameter are defined below in Table 9. RSRQ mapping in LTE and comply to [8].

Table 9. RSRQ mapping in LTE
𝑫𝑩𝒎 𝑽𝒂𝒍𝒖𝒆 [dBm] 𝑨𝑺𝑼 𝑳𝒆𝒗𝒆𝒍
-140 or less 0
-139 1
-138 … -44 2 … 96
-43 or greater 97
not known or not detectable 255
4.7.4 Signal Strength Level
Android API is defining an overall signal strength level with valid values between 0 and 4.
Usually this metric is used for representing mobile phone signal bars.
Based on ASU level the level can be computed as presented in below Table 10. Overall Level
mapping .

Table 10. Overall Level mapping [15]
𝑨𝑺𝑼 𝑽𝒂𝒍𝒖𝒆 𝑶𝒗𝒆𝒓𝒂𝒍𝒍 𝒒𝒖𝒂𝒍𝒊𝒕𝒚 Overall value
1 No signal strength or unknown 0
1> Poor 1
5> Moderate 2
8> Good 3
12> Great 4
99 No signal strength or unknown 0

26
5 Implementation
Technologies
5.1.1 Server component
Java
Java is a programming language originally developed in 1995. Shortly, java is guaranteed to
be Write once, run anywhere being to run on any machine able to run Java Runtime Environment
(JRE).
Java is Object oriented, platform independent, secure, architecture neutral, portable,
multithreaded, interpreted.
Platform independent, unlik e other programming languages, when Java code is compiled, it is
compiled i nto a platform independent byte code, that can be interpret by any platform capable of
running Java Running Machine(JMV).

GitLab – Version Control
Git represents a version control t ool for tracking changes in staged files and coordinating work
on these files between multiple people.
GitLab represent a web -based open source, git repository with several features like issue
tracking , developed by GitLab Inc.

Maven
“Maven, a Yiddish wo rd meaning accumulator of knowledge, was originally started as an
attempt to simplify the build processes in the Jakarta Turbine project. There were several projects
each with their own Ant build files that were all slightly different and JARs were checked into
CVS. We wanted a standard way to build the projects, a clear definition of what the project
consisted of, an easy way to publish project information and a way to share JARs across several
projects ”. [16]
Maven main functionalities are describing the process of building the software and describing
its dependencies . Using an Extensible Markup Language ( XML ) file, named pom.xml, Maven
describes the components to build, it’s dependencies , the directories and the add-ons required and
dynamically download libraries from one or more repositories.
The server needs following dependencies :

<dependency >
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-thymeleaf </artifactId >
<version>LATEST</version>
</dependency >
<dependency >
<groupId>org.springframework </groupId>
<artifactId >spring-jdbc</artifactId >
<version>LATEST</version>
</dependency >
<dependency >
<groupId>com.google.code.gson </groupId>
<artifactId >gson</artifactId >
<version>2.8.2</version>
</dependency >
<dependency >
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-web</artifactId >
</dependency >

Figure 33. pom.xml partial structure

27

Spring framework
Spring makes it easy to create Java enterprise applications. It provides everything you need to
embrace the Java language in an enterprise environment, with support for Groovy and Kotlin as
alternative languages on the JVM, and with the flexibility to create many kinds of arch itectures
depending on an application’s needs.
“The Spring Framework is divided into modules. Applications can choose which modules they
need. At the heart are the modules of the core container, including a configuration model and a
dependency injection me chanism. Beyond that, the Spring Framework provides foundational
support for different application architectures, including messaging, transactional data and
persistence, and web. It also includes the Servlet -based Spring MVC web framework and, in
parallel , the Spring WebFlux reactive web framework. ” [17]

Model -View -Controller MVC Framework
The Spring MVC framework provides model view architecture and ready components that can
be used to develop unlimited type of web applications. The MVC pattern is separating the different
aspects in application, yet keep coupling between them:
 Model – encapsulates the application data;
 View – represents the rendering model data using HTML output as the client’s browser
can interpret;
 Controller – is responsible of user request processing and building the required model
passing it to view for rendering.
The Spring MVC framework is designed around a Dispa tcher Servlet that is in charge of HTTP
requests and responses.

Thymeleaf template
Thymeleaf is a Java library. It is an XML/XHTML/HTML5 template engine able to apply a
set of transformations to template files in order to display data and/or text produced by your
applications.
The main goal of Thymeleaf is to provide an elegant and well -formed way of creating
templates. In order to achieve this, it is based on XML tags and attributes that define the execution
of predefined logic on the DOM (Document Object Model), instead of explicitly writing that logic
as code inside the template.

Hypertext Markup Language – HTML
Represents the standards language used for creating web pages and web applications. Providing
a wide area of elements, HTML can fit large set of needs, designs and behaviors .

Cascading Style Sheets – CSS
CSS is a style sheet language used for defining the look of a document written in HTML. Using
CSS the HTML elements can be stylized by change of text font, colors , text size behavior and
animations.

Java Script – JS
Representing a dynamic computer programing, is a part of web page, whose implementation
allows interact to user and make dynamic pages. Like java, it is and interpreted programming
language with object oriented capabilities.

Persistent data component – Database
A database is an organized set of data, remote stored and accessible electronically. Databases
are used in order to store persistent data required by an application . The data written in database

28
will not be affected by change of application code, application version deployed or server machine
restartin g.

MariaDB
MariaDB is one of the most popular databases server in the world and currently it is being
developed by original people of MySQL. It is developed as open source software and provides an
SQL interface in order to access data.
4.1.3 Client compon ent
Android
Android represents a mobile operating system developed by Google, that use modified version
of Linu x kernel and extending several open source software compatibles designed for mobile
device hardware.

Gradle
Gradle represents an open -source bui ld automation system that is using Groovy based domain
specific language instead of XML for declaring the project configuration.
Beside default Android dependences, the application requires several other:

implementation 'com.google.code.gson:gson:2.8.4'
compile 'com.loopj.android:android -async-http:1.4.9'
compile 'fr.bmartel:jspeedtest:1.32.1'

Figure 34. build.gradle partial structure

Java Google JSON – GSON
Gson represents a Java library that is used to convert java objects into JavaScript Object
Notation ( JSON) representation and also can be used to convert a JSON string to its equivalent
Object.

Asynchronous HTTP Client
An asynchronous callback -based Http client for Android built on top of Apache’s HttpClient
libraries. All requests are made outside of your app’s main UI thread, but any callback logic will
be executed on t he same thread as the callback was created using Android’s Handler message
passing. You can also use it in Service or background thread, library will automatically recognize
in which context is ran. [18]

bmartle:jspeedtest library
Represents an open source speed test client library that help determine your connection speed
on both upload and download with configurable file sizes, so that measurement of upload
connection to be parametrized.
Tools
IntelliJ IDEA Community
IntelliJ Idea Community is a free licensed Integrated Development Environment (IDE) used
for developing software.
In order to launch a Spring project, there are several options to choose. Usually when a spring
project is started from scratch, it is used th e Spring Initializer wizard. This initializer gives the
option to choose between Apache Maven or Gradle project, using Java, Kotlin or Groovy as
language and the version of spring boot do you want to use. Then, through the wizard it is possible
to add need ed dependenc ies, for example MVC, database connection, security patches and other A

29
project will be generated and it is possible to import it in the IDE and start working on it.

Android Studio
“Android Studio is the official Integrated Development Environment (IDE) for Android app
development, based on IntelliJ IDEA. On top of IntelliJ's powerful code editor and developer tools,
Android Studio offers even more features that enhance your productiv ity when building Android
applications ”. [19]
Android Studio is common used by android applicati on developers in order to write and test
their application. The tool comes with default tools for monitoring physical device activit y, create
emulated devices operating on different platforms, display sizes, system version or Application
Programming Interface ( API) level as well as simulate their state and technical specifications.
The IDE can be also used to develop applications on several other platforms like tables,
Android Wear Watches, televisors that run android compatible system.
A project can be started using an initial project configurator, offered by Android Studio, where
can be choose several setting and properties that the application will have to respect . Here is chose n
the name, the type of the platform that applications will run, mobile device, or Wear device or
televisors, also here is set the minimum required API leve l for the device in order to run specific
application. In android developing , API level refers mostly at Android operating system version,
latest Android on mobile devices at the time when this is paper is writ ten is Android Oreo 8.1,
featuring API level 2 7.
Continuing the initial wizard, is the view where an activity can be picked among several default
activities layout and the activity name. Usually, the activity created this way is the mai n activity
and is flagged with category. LAUNCHER which means the application will open with starting this
activity.

Figure 35. Create New Project Android Wizard

Oracle Virtual Machine
“VirtualBox is powerful Cross -platform Virtualization Software for x86 -based
systems.<<Cross -platform>> means that it installs on Windows, Linux, Mac OS X and Solaris x86
computers. And <<Virtualization Software>> means that you can create and run multiple Virtual
Machines, running different operating systems, on the same computer at the same time. For
example, you can run Windows and Linux on your Mac, run Linux and Solaris on your Windows
PC, or run Windows on you Linux systems.” [20]

30
Usually a virtual machine is used in order to run Operati ng Systems different that host
operatin g system. For example, to run a Linux Machine on a computer that runs on Windows as
operatin g system. Linux systems are well known for their reliability, low power consumption, well
management of resource, all this poin ting that usually a server will run on a Linux machine for
high performances.

DBeaver Community Edition
DBeaver represents a free, cross -platform, open source management tool for databases
developers and administrators. The tools feature a Graphical User Interface(GUI) which make jobs
like, creating, dropping, truncate, alter structure of a data base a lot easier. Also, the tool enables
you create SQL queries and run them, via integrated SQL editor with syntax highlighting and
autocomplete.

Postman
Postman is standalone application, a great tool for prototyping APIs along with powerful
testing features. The tool is used for interacting with HTTP calls via a friendly GUI for creating
requests and interpret respective responses. When creating a request, there are easy ways to
configure the content -type, headers, request body and/or cookies, which will be then sent via HTTP
to your custom endpoint expecting the response and interpret it. It can be chosen between POST
request, GET, PUT, and other restful methods , along with body request content -type: JSON, text,
HTML, JavaScript application, XML or others.
General Implementation
The set of the developed application s follows a server -client architecture , where the client is
installed on mobile terminal and the server section runs on a machine along with the database
instance.

Figure 36. Sampling sequence Diagram

The sequence of one sent sampling is presented in Figure 36. Sampling sequence Diagram and
described below. At the server startup the application starts sampling the radio interface parameters
values and retrieve the current locat ion of the terminal. If the sample in valid it will store in local

31
database, an instance of LiteSQL. Next the sampled is sent via HTTP to the server.
The server handles the request and store it the MariaDB instance then send success HTTP call
back to the c lient, at this moment the client will delete the respective sampled from the local
database.

The data transfer rate test activity, the sequence is defined below:

Figure 37. Transfer Data Rate sequence diagram

The client is implement the feature to measure the transfer data rate. For this the upload and
download button will be hit in order. During the test the User interface values are updated with
current data rate as well as the progress bar, at the finalize, the mean data rate will be computed
and displayed . When both test are done, the clie nt may proceed and sample the radio interface
properties along with the terminal current location coordinates.
The server is handling the POST HTTP method by storing the re ceived object to the database.

The reason that these data are collected is for the display and analyze them, so that relevant
conclusions are summarize and implement the better solution.

Figure 38. Sequence to render the collected data

32
The sequence diagram in the Figure 38. Sequence to render the collected data , is explaining
how the data are retrieved from the database and displayed i n browser for viewing. The server
handles the HTTP GET method coming from the browser along with filters values and interrogates
the database for result set. The MariaDB instance performs a complex query to return re requested
entries. This data is sent ba ck to the server which is forward them further to the browser for
interpretation.
Client implementation – Mobile Network Scanner Application
The client is represented by the Android Application named Mobile Network Scanner.

Figure 39. Mobile Networks Scanner Logo

To install the application there are several requirements that mobile terminal should fulfil. First
the device must run on Android as operati ng system, version of the system should be at least
Andr oid Oreo , API level 2 6. Also, the device should be equipped with a SIM card module to fit
the SIM card and read it also there is required that the mobile device to have an integrated GPS
module.
Also, the application need permission to access phone state a nd device location. The phone
state permission is used for retrieving the current serving mobile network radio interface parameters
 Radio frequency channel number;
 Signal Strength values ;
 Device Identification;
 International Mobile Equipment Identity –IMEI;
 Terminal manufacturer and model;
as well as SIM card details:
 Network operator name;
 International Mobile Subscriber Identity – IMSI ;
 Network class;
 Numeric operator name

The location access permission is required in order to check the current GPS location of the
device, so that the measurements could be rendered on the map according to the mobile coordinates
at the time when the sampling was sent.

33

Figure 40. Requesting
Phone State Permission Figure 41.. Requesting
Location Permission Figure 42.Case when
access was denied

Without allowing to the app the required permission the application could not operates as
expected and will automatically close before any other activity.

The source code of the client has the project structure presented in Figure 43. Client
Application Project Structure in below section.
In the first package, activities, are located the two activities defined for the application. The
main activity is represented by t he ConnectionLevelsActivity class. The application is started w ith
this activity and the dynamic content is retrieved to populate the fields describing the signal
strength, network type as well as device information and its current location in double longi tude
and latitude values. The view content elements are, from top to bottom: Signal Information, here
is included the Overall Signal Strength, received signal power in dBm, ASU level, operator name,
network class, network type name and the device model and manufacture. Below this the GPS
current location is represented in double longitude and latitude values. As well, in the main activity,
bottom section, is located the switch that start the sampling process.

Figure 43. Client Application Project Structure

34
In the toolbar can be find the settings icon the Speed Test feature. By clicking the settings icon,
the content for application properties is overlaid on main activity. This view is allowing to
 change the IP address or hostname of the server towards the HTTP POST requests will
be sent;
 enable or disable the retry job for failed sent measuring samples;
 enable or disable the manual position override;
 the time interval at which the sampling is complete;

Over the server URL several validations are made checking if the input value is a correct IP
address or hostname. If the URL is not valid, the new value is not taken in consideration, the default
value is not altered.
The switch for failed send samples retry job, stars a ser vice that tries to resend samples for
which the HTTP post has failed. In order to fulfill this, during the service following are checked:
 internet connection is established;
 there are failed samples in local database;
 the retry job is enabled from settings view;
Using the custom location coordinates, the application allows the users manually override the
device coordinates. The coordinates can be overridden by two ways: location can be chosen in
google maps fragment or longitude and latitude can be manually input in their edit fields. This
feature should be used when there is no GPS signal, like underground parking lots, subways or
elevators.

Figure 44. Mobile
Network Scanner Main
Activity
Figure 45. Mobile
Network Scanner Settings
Figure 46. Mobile
Network Scanner using
override location coordinates

During the time then the activity is up, several services running to provide the activity with
necessary data information. Since the app is started the service class named:
GSMDetailsToUiService is enabled. In the execution loop the service interrogates for current
network parameters providing via broadcast intent, the values for User Interface (UI) content.

The location lis tener is defined in class named CustomLocationListener which implements the
Location Listener interface. Inside are override the on location changed method and on provider

35
disabled method. The location listener is aware for every change of the device and when this
happens the on location changed is called, updating the current location used and the UI GPS
coordinates fields. Also, if the GPS provider is disabled, the application prompts for re -enable the
GPS function.
In the moment when the bottom switch i s turn on, the service called MainBackgroundService
will start. This thread will send the samples along with coordinates and device information to
server, via HTTP client. This service is configured to run in background, so even if the user shuts
off the screen or other applications are displayed. this thread keeps running.
The following defined activity is defined in SpeedTestActivity class. In this activity the client
is checking the data rate connection. In order to initiate the process, the upload butto n will be
pressed. During the connection check, both buttons are disabled, so that the test do not interfere,
and the progress bar located at the bottom section in activity indicates the test complete percentage.
The current rate is displayed by the first value under the button, following that the second value to
be populated with the actual mean data rate speed.
After the upload test is one hundred percent complete, the download speed test will be
launched. The elements in the activity follows the same pr operties as for upload test.
As the speed test results are collected, the “Send this data” enables and by hitting the button
the speed test results are sent to the server.

Figure 47.Speed Test Activity During
Upload Figure 48..Speed Test Activity during
Download
Server implementation – Mobile Network
The server section is a Java application, using several dependencies like Model View
Controller, Java Database Connecting (JDBC), front end template la nguage.
The structure of the project is presentment in figure 24.

36

Figure 49. Server Application Project Structure

In the MobileNetwork Server class is located the main method that start the server once it is ran,
Once the serve r is started up the IP on which the server is running will be printed on console. This
IP is also the machine IP on which the application is started, by default a HTTP server starts on
8080 port, but this parameters can be adjusted in application.propertie s file, property is named:
server.port .
In the LocalOperation class can be find the operation that handles web GET HTTP requests.
By using GET method to the server IP address appended with the port, or if there is used an alias
or Domain Name System (DNS) , only the hostname, the browser will create a request to the server
and the response will be a HTML web page controlled by MVC in this class.
During this operation is executed, data stored in database will be retrieved, sorted and then
passed to the web se ction, where browser will render the page based on controller specifications
and template language indications .

Figure 50. WEB Interface of the server

In the webpage can be find several dropdown lists that allows filtering rendered samples based
on selected values. It is available to show the samples gathered by as specific mobile terminal, or
specific manufacture. There is an option to render only sampl es harvested on a given network
operator or samples that was retrieved during a given time period. Even better, these all filters can
be combined to access a very narrow range of samples .

37
Regarding values rendered, there are several option also. The page a llows to view samples
rendered using DBm level of the signal, or ASU level of the sample and the overall signal value.
As the application also supports speed test result, you can choose to view data for upload data rate
or download data rate, also consider ing mobile device filtering.

In the IncomingOperations class are located POST methods handler at which the client is
sending request, with application/JSON as content -type.
There are three methods, each with their associated endpoint path.

Table 11. Mobile Network Server exposed endpoints
path User for:
/deviceProperties Endpoint that stores the device properties
/speedTestRate Endpoint that stores the speed test results
/postLocationAndLevels Endpoint that stores the mobile network parameters

The d evice properties endpoint is used by the client at the first startup of the client application,
in order to send static information regarding mobile device properties as: model, manufacture,
IMEI and such others. In the moment that a POST request is sent to this endpoint, the controller
will handle the request by storing the device properties in persistent data storage.
Below is represented the body request for this en dpoint:

{
"device" :"z2_plus" ,
"deviceId" :"860988033965968" ,
"deviceManufacturer" :"ZUK",
"deviceModel" :"Z2 Plus" ,
"imei":"860988033965968" ,
"mcc":"226",
"mnc":"10",
"networkOperatorName" :"orange" ,
"simCountryISO" :"ro",
"simOperator" :"22610",
"subscriberID" :"226102302024473"
}

Figure 51. Valid JSON body request for /deviceProperties path

The Speed Test rate endpoint is used in the moment when a client ran a speed test and the result
is sent to server. The controller is saving the speed test result into persistent database along with
other information about the location of the mobile terminal at the sampling moment, network
operator, subscriber ID and several others.
Below is represented the body request for the speed test endpoint:

{
"internetRates" :{
"downloadRate" :7.62,
"uploadRate" :15.18
},
"coordinates" :{
"lat":23.568,
"lng":0.0
},
"id":0,
"signalStrenght" :{
"asuLevel" :25,
"deviceId" :"860988033965968" ,
"gsmRFchannelNumber" :79,
"lteAbsoluteRFchannelNumber" :0,
"networkOperator" :"22610",
"networkOperat orName":"orange" ,
"networkTypeClass" :"2G",
"networkTypeName" :"EDGE",
"rsrp":0,
"rsrq":0,
"rssnr":0,
"signalDbm" :-63,
"signalStrengthLevel" :4,
"simOperator" :"22610",
"subscriberId" :"226102302024473" ,
"timingAdvance" :2147483647 ,
"wcdmaAbsoluteRFchannelNumber" :0
},
"timestamp" :0
}

Figure 52. Valid JSON body request for /speedTestRate path

38
Regarding postLocationAndLevels endpoint it can be considered the most important endpoint
in the application. To this path are sent all samples measured by the client . This path’s controller
stores the relevant data collected in mobile terminal sampling process.
Valid body request to th is endpoint:

{
"coordinates" :{
"lat":46.77708002453519 ,
"lng":23.616360145861172
},
"id":1,
"signalStrenght" :{
"asuLevel" :22,
"deviceId" :"860988033965968" ,
"gsmRFchann elNumber" :79,
"lteAbsoluteRFchannelNumber" :0,
"networkOperator" :"22610",
"networkOperatorName" :"orange" ,
"networkTypeClass" :"2G",
"networkTypeName" :"EDGE",
"rsrp":0,
"rsrq":0,
"rssnr":0,
"signalDbm" :-69,
"signalStrengthLevel" :4,
"simOperator" :"22610",
"subscriberId" :"226102302024473" ,
"timingAdvance" :2147483647 ,
"wcdmaAbsoluteRFchannelNumber" :0
},
"timestamp" :1530986716158
}

Figure 53. Valid JSON body request for /postLocationAndLevels path

The following package contains the database manager. The data access object interface
contains five methods.
The methods that write in the database are the following:
The method called insertLocationAndLevels , receive a LocationAndLelvesV2 as parameter
and stores the object into SIGNAL_LEVEL table in the database . The following method called
insertDeviceProperti es, receive a DeviceProperties as parameter and stores the object into
DEVICE_PROPERTIES table in the database. The insertSpeedRates stores a InternetRateObj into
SIGNAL_LEVEL table in the database.
The methods reading from the database is presented below:
The getFilteredDetails operation retrieves the levels and location entries from database based
on the array of strings containing the filters, which is received as parameter. The getDeviceDetails
method retrieves the device properties entries from databas e table. The JdbcManager implements
the DAO interface action directly to database tables to insert java objects or do interrogations over
the tables.
Regarding the model package, it contains the java objects classes, like Coordinates ,
SignalStrenght or InternetRate .
In the resources are located miscellaneous files starting with Spring beans XMLs or JavaScript
documents to HTTP pages.
In order to webpage to be rendered there is needed some HTML documents, along with
JavaScript files and CSS as well. Here is used an HTML page, index.html , describing the layout of
the webpage returned when the server is hit with the GET request. The file contains several web
elements. Starting in head of the document, where title of the page is described. Also in the head
will be loaded the JavaScript and the CSS files by link their path. In the following are located the
dropdown selectors used for filter results and rendered data. Next in the layout is arranged the
google maps frame on which the data is rendered. This Fragme nt is handled by the “map.js”
JavaScript document. In this file is controlled the attributes of the data overlaid on google maps.
Styling attributes for the map eleme nt re specified in the map.css document, as well as for legend
or the loader, the attribut es are defined in their corresponded CSS file.

39

Database implementation – MariaDB
In order to store the data that is needed, a database instance is configured. It was chosen a
MariaDB instance, due the software’s multiple feature and proved reliability on small to medium
application. Once installed the database instance requires configu ration of a database inside it,
along with access credentials and authorization level. When database is created, following step is
to create tables. In this situation two tables were needed:

Figure 54. DEVICE_PROPERTIES table

Figure 55.SIGNAL_LEVEL table

To create the above structures there is needed two SQL queries defined in the Figure 56. SQL
to create SIGNAL_LEVEL table and Figure 57.SQL to create DEVICE_PROPERTIES table :

CREATE TABLE `SIGNAL_LEVEL` (
`index_id` int(11) NOT NULL AUTO_INCREMENT,
`latitude` double NOT NULL DEFAULT '0',
`longitude` double NOT NULL DEFAULT '0',
`signalDbm` int(11) NULL DEFAULT NULL ,
`signalStrengthLevel` int(11) NULL DEFAULT NULL ,
`asuLevel` int(11) NULL DEFAULT NULL ,
`timingAdvance` int(11) NULL DEFAULT NULL ,
`Rssnr` int(11) NULL DEFAULT '0',
`Rsrq` int(11) NULL DEFAULT '0',
`Rsrp` int(11) NULL DEFAULT '0',
`networkOperator` varchar(100) NULL,
`networkTypeClass` varchar(100) NULL,
`networkTypeName` varchar(100) NULL,
`networkOperatorName` varchar(100) NULL,
`uploadRate` double NULL DEFAULT NULL ,
`downloadRate` double NULL DEFAULT NULL ,
`simOperator` varchar(100) NULL,
`subscriberId` varchar(100) NULL,
`deviceId` varchar(100) NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY (`subscriberId` )
) ENGINE=InnoDB
AUTO_INCREMENT= 1274
DEFAULT CHARSET=utf8mb4
COMMENT= 'stores signal level on area with LatLng'

CREATE TABLE testDB.DEVICE_PROPERTIES (
deviceId varchar(100) NOT NULL ,
imei varchar(100) NULL,
mcc varchar(100) NULL,
mnc varchar(100) NULL,
simOperator varchar(100) NULL,
networkOperatorName varchar(100) NULL,
networkCountryISO varchar(100) NULL,
subscriberId varchar(100) NULL,
deviceModel varchar(100) NULL,
deviceManufacturer varchar(100) NULL,
device varchar(100) NULL,
networkTypeName varchar(100) NULL,
networkClass varchar(100) NULL,
networkType varchar(100) NULL,
PRIMARY KEY (`subscriber Id`)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COMMENT= 'stores the device and SIM properties’

Figure 56. SQL to create
SIGNAL_LEVEL table Figure 57.SQL to create
DEVICE_PROPERTIES table

The entity relationship diagram in database used by the application is the Figure 58. Entity
Relationship in database :

40

Figure 58. Entity Relationship in database

The primary key for both tables is represented by subscriberId field. This value should be
unique so that no exception to be thrown. Also on this fields the join queries are executed to retrieve
the data.

41
6 Experimental Results
Database Content
During the BETA release of the system, the server handled over 3000 samples, received from
a total number of 8 unique subscribers .
Holding the samples information, below is displayed the current a preview of the current
content stored in the database in table SIGNAL_LEVEL is available below.

Figure 59. SIGNAL_LEVEL content pr eview

The table DEVICE_PROPERTIES content is displayed below:

Figure 60. DEVICE_PROPERTIES table content Preview
Filter ed Results
The server implementation provides the feature so the form the high number of acquired
samples stored and database, to view just a specific set based on o ne of the following criteria:
6.2.1 Device model
Is important to know the terminal on which the measurements were done , because different
classes of device have limitations and the measured samples may not be relevant;

42

Figure 61. Samples result filtered by Device Model

In the Figure 61. Samples result filtered by Device Model , the displayed samples has been only
sent by the Huawei PRA -LX1 device model.
6.2.2 Device manufacturer
In order to include or exclude a specific User Equipment from the result set;

Figure 62. Samples result filtered by Device Manufacturer

In the Figure 62, from the total of samples, only the measurement reported by mobile devic e
manufactured by Zuk are displayed .

43
6.2.3 Network Operator
If there are need information gathered only when connected to the interested mobile network .

Figure 63. Samples result filtered by Network Operator

In the Figure 63, are only represen ted the samples measured on Digi Mobile mobile network
operator.
6.2.4 Network class
This filter is used when there is interest only one of current network classes (2G, 3G, 4G) .

Figure 64. Samples result filtered by Network Class

In the Figure 64 the represented samples were measured on the second generation of the mobile
networks.

44
6.2.5 Netw ork implementation technology
This filter enables to view the measurement made then connected to a spe cific mobile network
technology.

Figure 65. Samples result filt ered by Network Implementation

In the Figure 65, due the applied filter , are visible only the samples acquired during the
device had LTE connectivity.
6.2.6 Time Interval
This filter represents a big necessity in monitoring the mobile systems p erformances and
coverage; as discussed, the mobile network might be affected by a large number of participantes ;
e.g: traffic jam or large festivals.
The granularity of the time period is one hour.

Figure 66. Samples result filt ered by time period

45
The Figure 66 is displaying only the samples acquired during the specified time period: 05 –
July-2018 at midnight to 06 -July-2018 at the 11 PM . The granularity of the time period is one hour.
Rendered Type
The implementation of the WEB page allows to choose what type of data to be overlaid on the
map. The options are:
6.3.1 Overall Level:
Is rendered by default at the page initialization, representing a unit used in Android for
displaying the network coverage information to the user interface.

Figure 67. Overall signal strength overlay

In the above Figure 67 is represented the overall signal strength level of all the acquired
information. Referring to Table 4. Signal Strength Classification this metric can take values from
0 to 4. In the right corner is presented the color legend for this metric as follows:

Table 12. Over all Level representation color s
OVERALL LEVEL VALUE COLOR
0
1
2
3
4

6.3.2 ASU level
Representing the RXLEV in GSM, the RSCP in UMTS and RSRP in 4G.

46

Figure 68. ASU level overlay

In the Figure 68 representation are displayed the ASU value of each acquired sample. Referring to Table
6,Table 7 and Table 8 in mobile network this metric values range is from 0 to 99. The colors use to draw
the va lues are represented in Table 13.
Table 13. ASU representation colors
color xx
ASU value 0 97 99 or 255
6.3.3 dBm value

Figure 69. dBm value overlay

In the Figure 69 is represented the dBm value of the measurement results. The colors used to
fill the samples dBm range values are described in
Table 14. dBm representation colors

47

Table 14. dBm representation colors
color
dBm value -130dBm -51dBm

6.3.4 Upload and Download transfer rate

Figure 70.Upload Transfer rate

In the Figure 70 is selected a sample of the upload transfer data rate result. The colors used for
representing upload rate is Table 15. Upload representation colors .

Table 15. Upload representation colors
color
upload rate 0MB/s 115MB/s
6.3.5 Download transfer rate
In the figure Figure 71. Download transfer rate , is selected the same transfer rate as in the case
of upload transfer rate, but the represented data is corresponding to the download speed rate instead.
The colors used for represent ing the download data rate metrics are the same as for the upload data
rate, defined in Table 15.

48

Figure 71. Download transfer rate
Offline measure samples
These measurements purpose is to build a map containing the areas where the mobile net work
coverage is missing. Places like tunnels, subways or underground parking lots represent such
places.
6.4.1 Sample a cquired in underground

Figure 72. Offline measurements in underground

In the Figure 72. Offline measurements in underground is selected a sample acquired by the
client while being the underground. It is a difficult job for the mobile networks to provide cover in
the tunnels. In this case the sample has been saved locally by the client application and with the
closet opportunity the bulk data of unsuccessful sent samples has been re -sent to the server.

49
6.4.2 Sample acquired in the elevator
The Figure 73. Offline measurement in elevators is representing a sample acquired in the
elevator of an building. In this case the client applies the same behavior as for underground
measurements.

Figure 73. Offline measurement in elevators

50
7 Conclusions
The necessity that this type of system application to be further developed has been
demonstrated. Currently, by looking at the experimental result, we comfortably can say that the
whole world is still using the earlier developed mobile networks architecture along with newer,
more reliable, high performance .
Due to people ’s constant needs of movement and communication the current in place mobile
networks do a good god job in providing the subscriber with all the services, making the life easier.
Although, we must be aware by the drawbacks of these mobile network and continuously try to
improve them. After all, the today technologies would not be at this standard if for the las t decade
this this technology field would not have been studied looking for better performances.
There shouldn’t be forgotten the remote areas where the mobile networks are havi ng trouble
to provide coverage. L et’s say, geographical areas which impedes the radio interface to performs
it processes , large unpopulated lands or place where due to other impediments can’t be served with
cellular coverage, for example subway track underground parking lots.
In order for the technology to move forward it would be ea sier if all collected information
regarding the radio signal power would be gather to a single point and several tools to enables the
engineers to find the solution quicker, maintaining the quality in all this time.
Furthermore, looking at the results it i s observable that even if the technology has evolved a
lot, as regards the quality of the services, implemented features, yet, there are still places where
even the basic voice services can’ t be delivered for subscribers.
Both client and server application s has been developed in Java. Beside this the server part use
Spring framework and Maven for building the software and describing dependences. The
requirements building the server application is a database connection and internet access. The client
has bee n developed using Android APIs and can run only on devices that runs on Android operating
system.
For allowing access to the acquired data, the server implements an WEB interface where the
samples are represented on google maps. Based on different criterion the represented data might
be narrowed or widen.
To sum up, the application proposed in this thesis , aims to identify where the mobile networks
are not in place, why is that and what can be done in order that t hese services availability to reaches
99.9% or as it closes as it gets if the found solution can be implemented.
The roadmap of this application should contain the following milestones: On the client part,
might be developed a better GPS localization manag er and of course it requires a little attention
regarding the user interface design. For the server, the development plan should include an
optimization for database interrogations .

51
8 References

[1] "Open Signal – Google Play," OpenSignal.c om, 2018. [Online]. Available:
https://play.google.com/store/apps/details?id=com.staircase3.opensignal. [Accessed 03 06 2018].
[2] OpenSignal, "OpenSignal," OpenSignal.com, 2018.
[3] OpenSignal, "Global Cell Coverage Maps – Open Signal," OpenSignal, 2018. [Online]. Available:
https://opensignal.com/networks. [Accessed 05 06 2018].
[4] Google, "Sensorly: 4G Coverage and Speedtests," 2018. [Online]. Available:
https://play.google.com/store/apps/details?id=com.sensorly.viewer. [Accessed 08 07 2018].
[5] Sensorly, "Sensorly – Unbiased, Real -World Mobile Coverage," Sensorly LLC, 2018. [Online]. Available:
https://www.sensorly.com/. [Accessed 03 07 2018].
[6] International Teleccommunications Union, "International Telecommunications Union – Access
Technologies," 2011. [Online]. Available: https://www.itu.int/osg/spu/imt -2000/technology.html.
[Accessed 20 06 2018].
[7] R. M. Terebes, Mobile Communication System Part One: GSM network, U.T. Press, 2006.
[8] European Telecommunications Standards Insti tute, "Digital cellular telecommunications system," ETSI TS
127 007, vol. V10.4.0, p. 163, 2004.
[9] Cisco, "Overview of GSM, GPRS, and UMT," Cisco Mobile Exchange (CMX) Solution Guide, pp. 2 -10.
[10] I. Poole, "3G UMTS Tutorial | WCDMA Tutorial | Radio -Electronics.Com," Adrio Communications Ltd,
[Online]. Available: https://www.radio –
electronics.com/info/cellulartelecomms/umts/umts_wcdma_tutorial.php. [Accessed 02 08 2018].
[11] Cisco, "P -GW Administration Guide, StarOS Release 20," Cisco, 2017.
[12] New -Tech Europe Magazine, "February 2018," New -Tech Europe Magazine, pp. 61 -63, 02 2018.
[13] Electronics Notes, "What is LTE | Tutorial & Overview | Electronics Notes," Electronics Notes, [Online].
Available: https://www.electronics -notes.com/ar ticles/connectivity/4g -lte-long -term -evolution/what -is-
lte-basics -tutorial -overview.php. [Accessed 22 07 2018].
[14] I. T. a. M. B. Stefania Sesia, LTE: The UMTS Long Term Evolution: From Theory to Practice, John Wiley &
Sons, Ltd., Publication, 2009.
[15] Android, "CellSignalStrength," Android Developers, 2018.

52
[16] Maven, "Maven – Introduction," 2002. [Online]. Available: https://maven.apache.org/what -is-
maven.html. [Accessed 02 07 2018].
[17] Spring , "Spring Framework Overview," 12 06 2012. [Online]. Available:
https://docs.spring.io/spring/docs/current/spring -framework -reference/overview.html. [Accessed 01 05
2018].
[18] S. James, "Android Asynchronous Http Client," 2012. [Online]. Available: http://loopj.com/android -async –
http/. [Accessed 20 05 2018].
[19] Android, "Meet Android Studio | Android Developers," 5 06 2018. [Online]. Available:
https://developer.android.com/studio/intro/. [Accessed 03 05 2018].
[20] Oracle, "Oracle VM VirtualBox | Oracle Technology Network," [Online]. Avail able:
http://www.oracle.com/technetwork/server -storage/virtualbox/overview/index.html. [Accessed 03 07
2018].
[21] "International Journal of Engineering and Advanced Technology," Advanced Technology & Science 2013,
2016.
[22] R. &. S. T. center, "GPRS -Mobility Management and Packet Data Transfer Management," vol. v1.1, pp. 48 –
49.
[23] A. N. M. M. Karandikar A., Mobility Management in LTE Heterogeneous Networks, 2017.
[24] Google, "OpenSignal Hărți 3G/4G/WiFi," 2018. [Online]. Available:
https://play.google.com/store/apps/details?id=com.staircase3.opensignal. [Accessed 20 06 2018].
[25] Android, "CellSignalStrengthGsm | Android Developers," 6 June 2018. [Online]. Available:
https://developer.android.com/reference/and roid/telephony/CellSignalStrengthGsm.html#getAsuLevel().
[Accessed 06 07 2018].
[26] Android , "CellSignalStrengthLte | Android Developers," Android, 6 6 2018. [Online]. Available:
https://developer.android.com/reference/android/telephony/CellSignalStren gthLte.html#getAsuLevel().
[Accessed 06 07 2018].
[27] Android, "CellSignalStrengthWcdma | Android Developers," 6 6 2018. [Online]. Available:
https://developer.android.com/reference/android/telephony/CellSignalStrengthWcdma. [Accessed 02 07
2018].
[28] Innovations, Z Series, "Generations in Telecommunication (1G, 2G, 3G, 4G)," 2015. [Online]. Available:
http://www.zseries.in/telecom%20lab/telecom%20generations/#.W0IuGtL7RPZ. [Accessed 16 06 2018].
[29] laroccasolutions, "RSCP and RSSI in UMTS," 2018. [Online]. Available:
https://www.laroccasolutions.com/141 -rscp-rssi/. [Accessed 20 06 2018].

53
9 Appendix
Server Source code
9.1.1 Controllers
IncomingOperations

package com.example.mobileNetworkServer;

import models.DeviceProperties;
import models.InternetRatesObj;
import models.LocationAndLevelV2;
import com.google.gson.Gson;
import dao.DAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.suppo rt.ClassPathXmlApplicationContext;
import org.springframework.web.bind.EscapedErrors;
import org.springframework.web.bind.annotation.*;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

/**
* This class is a rest controller. Here is ex posed the public endpoints at which the
client will send data over HTTP.
*/
@RestController
public class IncomingOperations {
private final Logger log = LoggerFactory. getLogger (this.getClass());
private static final SimpleDateFormat sdf = new
SimpleDateFormat( "yyyy.MM.dd.HH.mm.ss" );
private DecimalFormat df = new DecimalFormat( "##.#######" );
ApplicationContext context =
new ClassPathXmlApplicationContext( "Spring-Module.xml" );

/**
* Handles the HTTP POST request for endpoint "/deviceProperties". This operation
receive a Device Property as
* JSON object and stores it into database via DAO interface.
*
* @param deviceProperties
*/
@RequestMapping (value = "/deviceProperties" , method = RequestMethod. POST, produces
= "application/json" )
public @ResponseBody
void storeDeviceProperties( @RequestBody DeviceProperties deviceProperties) {
log.info("New terminal enrolled: " + new Gson().toJson(deviceProperties));
try {
DAO dbDAO = (DAO) context.getBean( "databaseDao" );
dbDAO.insertDeviceProperties(deviceProperties);
} catch (Exception ex) {
log.error(ex.toString());
}
}

/**
* Handles the HTTP POST reques t for endpoint "/postLocationAndLevels". This
operation receive a LocationAndLevelV2
* object and stores it into database via DAO interface.
*
* @param locationAndLevels
* @return a JSON object representing index of the sample received.

54
*/
@RequestMapping (value = "/postLocationAndLevels" , method = RequestMethod. POST,
produces = "application/json" )
public @ResponseBody
String storesConnectionParameters( @RequestBody LocationAndLevelV2
locationAndLevels) {
try {
log.info("Received level and location from subscriber id: " +
locationAndLevels.getSignalStrenght().getSubscriberId());

locationAndLevels.getCoordinates().setLat(Double. parseDouble (df.format(locationAndLevel
s.getCoordinates().getLat ())));

locationAndLevels.getCoordinates().setLng(Double. parseDouble (df.format(locationAndLevel
s.getCoordinates().getLng())));

DAO dbDAO = (DAO) context.getBean( "databaseDao" );
dbDAO.insertLocationAndLevels(locationAndLe vels);
} catch (Exception ex) {
log.error(ex.toString());

}
return "{\"index\":" + locationAndLevels.getId() + "}";
}

/**
* Handles the HTTP POST request for endpoint "/speedTestRate". This operation
receive a InternetRatesObj
* object and stores it into database via DAO interface.
*
* @param ratesObj
*/
@RequestMapping (value = "/speedTestRate" , method = RequestMethod. POST, produces =
"application/json" )
public @ResponseBody
void storeSpeedTestRates( @RequestBody InternetRatesObj ratesObj) {
DAO dbDAO = (DAO) context.getBean( "databaseDao" );
try {
dbDAO.insertSpeedRate s(ratesObj);
log.info("Speed Test run received from subscriber id: " +
ratesObj.getSignalStrenght().getSubscriberId());
}
catch (Exception e ){
log.error(e.toString());
}

}

}

LocalOperations

package com.example.mobileNetworkServer;

import models.*;
import dao.DAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype. Controller ;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation. GetMapping ;
import org.springframework.web.bind.annotation. RequestParam ;

import java.util.*;

/**
* This class controls th e web request to the server
*/

55
@Controller
public class LocalOperations {
ApplicationContext context = new ClassPathXmlApplicationContext( "Spring-
Module.xml" );
private final Logger log = LoggerFactory. getLogger (this.getClass());
/** This operation handles the GET method requested at the server address by
browser when page is loaded.
*
* @param phoneModelOption is completed with the value from dropdown selector in
the moment when "Submit" button is hit
* @param phoneManufactu rerOption is completed with the value from dropdown
selector in the moment when "Submit" button is hit,
* @param networkNameOp is completed with the value from dropdown selector in the
moment when "Submit" button is hit,
* @param initTime is completed with the value from begin date field in the moment
when "Submit" button is hit,
* @param finalTime is completed with the value from end date field in the moment
when "Submit" button is hit,
* @param model
* @return the index.html web p age, browser is rendering it.
*/
@GetMapping ("/")
public String mapRendering( @RequestParam (name = "phoneModelOption" , required =
false, defaultValue = "%" ) String phoneModelOption,
@RequestParam (name = "phoneManufacturerOption" , required
= false, defaultValue = "%") String phoneManufacturerOption,
@RequestParam (name = "networkNameOp" , required = false,
defaultValue = "%") String networkNameOp,
@RequestParam (name = "initTime" , required = false,
defaultValue = "") String initTime,
@RequestParam (name = "finalTime" , required = false,
defaultValue = "") String finalTime,
@RequestParam (name = "networkTypeName" , required =
false, defaultValue = "%") String networkTypeName,
@RequestParam (name = "networkTypeClass" , required =
false, defaultValue = "%") String networkTypeClass,
Model model) {

log.info("New GET Method received" );
model.addAttribute( "phoneModelOption" , phoneModelOption);
model.addAttribute( "phoneManufacturerOption" , phoneManufacturerOption);
model.addAttribute( "networkNameOp" , networkNameOp);
model.addAttribute( "initTime" , initTime);
model.addAttribute( "finalTime" , finalTime);
model.addAttribute( "networkTypeName" , networkTypeName);
model.addAttribute( "networkTypeClass" , networkTypeClass);

DAO obj = (DAO) context.getBean( "databaseDao" );

String[] filterParams = new String[7];
filterParams[ 0] = phoneModelOption;
filterParams[ 1] = phoneManufacturerOption;
filterParams[ 2] = networkNameOp;
filterParams[ 3] = initTime;
filterParams[ 4] = finalTime;
filterParams[ 5] = networkTypeName;
filterParams[ 6] = networkTypeClass;

// obj.getFilteredDetails(filterParams);

model.addAttribute( "varMapFromJava" , obj.getFilteredDetails(f ilterParams));

List<DeviceProperties> devices = obj.getDeviceDetails();

model.addAttribute( "devices" , getSetOfList(devices));

return "index";
}

/**

56
* Iterates the list with DeviceProperties object for returning an unique set of
entries used in dropdowns.
* @param devices
* @return unique entries for each dropdown.
*/
private List<List<String>> getSetOfList(List<DeviceProperties> devices) {

List<String> allDevicesModel = new ArrayList<>();
List<String> allDevicesManufacturer = new ArrayList<>();
List<String> allNetworkOperatorsName = new ArrayList<>();
for (int i = 0; i < devices.size(); i++) {

allDevicesModel.add(devices.get(i).getDeviceModel());
allDevicesManufacturer.add(devices.get(i).getDeviceManufacturer());
allNetworkOperatorsName.add(devices.get(i).getNetworkOperatorName());
}
Set<String> uniqueDevicesModel = new HashSet<>(allDevicesModel);
Set<Strin g> uniqueDevicesManufacturer = new HashSet<>(allDevicesManufacturer);
Set<String> uniqueNetworkOperatorsName = new
HashSet<>(allNetworkOperatorsName);

List<List<String>> listOfSets = new ArrayList<>();
listOfSets.add( new ArrayList <>(uniqueDevicesModel));
listOfSets.add( new ArrayList<>(uniqueDevicesManufacturer));
listOfSets.add( new ArrayList<>(uniqueNetworkOperatorsName));
return listOfSets;
}

}

MobileNetworkServer

package com.example.mobileNetworkServer;

import org.springframework.beans.factory.annotation. Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure. SpringBootApplication ;

import java.net.InetAddress;
import java.net.UnknownHostException;

@SpringBootApplication
public class MobileNetworkServer {

@Value("${server.port}" )
private String serverPort ;

public static void main(String[] args) {
SpringApplication. run(MobileNetworkServer. class, args);
printServerStartAddress ();
System.out.println();
}

private static void printServerStartAddress() {
InetAddress ip = null;
try {
ip = InetAddress. getLocalHost ();
} catch (UnknownHostException e) {
e.printStackTrace();
}
System.out.println( "–––––––––- \nCurrent IP address : " +
ip.getHostAddress() + "\n–––––––––- ");
}

}

57
9.1.2 JDBC
package dao.impl;

import models.*;
import dao.DAO;

import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
* This class implements DAO interface and overrides the methods.
*/
public class JdbcManager implements DAO {

private DataSource dataSource ;
private String DEVICE_PROPERTIES_TABLE = "DEVICE_PROPERTIES" ;

private static final String LONGITUDE = "longitude" ;
private static final String LATITUDE = "latitude" ;

private static final String DEVICE_ID = "deviceId" ;
private static final String SIGNAL_DBM = "signalDbm" ;
private static final String SIGNAL_STRENGTH_LEVEL = "signalStrengthLevel" ;
private static final String ASU_LEVEL = "asuLevel" ;
private static final String TIMING_ADVANCE = "timingAdvance" ;

private static final String RSSNR = "Rssnr";
private static final String RSRQ = "Rsrq";
private static final String RSRP = "Rsrp";

private static final String NETWORK_OPERATOR = "networkOperator" ;
private static final String NETWORK_TYPE_CLASS = "networkTypeClass" ;
private static final String NETWORK_TYPE_NAME = "networkTypeName" ;
private static final String NETWORK_OPERATOR_NAME = "networkOperatorName" ;
private static final String TIMESTAMP = "timestamp" ;
private static final String UPLOAD_RATE = "uploadRate" ;
private static final String DOWNLOAD_RATE = "downloadRate" ;

private static final String IMEI = "imei";
private static final String MCC = "mcc";
private static final String MNC = "mnc";
private static final String NETWORK_COUNTRY_ISO = "networkCountryISO" ;
private static final String DEVICE_MODEL = "deviceModel" ;
private static final String DEVICE_MANUFACTURER = "deviceManufacturer" ;
private static final String DEVICE = "device" ;
private static final String NETWORK_CLASS = "networkClass" ;
private static final String NETWORK_TYPE = "networkType" ;
private static final String SUBSCRIBER_ID = "subscriberId" ;
private static final String SIM_OPERATOR = "simOpera tor";

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

/**
* Mapping over the numeric network operator.
* @param operator
* @return the String value of Operator
*/
private String getNetworkOperatorName(String operator) {
switch (operator) {
case "22601":
return "Vodafone" ;
case "22602":
return "Romtelecom" ;
case "22603":

58
return "Telekom";
case "22605":
return "DIGI Mobil" ;
case "22606":
return "Zapp";
case "22610":
return "Orange" ;
case "22611":
return "Enigma" ;
case "22616":
return "Lycamobile" ;
default:
return String.valueOf(operator);

}

}

/**
* During this method the database is access and object is written in the
DEVICE_PROPERTIES table
* @param deviceProperties
*/
@Override
public void insertDeviceProperties(DeviceProperties deviceProperties) {
String sql = "INSERT INTO " + DEVICE_PROPERTIES_TABLE +
"(deviceId,imei, mcc,
mnc,simOperator,networkOp eratorName,networkCountryISO,subscriberID,deviceModel,deviceMa
nufacturer,device,networkTypeName,networkClass) " +
"VALUES " +
"(?,?,?,?,?,?,?,?,?,?,?,?,?)" ;
Connection conn = null;

try {
conn = dataSource .getConnection();
PreparedStatement ps = conn.prepareStatement(sql);

ps.setString( 1, deviceProperties.getDeviceId());
ps.setString( 2, deviceProperties.getImei());
ps.setString( 3, deviceProperties.getMcc());
ps.setString( 4, deviceProperties.getMnc());
ps.setString( 5, deviceProperties.getSimOperator());
ps.setString( 6, getNetworkOperatorName(deviceProperties.getSimOperator()));
ps.setSt ring(7, deviceProperties.getSimCountryISO());
ps.setString( 8, deviceProperties.getSubscriberID());
ps.setString( 9, deviceProperties.getDeviceModel());
ps.setString( 10, deviceProperties.getDeviceManufacturer());
ps.setString( 11, deviceProperties.getDevice());
ps.setString( 12, deviceProperties.getNetworkType());
ps.setString( 13, deviceProperties.getNetworkClass());
ps.executeUpdate();
ps.close();

} catch (SQLException e) {
throw new RuntimeException(e);

} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
}

/**
* During this method the database is access and object is written in the

59
SIGNAL_LEVEL table
* @param locationAndLevelsObject
*/
@Override
public void insertLocationAndLevels(LocationAndLevelV2 locationAndLevelsObject) {

String sql = "INSERT INTO SIGNAL_LEVEL " +
"(" + LATITUDE + ", " + LONGITUDE + ", " + SIGNAL_DBM + ", " +
SIGNAL_STRENGTH_LEVEL + ", " + ASU_LEVEL + ", " + TIMING_ADVANCE + ", " + RSSNR + ", "
+ RSRQ + ", " + RSRP + ", " + NETWORK_OPERATOR + ", " + NETWORK_TYPE_CLASS + ", " +
NETWORK_TYPE_NAME + ", " + NETWORK_OPERATOR_NAME + ", " + SIM_OPERATOR + ", " +
SUBSCRIBER_ID + ", " + DEVICE_ID + ", " + TIMESTAMP + ") VALUES (?, ?,?,
?,?,?,?,?,?,?,?,?,?,?,?,?,?)" ;
Connection conn = null;

try {
conn = dataSource .getConnection();
PreparedStatement ps = conn.prepareStatement(sql);

ps.setDouble( 1, locationAndLevelsObject.getCoordinates().getLat());
ps.setDouble( 2, locationAndLevelsObject.getCoordinates().getLng());
if (locationAndLevelsObject.getSignalStrenght() != null) {
ps.setInt( 3,
locationAndLevelsObject.getSignalStrenght().getSignalDbm());
ps.setInt( 4,
locationAndLev elsObject.getSignalStrenght().getSignalStrengthLevel());
ps.setInt( 5,
locationAndLevelsObject.getSignalStrenght().getAsuLevel());
ps.setInt( 6,
locationAndLevelsObject.getSignalStrenght().getTimingAdvance());

ps.setInt( 7, locationAndLevelsObject.getSignalStrenght().getRssnr());
ps.setInt( 8, locationAndLevelsObject.getSignalStrenght().getRsrq());
ps.setInt( 9, locationAndLevelsObject.getSignalStrenght().getRsrp());

ps.setString( 10,
locationAndLevelsObject.getSignalStrenght().getNetworkOperator());
ps.setString( 11,
locationAndLevelsObject.getSignalStrenght().getNetworkTypeClass());
ps.setString( 12,
locationAndLevelsObject.getSignalStr enght().getNetworkTypeName());
ps.setString( 13,
locationAndLevelsObject.getSignalStrenght().getNetworkOperatorName());
ps.setString( 14,
locationAndLevelsObject.getSignalStrenght().getSimOperator());
ps.setStr ing(15,
locationAndLevelsObject.getSignalStrenght().getSubscriberId());
ps.setString( 16,
locationAndLevelsObject.getSignalStrenght().getDeviceId());
}
ps.setTimestamp( 17, locationAndLevelsObject.getTimestamp());
ps.executeUpdate();
ps.close();

} catch (SQLException e) {
throw new RuntimeException(e);

} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}

}

/**

60
* During this method the database is access and object is written in the
SIGNAL_LEVEL table
* @param obj
*/
@Override
public void insertSpeedRates(InternetRatesObj obj) {

String sql = "INSERT INTO SIGNAL_LEVEL " +
"(" + LATITUDE + ", " + LONGITUDE + ", " + SIGNAL_DBM + ", " +
SIGNAL_STRENGTH_LEVEL + ", " + ASU_LEVEL + ", " + TIMING_ADVANCE + ", " + RSSNR + ", "
+ RSRQ + ", " + RSRP + ", " + NETWORK_OPERATOR + ", " + NETWORK_TYPE_CLASS + ", " +
NETWORK_TYPE_NAME + ", " + NETWORK_OPERATOR_NAME + ", " + UPLOAD_RATE + ", " +
DOWNLOAD_RATE + ", " + SIM_OPERATOR + ", " + SUBSCRIBER_ID + ", " + DEVICE_ID + ")
VALUES (?, ?,?, ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" ;
Connection conn = null;

try {
conn = dataSource .getConnection();
PreparedStatement ps = conn.prepareStatement(sql);

ps.setDouble( 1, obj.getCoordinates(). getLat());
ps.setDouble( 2, obj.getCoordinates().getLng());
if (obj.getSignalStrenght() != null) {

ps.setInt( 3, obj.getSignalStrenght().getSignalDbm());
ps.setInt( 4, obj.getSignalStrenght().getSignal StrengthLevel());
ps.setInt( 5, obj.getSignalStrenght().getAsuLevel());
ps.setInt( 6, obj.getSignalStrenght().getTimingAdvance());

ps.setInt( 7, obj.getSignalStrenght().getRssnr());
ps.setInt( 8, obj.getSignalStrenght().getRsrq());
ps.setInt( 9, obj.getSignalStrenght().getRsrp());

ps.setString( 10, obj.getSignalStrenght().getNetworkOperator());
ps.setString( 11, obj.getSignalStrenght().getNetworkTypeCl ass());
ps.setString( 12, obj.getSignalStrenght().getNetworkTypeName());
ps.setString( 13, obj.getSignalStrenght().getNetworkOperatorName());
ps.setDouble( 14, obj.getInternetRates().getUploadRate());
ps.setDouble( 15, obj.getInternetRates().getDownloadRate());
ps.setString( 16, obj.getSignalStrenght().getSimOperator());
ps.setString( 17, obj.getSignalStrenght().getSubscriberId());

ps.setString( 18, obj.getSignalStrenght().getDeviceId());
}
ps.executeUpdate();
ps.close();

} catch (SQLException e) {
throw new RuntimeException(e);

} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}

}

/**
* Maps the database fields values to proper DeviceProperties java object
* @param rs
* @param conn
* @return DeviceProperties with database values mapped.
*/
private DeviceProperties doDBtoDevicePropObjectSetter(ResultSet rs, Connection

61
conn) {
DeviceProperties obj = new DeviceProperties();
try {
obj.setDeviceId(r s.getString( DEVICE_ID ));
obj.setImei(rs.getString( IMEI));
obj.setMcc(rs.getString( MCC));
obj.setMnc(rs.getString( MNC));
obj.setNetworkOperatorName(rs.getString( NETWORK_OPERATOR_NAME ));
obj.setSimCountryISO(rs.getString( NETWORK_COUNTRY_ISO ));
obj.setSubscriberID(rs.getString( SUBSCRIBER_ID ));
obj.setDeviceModel(rs.getString( DEVICE_MODEL ));
obj.setDeviceManufacturer(rs.getString( DEVICE_MANUFAC TURER));
obj.setDevice(rs.getString( DEVICE));
obj.setNetworkTypeName(rs.getString( NETWORK_TYPE_NAME ));
obj.setNetworkClass(rs.getString( NETWORK_CLASS ));
obj.setNetworkType(rs.getString( NETWORK_TYPE ));

return obj;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
}

/**
* Maps the database fields values to proper LocationAndLevelV2 java object
* @param rs
* @param conn
* @return LocationAndLevelV2 set with database values.
*/
private LocationAnd LevelV2 doDBtoLevelsObjSetter(ResultSet rs, Connection conn) {
LocationAndLevelV2 dbToObj = new LocationAndLevelV2();

try {

Coordinates coordinates = new Coordinates();
coordinates.setLng(rs.getDouble( LONGITUDE ));
coordinates.setLat(rs.getDouble( LATITUDE ));
dbToObj.setCoordinates(coordinates);

SignalStrenght gsmParams = new SignalStrenght();
gsmParams.setSignalDbm(rs.getInt( SIGNAL_DBM ));
gsmParams.setSign alStrengthLevel(rs.getInt( SIGNAL_STRENGTH_LEVEL ));
gsmParams.setAsuLevel(rs.getInt( ASU_LEVEL ));
gsmParams.setTimingAdvance(rs.getInt( TIMING_ADVANCE ));

gsmParams.setRssnr(rs.getInt( RSSNR));
gsmParams.setRsrq( rs.getInt( RSRQ));
gsmParams.setRsrp(rs.getInt( RSRP));

gsmParams.setNetworkOperator(rs.getString( NETWORK_OPERATOR ));
gsmParams.setNetworkTypeClass(rs.getString( NETWORK_TYPE_CLASS ));
gsmParams.setNetworkTypeNa me(rs.getString( NETWORK_TYPE_NAME ));
gsmParams.setNetworkOperatorName(rs.getString( NETWORK_OPERATOR_NAME ));

gsmParams.setNetworkOperatorName(rs.getString( NETWORK_OPERATOR_NAME ));

gsmParams.setSimOperator(rs.getString( SIM_OPERATOR ));
gsmParams.setSubscriberId(rs.getString( SUBSCRIBER_ID ));
gsmParams.setDeviceId(rs.getString( DEVICE_ID ));

dbToObj.setSignalStrenght(gsmParams);

62

InternetRate rates = new InternetRate();
rates.setDownloadRate(rs.getDouble( DOWNLOAD_RATE ));
rates.setUploadRate(rs.getDouble( UPLOAD_RATE ));
dbToObj.setInternetRates(rates);

dbToObj.setTimestamp(rs.getTimestamp( TIMESTAMP ));

return dbToObj;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
}

/**
* Based on the received filters interrogates the database and retrieves request
entries.
* It actions both on SIGNAL_LEVEL table and DEVICE_PROPERTIES table
* @param args
* @return list of LocationAndLevelV2 objects
*/
@Override
public List<LocationAndLevelV2> getFilteredDetails(String[] args) {

String DEVICE_MODEL = args[ 0];
String DEVICE_MANUFACTURER = args[ 1];
String NETWORK_OPERATOR_NAME = args[ 2];
String INIT _TIME = args[ 3];
String FINAL_TIME = args[ 4];
String NETWORK_TYPE_NAME=args[ 5];
String NETWORK_TYPE_CLASS=args[ 6];

String baseSql = "SELECT SIGNAL_LEVEL. *\n" +
" FROM DEVICE_PROPERTIES INNER JOIN SIGNAL_LE VEL ON
DEVICE_PROPERTIES.subscriberId = SIGNAL_LEVEL.subscriberId" ;

if (!INIT_TIME.isEmpty() && !FINAL_TIME.isEmpty()) {
baseSql += " AND SIGNAL_LEVEL.timestamp BETWEEN \"" + INIT_TIME + "\" AND
\"" + FINAL_TIME + "\"";
}

baseSql += " WHERE DEVICE_PROPERTIES.deviceModel LIKE ( \"" + DEVICE_MODEL +
"\")";
baseSql += " AND DEVICE_PROPERTIES.deviceManufacturer LIKE ( \"" +
DEVICE_MANUFACTURER + "\")";
baseSql += " AND DEVICE_PROPERTIES.networkOperatorName LIKE (\"" +
NETWORK_OPERATOR_NAME + "\")";
baseSql += " AND SIGNAL_LEVEL.networkTypeClass LIKE ( \"" + NETWORK_TYPE_CLASS +
"\")";
baseSql += " AND SIGNAL_LEVEL.networkTypeName LIKE ( \"" + NETWORK_TYPE_NAME +
"\")";

Connection con n = null;
List<LocationAndLevelV2> listOfEntryes = new ArrayList<>();
try {
conn = dataSource .getConnection();
PreparedStatement ps = conn.prepareStatement(baseSql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {

LocationAndLevelV2 obj = doDBtoLevelsObjSetter(rs, conn);

63
listOfEntryes.add(obj);
}
rs.close();
ps.close();

} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
return listOfEntryes;

}

/**
* Interogates over the DEVICE_PROEPRTIES table and retries all entries as list of
DeviceProperties java object.
* @return list of DeviceProperties objects
*/
@Override
public List<DeviceProperties> getDeviceDetails() {

String sql = "SELECT * FROM DEVICE_PROPERTIES;" ;
Connection conn = null;
List<DeviceProperties> listOfEntryes = new ArrayList<>();
try {
conn = dataSource .getConnection();
PreparedStatement ps = conn. prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()) {

DeviceProperties obj = doDBtoDevicePropObjectSetter(rs, conn);
listOfEntryes.add(obj);
}
rs.close( );
ps.close();

} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
}
}
}
return listOfEntryes;

}
}
package dao;

import models.DeviceProperties;
import models.InternetRatesObj;
import models.LocationAndLevelV2;

import java.util.List;

/**
* Interface for working with database.
*/
public interface DAO {
/**
* Stores LocationAndLevelV2 object into database

64
* Actions over SIGNAL_LEVEL table
* @param locationAndLevelsObject
*/
void insertLocationAndLevels(LocationA ndLevelV2 locationAndLevelsObject);

/**
* Stores DeviceProperties object into database
*
* @param deviceProperties
*/
void insertDeviceProperties(DeviceProperties deviceProperties);

/**
* Stores InternetRatesObj objec t into database
*
* @param rateObj
*/
void insertSpeedRates(InternetRatesObj rateObj);

/**
* Retrieve the levels and location entries from database based on the requested
filters.
*Actions over the SIGNAL_LEVELS table
* @param args
* @return list with filtered location and levels objects.
*/
List<LocationAndLevelV2> getFilteredDetails(String[] args);

/**
* Retrieve the device properties from database.
* Actions over the DEVICE_PROPERTIES ta ble
* @return list with all entries from the table.
*/
List<DeviceProperties> getDeviceDetails();
}

9.1.3 Models
package models;

/**
* Class describing the coordinates object. Has two double properties: lat and long,
referring to latitude and l ongitude
*/
public class Coordinates {
private double lat;

public double getLat() {
return lat;
}

public void setLat(double lat) {
this.lat= lat;
}

public double getLng() {
return lng;
}

public void setLng(double lng) {
this.lng= lng;
}

private double lng;
}

65
package models;

/**
* Class describing the device properties object. Has fourteen string properties each
referring to mobile terminal
* properties, like model, manu facture or regarding SIM card as simOperator or
subscriber ID.
*/
public class DeviceProperties {
String deviceId ;
String imei;
String mcc;
String mnc;
String simOperator ;
String networkOperatorName ;
String simCountryISO ;
String subscriberID ;
String deviceModel ;
String deviceManufacturer ;
String device;
String networkTypeName ;
String networkClass ;
String networkType ;

public String getSimOperator() {
return simOperator ;
}

public v oid setSimOperator(String simOperator) {
this.simOperator = simOperator;
}

public String getNetworkOperatorName() {
return networkOperatorName ;
}

public void setNetworkOperatorName(String networkOperatorName) {
this.networkOperatorName = networkOperatorName;
}

public String getImei() {
return imei;
}

public void setImei(String imei) {
this.imei = imei;
}

public String getSimCountryISO() {
return simCountryISO ;
}

public void setSimCountryISO(String simCountryISO) {
this.simCountryISO = simCountryISO;
}

public String getDeviceId() {
return deviceId ;
}

public void setDeviceId(String deviceId) {
this.deviceId = device Id;
}

public String getMcc() {
return mcc;
}

public void setMcc(String mcc) {
this.mcc = mcc;

66
}

public String getMnc() {
return mnc;
}

public void setMnc(String mnc) {
this.mnc = mnc;
}

public String getSubscriberID() {
return subscriberID ;
}

public void setSubscriberID(String subscriberID) {
this.subscriberID = subscriberID;
}

public String getDeviceModel() {
return deviceModel ;
}

public void setDeviceModel(String deviceModel) {
this.deviceModel = deviceModel;
}

public String getDeviceManufacturer() {
return deviceManufacturer ;
}

public void setDeviceManufacturer(String deviceManufacturer) {
this.deviceManufacturer = deviceManufacturer;
}

public String getDevice() {
return device;
}

public void setDevice(String device) {
this.device = device;
}

public String getNetworkTypeName() {
return networkTypeName ;
}

public void setNetworkTypeName(String networkTypeName) {
this.networkTypeName = networkTypeName;
}

public String getNetworkClass() {
return networkClass ;
}

public void setNetworkClass(String net workClass) {
this.networkClass = networkClass;
}

public String getNetworkType() {
return networkType ;
}

public void setNetworkType(String networkType) {
this.networkType = networkType;
}

67

}
package models;

/**
*
*/
public class InternetRate {

double downloadRate ;
double uploadRate ;

public double getDownloadRate() {
return downloadRate ;
}

public void setDownloadRate( double downloadRate) {
this.downloadRate = downloadRate;
}

public double getUploadRate() {
return uploadRate ;
}

public void setUploadRate( double uploadRate) {
this.uploadRate = uploadRate;
}
}
package models;

public class InternetRatesObj extends LocationAndL evelV2{
private InternetRate internetRates ;

public InternetRate getInternetRates() {
return internetRates ;
}

public void setInternetRates(InternetRate internetRates) {
this.internetRates = internetRates;
}

}
package models;

import java.sql.Timestamp;

public class LocationAndLevelV2 {
private Coordinates coordinates ;
private SignalStrenght signalStrenght ;
private InternetRate internetRates ;
private Timestamp timestamp ;

public InternetRate getInternetRates() {
return internetRates ;
}

public void setInternetRates(InternetRate internetRates) {
this.internetRates = internetRates;
}

public Timestamp getTimestamp() {
return timestamp ;
}

public vo id setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}

68
public int getId() {
return id;
}

private int id;

public Coordinates getCoordinates() {
return coordinates ;
}

public void setCoordinates(Coordinates coordinates) {
this.coordinates = coordinates;
}

public SignalStrenght getSignalStrenght() {
return signalStrenght ;
}

public void setSignalStrenght(SignalStrenght signalStrenght) {
this.signalSt renght = signalStrenght;
}

}
package models;

public class SignalStrenght {
private String deviceId ;
private int signalDbm ;
private int signalStrengthLevel ;
private int asuLevel ;
private int timingAdvance ;

private int rssnr;
private int rsrq;
private int rsrp;

private String networkOperator ;
private String networkTypeClass ;
private String networkTypeName ;
private String networkOperatorName ;
private String subscriberId ;
private String simOperato r;

public String getSubscriberId() {
return subscriberId ;
}

public void setSubscriberId(String subscriberId) {
this.subscriberId = subscriberId;
}

public String getSimOperator() {
return simOperator ;
}

public void setSimOperator(String simOperator) {
this.simOperator = simOperator;
}

public int getRssnr() {
return rssnr;
}

public void setRssnr( int rssnr) {
this.rssnr = rssnr;
}

public int getRsrq() {

69
return rsrq;
}

public void setRsrq( int rsrq) {
this.rsrq = rsrq;
}

public int getRsrp() {
return rsrp;
}

public void setRsrp( int rsrp) {
this.rsrp = rsrp;
}

public int getTimingAdvance() {
return timingAdvance ;
}

public void setTimingAdvance( int timingAdvance) {
this.timingAdvance = timingAdvance;
}

public String getNetworkOperator() {
return networkOperator ;
}

public void setNetworkOperator (String networkOperator) {
this.networkOperator = networkOperator;
}

public String getDeviceId() {
return deviceId ;
}

public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}

public String ge tNetworkTypeClass() {
return networkTypeClass ;
}

public void setNetworkTypeClass(String networkTypeClass) {
this.networkTypeClass = networkTypeClass;
}

public int getSignalStrengthLevel() {
return signalStrengthLev el;
}

public void setSignalStrengthLevel( int signalStrengthLevel) {
this.signalStrengthLevel = signalStrengthLevel;
}

public int getAsuLevel() {
return asuLevel ;
}

public void setAsuLevel( int asuLevel) {
this.asuLevel = asuLevel;
}

public String getNetworkTypeName() {
return networkTypeName ;
}

public void setNetworkTypeName(String networkTypeName) {
this.networkTypeName = networkTypeName;

70
}

public String getNetwo rkOperatorName() {
return networkOperatorName ;
}

public void setNetworkOperatorName(String networkOperatorName) {
this.networkOperatorName = networkOperatorName;
}

public int getSignalDbm() {

return signalDbm ;
}

public void setSignalDbm( int signalDbm) {
this.signalDbm = signalDbm;
}

9.1.4 Web PAGE
#mapLegend {
/*background: #fdfdfd;*/
/*background: linear -gradient(to bottom, hsl(0, 100%, 50%),hsl(82, 100%,
50%),hsl(163, 100%, 50%),hsl(245, 100%, 50%), hsl(326, 100%, 50%));*/
background : gray;
color: #000000;
/*color: hsl(50,100%,50%);*/
padding: 10px 10px 10px 10px;
margin: 10px;
font-weight: bold;
filter: alpha(opacity=80);
opacity: 0.8;
border: 2px solid #000;
height: 100px;
width: 110px;
position : relative ;
}

#mapLegend div {
line-height: 25px;
font-size: 1.2em;
}

#mapLegend div :first-child {
position : absolute ;
top: 0;
left: 25px;
}

#scaleDiv {
position : absolute ;
top: 5px;
left: 5px;
bottom: 5px;
right: 5px;
width: 10px;
}

#mapLegend div :last-child {
position : absolute ;
bottom: 0;
left: 25px;
}

#mapLegend div img {
float: left;

71
margin-right: 10px;
}

#mapLegend h2 {
vertical -align: bottom;
}

/*
loader
*/
.loaderOn {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation : spin 2s linear infinite ;
background : transparent ;
position : fixed;
margin: auto;
top: 0;
right: 0;
left: 0;
bottom: 0;
}

@keyframes spin {
0% { transform : rotate(0deg); }
100% { transform : rotate(360deg); }
}

#map {
height: 100%;
margin: 10px;
}

html, body {
height: 100%;
margin: 1px;
padding: 1px;
}

.infowindow {
width: 200px;
height: 150px;
}
function toObject (arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[i] = arr[ i];
return rv;
}

function hslColorCalc (min, max, val) {
var minHue = 0, maxHue = 200;
var curPercent = (val – min) / (max – min);
var colString = "hsl(" + ((curPercent * (maxHue – minHue)) + minHue) +
",100%,50%)" ;
return colString ;
}

function returnRadius (renderType, pointsMapObj, point) {
switch (renderType) {
case 'signalStrengthLevel' :
if (pointsMapObj[point].signalStrenght.signalStrengthLevel == 0) {
return 10;
break;
}

72
else {
return radiusValue =
Math.sqrt(pointsMapObj[point].signalStrenght[renderType]) * 10;
break;
}
case 'asuLevel' :
if (pointsMapObj[point].signalStrenght.asuLevel == 255 ||
pointsMapObj[point].signalStrenght.asuLevel == 97) {
return 30;
break;
}
else {

return radiusValue =
Math.sqrt(pointsMapObj[point].signalStrenght[renderType]) * 5;
break;
}
case 'signalDbm' :
if (pointsMapObj[point].signalStrenght.signalDbm == 2147483647 ) {
return 30;
break;
} else {
return radiusValue =
Math.abs(pointsMapObj[point].signalStrenght[renderType]) / 2;
break;
}
case 'uploadRate' :
return Math.abs(pointsMapObj[point].internetRates.uploadRate);
break;
case 'downloadRate' :
return Math.abs(pointsMapObj[point].internetRates.downloadRate);
break;
default:
return radiusValue =
Math.sqrt(pointsMapObj[point].signalStrenght[renderType]) * 10;
}
}

function returnFillColor (renderType, pointsMapObj, point) {

switch (renderType) {
case 'signalStrengthLevel' :
if (pointsMapObj[point].signalStrenght.signalStrengthLevel == 0) {
return "#000000" ;
break;
}
if (pointsMapObj[poin t].signalStrenght.signalStrengthLevel == 1) {
return "#1100ff" ;
break;
}
if (pointsMapObj[point].signalStrenght.signalStrengthLevel == 2) {
return "#00eaff" ;
break;
}
if (pointsMapObj[point].signalStrenght.signalStrengthLevel == 3) {
return "#ff0073" ;
break;
}
if (pointsMapObj[point].signalStrenght.signalStrengthLevel == 4) {
return "#ff0000" ;
break;
}
break;
case
'asuLevel' :
if ((pointsMapObj[point].signalStrenght.asuLevel == 99) ||
(pointsMapObj[point].signalStrenght.asuLevel == 255)) {
return "#000000" ;

73
break;
}
return hslColorCalc (97, 0, pointsMapObj[point].signalStrenght.asuLevel);
break;
case
'signalDbm' :
if (pointsMapObj[point].signalStrenght.signalDbm == 2147483647 ) {
return "#000000" ;
break;
}
return hslColorCalc (51, 115, pointsMapObj[point].signalStrenght.signalDbm);
break;
case
'uploadRate' :
return hslColorCa lc(1, 100, pointsMapObj[point].internetRates.uploadRate);
break;
case
'downloadRate' :
return hslColorCalc (1, 115,
pointsMapObj[point].internetRates.downloadRate);
break;
default:
return hslColorCalc (4, 1,
pointsMapObj[point].signalStrenght.signalStrengthLevel);
}
}

function returnPupUpContent (renderType, pointsMapObj, point) {
switch (renderType) {
case 'signalStrengthLevel' :
return JSON.stringify (pointsMapObj[point].signalStrenght);
break;
case 'asuLevel' :
return JSON.stringify (pointsMapObj[point].signalStrenght);
break;
case 'signalDbm' :
return JSON.stringify (pointsMapObj[point].sign alStrenght);
break;
case 'uploadRate' :
return JSON.stringify (pointsMapObj[point].internetRates);
break;
case 'downloadRate' :
return JSON.stringify (pointsMapObj[point].internetRates);
break;
default:
return hslColorCalc (4, 1,
pointsMapObj[point].signalStrenght.signalStrengthLevel);
}
}

function returnLegend (renderType) {
var upperText ;
var lowerText ;
var legendScale ;
var legend = document .createElement ('div');
switch (renderType) {
case 'signalStrengthLevel' :
lowerText = '0 Signal Bars' ;
upperText = '4 Signal Bars' ;
legendScale = "linear-gradient(to bottom, hsl(0, 100%, 50%),hsl(200, 100%,
50%))";
break;
case 'asuLevel' :
upperText = '97';
lowerText = '0';
legendScale = "linear-gradient(to bottom, hsl(0, 100%, 50%),hsl(40, 100%,
50%),hsl(80, 100%, 50%),hsl(120, 100%, 50%),hsl(160, 100%, 50%), hsl(200, 100%, 50%))" ;
break;
case 'signalDbm' :

74
upperText = '-51 DBm Power' ;
lowerText = '-130 DBm Power' ;
legendScale = "linear-gradient(to bottom, hsl(0, 100%, 50%),hsl(40, 100%,
50%),hsl(80, 100%, 50%),hsl(120, 100%, 50%),hsl(160, 100%, 50%), hsl(200, 100%, 50%))" ;
break;
case 'uploadRate' :

upperText = '115 MB/s' ;
lowerText = '0 MB/s' ;
legendScale = "linear-gradient(to top, hsl(0, 100%, 50%),hsl(40, 100%,
50%),hsl(80, 100%, 50%),hsl(120, 100%, 50%),hsl(160, 100%, 50%), hsl(200, 100%, 50%))" ;
break;

case 'downloadRate' :

lowerText = '0 MB/s' ;
upperText = '115 MB/s' ;
legendScale = "linear-gradient(to top, hsl(0, 100%, 50%),hsl(40, 100%,
50%),hsl(80, 100%, 50%),hsl(120, 100%, 50%),hsl(160, 100%, 50%), hsl(200, 100%, 50%))" ;
break;
default:
}

legend.id = 'mapLegend' ;
document .body.appendChild (legend);

{
div = document .createElement ('div');
div.innerText = upperText ;
legend.appendChild (div);

div = document .createElement ('div');
div.id = 'scaleDiv' ;
div.style.background = legendScale ;
legend.appendChild (div);

div = document .createElement ('div');
div.innerText = lowerText ;
legend.appendChild (div);

}
return legend;

}

function initMap(renderType) {
if (!renderType) {
renderType = 'signalStrengthLevel' ;
}

var map = new google.maps.Map( document .getElementById ('map'), {
zoom: 13,
center: {
lat: 46.773,
lng: 23.6
},
mapTypeId : 'roadmap'
});
google.maps.event. addListener (map, 'tilesloaded' , mapLoaded ());

var legend = returnLegend (renderType);
map.controls[google.maps.ControlPosition.RIGHT_TOP]. push(legend);

for (var point in pointsMapObj ) {
var pointCircle = new google.maps.Circle(
{

clickable : true,
strokeOpacity : 0,

75
strokeWeight : 0,
fillColor : returnFillColor (renderType, pointsMapObj , point),
fillOpacity : 1,
map: map,
center: {lat: pointsMapObj [point].coordinates. lat, lng:
pointsMapObj [point].coordinates. lng},
title: returnPupUpContent (renderType, pointsMapObj , point),
radius: returnRadius (renderType, pointsMapObj , point)
});

google.maps.event. addListener (pointCircle , 'click', function (ev) {

var infolist = '<ul>Sample Details</ul>' ;
var json = JSON.parse(this.get('title'));
for (attribute in json) {
infolist = infolist + ('<li><b>' + attribute + '</b>: ' +
json[attribute ] + '</li>');
}
var infoWindow = new google.maps.InfoWindow({
content: infolist
});
infoWindow .setPosition (ev.latLng);
infoWindow .open(map);
});

}

}

function mapLoaded () {
document .getElementById ("spinner" ).style.display = 'none';
}

index.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Mobile Networks </title>
<script src="map.js" ></script>
<link rel="stylesheet" type="text/css" href="legend.css" >
<link rel="stylesheet" type="text/css" href="map.css" >
<meta http-equiv="Content -Type" content= "text/html; charset=UTF -8"/>
<link rel="stylesheet"
href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity= "sha384-
BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin= "anonymous" >
</head>
<body>
<div class="col-md-2">
<label for="representationTypeSelect" class="information" >Select the
parameter </label>
<select class="form-control" id="representationTypeSelect"
onchange= "initMap(this.value)">
<option value="asuLevel" text="Asu Level" >ASU Level </option>
<option selected value= "signalStrengthLevel" text="Signal Strength
Level">Overall Level </option>
<option value="signalDbm" text="Signal DBm" >dBm</option>
<option value="uploadRate" text="Upload Rate" >Upload Rate </option>
<option value="downloadRate" text="Download Rate" >Download Rate </option>
</select>
<hr>
<label class="information" style="font-size: 30px"> Filters</label>
<form>
<label class="control -label" for="phoneModelOption" >Select device Model</label>
<select class="form-control" name="phoneModelOption" id="phoneModelOption"
th:method= "get">

76
<option value="%" text="%">ALL</option>
<th:block th:each="lists : ${devices[0]}" >
<option th:each="phoneModel: ${lists}"

th:value="${phoneModel}"
th:text="${phoneModel}"
th:id="${phoneModel}"
th:selected= "${phoneModel== phoneModelOption}" >
</option>
</th:block>
</select>
<label class="control -label" for="phoneManufacturerOption" >Select device
Manufacturer </label>
<select class="form-control" name="phoneManufacturerOption"
id="phoneManufacturerOption" th:method= "get">
<option value="%" text="%">ALL</option>
<th:block th:each="lists : ${devices[1]}" >
<!–<th:block th:each="lists : ${devices}"> –>
<option th:each="phoneModel: ${lists}"

th:value="${phoneModel}"
th:text="${phoneModel}"
th:id="${phoneModel}"
th:selected= "${phoneModel== phoneManufacturerOption}" >
</option>
</th:block>
</select>
<label class="control -label" for="networkNameOp" >Select network
Operator </label>
<select class="form-control" name="networkNameOp" id="networkNameOp"
th:method= "get">

<option value="%" text="%">ALL</option>
<th:block th:each="lists : ${devices[2]}" >
<option th:each="phoneModel: ${lists}"

th:value="${phoneModel}"
th:text="${phoneModel}"
th:id="${phoneModel}"
th:selected= "${phoneModel== networkNameOp}" >
</option>
</th:block>
</select>
<label class="control -label" for="networkTypeClass" >Select network
Class</label>
<select class="form-control" name="networkTypeClass" id="networkTypeClass"
th:method= "get">

<option value="%" text="%">ALL</option>
<option value="2G" text="2G">2G</option>
<option value="3G" text="3G">3G</option>
<option value="4G" text="4G">4G</option>

</select>
<label class="control -label" for="networkTypeName" >Select the network
implementation </label>
<select class="form-control" name="networkTypeName" id="networkTypeName"
th:method= "get">

<option value="%" text="%">ALL</option>
<option value="HSPA+" text="HSPA+">HSPA+</option>
<option value="HSPA" text="HSPA">HSPA</option>
<option value="LTE" text="LTE">LTE</option>
<option value="UMTS" text="UMTS">UMTS</option>
<option value="GSM" text="LTE">GSM</option>
</select>
<div class="form-group"> <!– Date init input –>
<label class="control -label" for="initTime" >Date to Begin</label>
<input class="form-control" id="initTime" name="initTime"
th:value="${initTime}" type="datetime -local"

77
step="3600"/>
</div>
<div class="form-group"> <!– Date final input –>
<label class="control -label" for="finalTime" >Date of ending </label>
<input class="form-control" id="finalTime" name="finalTime"
th:value="${finalTime}" type="datetime -local"
step="3600"/>
</div>
<input type="submit" value="submit" id="btn" class="btn btn -primary html –
editor-align-center"/>
</form>
</div>
<div id="map"></div>
<div id="spinner" class="loaderOn" ></div>

<script type="text/javascript" th:inline= "javascript" >
var pointsMapObj = toObject ([[${varMapFromJava}]]);
</script>

<script>

</script>
<script async defer

src="https://maps.googleapis.com/maps/api/js?v=3&key=AIzaSyCQ8C7CrpVNXW66UCObOM7FEsmytQ
HLDgE&callback=initMap" >
</script>

</body>
</html>
Maven pom <?xml version ="1.0" encoding ="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema -instance"
xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven -4.0.0.xsd" >
<modelVersion >4.0.0</modelVersion >

<groupId>com.example </groupId>
<artifactId >DataAquisition </artifactId >
<version>0.0.1-SNAPSHOT </version>
<packaging >jar</packaging >

<name>DataAquisition </name>
<description >Demo project for Spring Boot </description >

<parent>
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-parent</artifactId >
<version>2.0.1.RELEASE </version>
<relativePath /> <!– lookup parent from repository –>
</parent>

<properties >
<project.build.sourceEncoding >UTF-8</project.build.sourceEncoding >
<project.reporting.outputEncoding >UTF-8</project.reporting.outputEncoding >
<java.version >1.8</java.version >
</properties >

<dependencies >
<dependency >
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-thymeleaf </artifactId >
<version>LATEST</version>
</dependency >
<dependency >
<groupId>org.springframework </groupId>
<artifactId >spring-jdbc</artifactId >
<version>LATEST</version>

78
</dependency >
<dependency >
<groupId>com.google.code.gson </groupId>
<artifactId >gson</artifactId >
<version>2.8.2</version>
</dependency >
<dependency >
<groupId>org.mariadb.jdbc </groupId>
<artifactId >mariadb-java-client</artifactId >
<version>2.2.3</version>
</dependency >
<dependency >
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-web</artifactId >
</dependency >

<dependency >
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-starter-test</artifactId >
<scope>test</scope>
</dependency >
</dependencies >

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot </groupId>
<artifactId >spring-boot-maven-plugin</artifactId >
</plugin>
</plugins>
</build>

</project>

79

Server Javadoc

Client Sou rce code
9.3.1 Activities
ConnectionLevelsActivity

package com.sergiud.tarca.mynewdataaquisition.activities;

import android.Manifest;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation. NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.LayoutInfla ter;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

80
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.Goog leMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.Marker;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.ConnectionParameters;
import com.sergiud.tarca.mynewdataaquisition.R;
import com.sergiud.tarca.mynewdataaquisition.Services.GSMDetailsToUiService;
import com.sergiud.tarca.mynewdataaquisition.Servic es.MainBackgroundSerivce;
import com.sergiud.tarca.mynewdataaquisition.Services.RetryJob;
import com.sergiud.tarca.mynewdataaquisition.Utils.Constants;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;
import com.sergiud.tarca.mynewdataaquisition.l isteners.CustomLocationListener;
import
com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners.CustomEditTextListener;
import
com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners.CustomOnMapClickListene
r;
import
com.sergiud.tarca.mynewd ataaquisition.listeners.ObjectsListners.CustomOnUseCustomLocati
onBtnListener;
import
com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners.CustomRetryJobSwitchLis
tener;
import
com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners.Custom SeekBarListener;
import
com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners.CustomTextWatcher;
import
com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners.UseCustomLocationCustom
Listener;
import com.sergiud.tarca.mynewdataaquisition. persistentData.helper.DatabaseHelper;

import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. globalLocationListner ;
import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. isJobRetry ;
import static com.sergiud.tarca.mynewdataaquisition.Gl obalStaff. locationManager ;
import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. pref;
import static
com.sergiud.tarca.mynewdataaquisition.Utils.Constants. DEFAULT_HOSNAME_ADDRESS ;
import static com.sergiud.tarca.mynewdataaquisition.Utils.Constant s.defaulLatLnt ;
import static com.sergiud.tarca.mynewdataaquisition.Utils.Constants. defaultLatitude ;
import static com.sergiud.tarca.mynewdataaquisition.Utils.Constants. defaultLongitude ;

public class ConnectionLevelsActivity extends AppCompatActivity implements
OnMapReadyCallback {

private BroadcastReceiver broadcastReceiver ;
public static EditText longitudeTV ;
public static EditText latitudeTV ;

private Switch retryJobSwitch ;

private TextView signalStrenghtTV ;
private TextView signalDBmTV ;
private TextView signalASUTV ;
private TextView networkOpNameTV ;
private TextView netowkClassNameTV ;
public static TextView deviceInfoTV ;
private TextView netowkClassTypeTV ;

81

private PopupWindow popup;

public stati c TextView seekBarProgressTV ;
private EditText serverIpAddressED ;
public static Switch mainServiceSwitch ;

public static GoogleMap mMap;
public static Marker mMapMaker ;
private Switch useCustomLocationSwitch ;
public static FrameLayo ut frameLayout ;
public static Button manualLocationInputBtn ;

/**
* This method is executed when the application is resumed
*/
@Override
protected void onResume() {
super.onResume();

if (broadcastReceiver == null) {
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {

ConnectionParameters connectionParameters = (ConnectionParameters)
intent.g etExtras().get(Constants. EXTRA_INTENT_SERVICE_TO_FRONT );
if (connectionParameters != null) {

signalStrenghtTV .setText(String. valueOf(connectionParameters.getSignalStrengthLevel()))
;

networkOpNameTV .setText(connectionParameters.getNetworkOperatorName());

signalDBmTV .setText(String. valueOf(connectionParameters.getSignalDbm()));

signalASUTV .setText(String. valueOf(connectionParameters.getAsuLevel( )));

netowkClassNameTV .setText(String. valueOf(connectionParameters.getNetworkTypeName()));

netowkClassTypeTV .setText(String. valueOf(connectionParameters.getNetworkTypeClass()));
}

}
};
}
registerReceiver( broadcastReceiver , new
IntentFilter(Constants. BROADCAST_FILTER ));
// if main service already started, not override the counter
if (MainBackgroundSerivce. counter.get() == 0) {

MainBackgroundSerivce. counter.set(GlobalStaff. pref.getLong(Constants. ATOMIC_COUNTER ,
0));
}
}
/**
* This method is executed when the application is destroyed
*/
@Override
protected void onDestroy() {
super.onDestroy();
Utils.setPreferences (Constants. ATOMIC_COUNTER ,
MainBackgroundSerivce. counter.get());
//stop retry job
Intent retryJob = new Intent(getApplicationContext(), RetryJob. class);
stopService(retryJob);
//stop main service job
Intent mainService = new Intent(getApplicationContext(),

82
MainBackgroundSerivce. class);
stopService(mainService);

// GlobalStaff.useCustomLocation = false;

//stop location updates
locationMana ger.removeUpdates( globalLocationListner );

if (broadcastReceiver != null) {
unregisterReceiver( broadcastReceiver );
}
if (locationManager != null) {
//noinspection MissingPermission
locationManager .removeUpdates(GlobalStaff. globalLocationListner );
}
}

/**
* This method is executed when the application is created
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_collect_levels );
Toolbar toolbar = (Toolbar) findViewById(R.id. toolbar);
frameLayout = (FrameLayout) findViewById(R.id. frameLayout );
if (!GlobalSta ff.useCustomLocation ) {
frameLayout .setVisibility(View. INVISIBLE );
}

GlobalStaff. pref = getApplicationContext().getSharedPreferences( "sys",
MODE_PRIVATE );
GlobalStaff. dataSendPeriod =
GlobalStaff. pref.getInt(Constants. DATE_SEND_PERIOD , 3);
GlobalStaff. serverIpAddress = pref.getString(Constants. HOSNAME_ADDRESS ,
DEFAULT_HOSNAME_ADDRESS );
GlobalStaff. db = new DatabaseHelper( this);

//start retry job
Intent retryJobServiceIntent = new Intent(getApplicationContext(),
RetryJob. class);
startService(retryJobServiceIntent);

setSupportActionBar(toolbar);

locationManager = (LocationManager)
getApplicationContext().getSystemService(Context. LOCATION_SERVICE );
globalLocationListner = new
CustomLocationListener(ConnectionLevelsActivity. this);
mainServiceSwitch = findViewById(R.id. mainService );
longitudeTV = (EditText) findViewById(R.id. longitudeValue );
latitudeTV = (EditText) findViewById(R. id.latitudeValue );
manualLocationInputBtn = (Button) findViewById(R.id. manualLocationInputBtn );
manualLocationInputBtn .setOnClickListener( new
CustomOnUseCustomLocationBtnListener());
signalStrenghtTV = (TextView) findViewById(R.id. signalStrengthValue );
signalDBmTV = (TextView) findViewById(R.id. signalDBmValue );
signalASUTV = (TextView) findViewById(R.id. signalASUValue );
networkOpNameTV = (TextView) findViewById(R.id. networkOpNameValue );
netowkClassName TV = (TextView) findViewById(R.id. networkClassNameValue );
deviceInfoTV = (TextView) findViewById(R.id. deviceDetailsValue );

deviceInfoTV .setText(GlobalStaff. pref.getString(Constants. DEVICE_INFO_PROPERTIES ,
"Unknown" ));
netowkClassTypeTV = (TextView) findViewById(R.id. networkClassTypeValue );

if (!askPermisions()) {
Intent uiUpdateServiceIntent = new Intent(getApplicationContext(),

83
GSMDetailsToUiService. class);
startService(uiUpdateService Intent);
SupportMapFragment mapFragment = (SupportMapFragment)
getSupportFragmentManager()
.findFragmentById(R.id. map);
mapFragment.getMapAsync( this);
}
addListenersToSwitch();

GlobalStaf f.appContext = getApplication().getApplicationContext();
}
/**
* This method is executed when the application is created, inflates the option
menu in top -right of the screen
* @param menu
* @return
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu. menu_collect_levels , menu);
return true ;
}

/**
* This method ad ds listeners on main service switch on/off
*/
private void addListenersToSwitch() {
mainServiceSwitch .setOnCheckedChangeListener( new
CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged( CompoundButton buttonView, boolean isChecked)
{
if (isChecked) {
Intent i = new Intent(getApplicationContext(),
MainBackgroundSerivce. class);
startService(i);
}
if (!isChecked) {
Intent i = new Intent(getApplicationContext(),
MainBackgroundSerivce. class);
stopService(i);
}
}
});

}
/**
* This method check for permission and if not g ranted, initiate requesting process
them.
* READ_PHONE_STATE and ACCESS_FINE_LOCATION are necessarily to be granted.
*/
private boolean askPermisions() {
if (Build.VERSION. SDK_INT >= 23 && ContextCompat. checkSelfPermission (this,
Manifest.permission. READ_PHONE_STATE ) != PackageManager. PERMISSION_GRANTED &&
ContextCompat. checkSelfPermission (this, Manifest.permission. ACCESS_FINE_LOCATION ) !=
PackageManager. PERMISSION_GRANTED ) {

requestPermissions( new String[]{Manifest.permission. READ_PHONE_STATE ,
Manifest.permission. ACCESS_FINE_LOCATION , Manifest.permission. INTERNET }, 100);

return true ;
}
return false ;
}

/**
* This method handles the persimmon request response ,
* If permissions not granted, ask again.

84
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult( int requestCode, @NonNull String[]
permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 100) {
if (grantResults[ 0] == PackageManager. PERMISSION_GRANTED && grantResults[ 1]
== PackageManager. PERMISSION_GRANTED ) {
// addListenersToSwitch();
Utils.checkDeviceInformation ();
Intent i = new Intent(getApplicationContext(),
GSMDetailsToUiService. class);
startService(i);
SupportMapFragment m apFragment = (SupportMapFragment)
getSupportFragmentManager()
.findFragmentById(R.id. map);
mapFragment.getMapAsync( this);
//setting app the maps

} else {
permisionRequired ();

}
}

}

/**
* This method handles the menu items behaviour
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id. speedTest ) {
Intent in tent = new Intent(ConnectionLevelsActivity. this,
SpeedTestActivity. class);
startActivity(intent);
}
//noinspection SimplifiableIfStatement
if (id == R.id. action_settings ) {

SeekBar seekBar;

LayoutInflater inflater = (LayoutInflater)
this.getSystemService(Context. LAYOUT_INFLATER_SERVICE );
View popUpLayout = inflater.inflate(R.layout. settings_activity , null,
false);
popup = new PopupWindow(popUpLayout, ViewGroup.LayoutParams .WRAP_CONTENT ,
ViewGroup.LayoutParams. WRAP_CONTENT , true);
popup.showAtLocation( this.findViewById(R.id. main), Gravity. CENTER, 0, 0);

//dim background
View container = (View) popup.getContentView().getParent();
WindowManager wm = (WindowManager)
getSystemService(Context. WINDOW_SERVICE );
WindowManager.LayoutParams p = (WindowManager.LayoutParams)
container.getLayoutParams();
p.flags = WindowManager.LayoutParams. FLAG_DIM_BEHIND ;
p.dimAmount = 0.7f;
wm.updateViewLayout(container, p);

useCustomLocationSwitch = (Switch)

85
popUpLayout.findViewById(R.id. useCustomLocation );
useCustomLocationSwitch .setChecked(GlobalStaff. useCustomLocation );
useCustomLocationSwitch .setOnCheckedChangeListener( new
UseCustomLocationCustomListener());

retryJobSwitch = (Switch) popUpLayout.findViewById(R.id. jobRetrySwitch );
retryJobSwitch .setChecked( isJobRetry );
retryJobSwitch .setOnCheckedChangeListener( new
CustomRetryJobSwitchListener());

serverIpAddressED = (EditText) popUpLayout.findViewById(R.id. IpAddressED );
serverIpAddressED .setOnFocusChangeListener( new CustomEditTextListener());
serverIpAddressED .addTextChangedListener( new CustomTextWatcher());

seekBarProgressTV = (TextView)
popUpLayout.findViewById(R.id. seekBarProgress );
seekBarProgressTV .setText(String. valueOf("Current data send period is: " +
GlobalStaff. dataSendPeriod ) + " seconds" );

seekBar = (SeekBar) popUpLayout.findViewById(R.id. seekBarSendPeriod );
seekBar.setProgress(GlobalStaff. dataSendPeriod );
seekBar.setOnSeekBarChangeListener( new CustomSeekBarLis tener());

return true ;
}

return super .onOptionsItemSelected(item);
}

/**
* at the settings popup close, it saves the new IP address if valid
* @param v
*/
public void closePopup(View v) {
Utils.saveNewIpAddress (String. valueOf(serverIpAddressED .getText()));

popup.dismiss();
}

/**
* Show an alert dialog requesting for permission, if first time permission was
denied
*/
public void permisionRequired() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( this);
alertDialogBuilder.setMessage( "In order to use this application you need accept
the requested permissions" )
.setCancelable( false)
.setPositiveButton( "Try again!" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
askPermisions();
}
});
alertDialogBuilder.setNegativeButton( "Exit",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
finish();

}
});
alertDialogBuilder.setTitle( "Please approve requested permissions!" );
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}

86
/**
* This met hod executes when application goes to pause state, background or screen
is locked
*/
@Override
protected void onPause() {
super.onPause();
Intent i = new Intent(getApplicationContext(), GSMDetailsToUiService. class);
stopService(i);
}

/**
* Callback for the google map fragment.
* It executes immediately after the map is loaded
* @param googleMap
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = google Map;
// mMap.setMyLocationEnabled(true);
mMap.moveCamera(CameraUpdateFactory. newLatLngZoom (defaulLatLnt , 10.0f));
// mMapMaker = mMap.addMarker(new
MarkerOptions().position(defaulLatLnt).draggable(true));

GlobalStaff. globalLo cation = new Location(LocationManager. GPS_PROVIDER );
GlobalStaff. globalLocation .setLatitude( defaultLatitude );
GlobalStaff. globalLocation .setLatitude( defaultLongitude );
mMap.setOnMapClickListener( new CustomOnMapClickListener());
}
}
SpeedTestActivity
package com.sergiud.tarca.mynewdataaquisition.activities;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStat eList;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.sergiud.tarca.mynewdataaquisition.ExternalIntereface.CustomHttpClient;
import com.sergiud.tarca.mynewdataaquisition.Gatheri ngData.RetrieveNetworkParameters;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.ExernModels.InternetRateObj;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.Coordinates;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.InternetRates;
import com.sergiud.tarca.mynewdataaquisition.R;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;
import com.sergiud.tarca.mynewdataaquisition.listeners.CustomSpeedTesterListener;

import fr.bmartel.speedtest.SpeedTestSocket;

import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. telephonyManager ;

public class SpeedTestActivity extends AppCompatAct ivity {

//TODO custom file size
// https://github.com/bertrandmartel/speed -test-lib
// http://www.activejetbrains.ga

87
public static ImageButton downloadTestBtn , uploadTestBtn ;
public static Button sendDataBtn ;
public static ProgressB ar progressBar ;
public static TextView uploadValue , uploadValueDone ;
public static TextView downloadValue , downloadValueDone , percentValue ;
int SOCKET_TIMEOUT = 5000;
final String SPEED_TEST_SERVER_URI_DL = "http://ipv4.ikoula.testdebit.info/1M.iso" ;
final String SPEED_TEST_SERVER_URI_UL = "http://ipv4.ikoula.testdebit.info/" ;
// upload 10Mo file size.
private static final int FILE_SIZE_UPLOAD = 10000000 ;

@Override
protected void onDestroy() {
super.onDestroy();
}

/**
* Executes when speed test activity is launched
* Initialize the objects and listeners on them
*
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle sav edInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout. activity_speed_test );

downloadTestBtn = findViewById(R.id. startDownload );
uploadTestBtn = findViewById(R.id. startUpload );
progressBar = findViewById(R.id. progressBar );
progressBar .setProgressTintList(ColorStateList. valueOf(Color.RED));
downloadTestBtn .setOnClickListener( startDownloadTestListner );
uploadTestBtn .setOnClickListener( uploadTestListner );

sendDataBtn = findViewById(R.id. sendSpeedResultsBtn );
sendDataBtn .setOnClickListener( sendData );

uploadValue = findViewById(R.id. uploadCurrentRate );
downloadValue = findViewById(R.id. downloadCurrentRate );

uploadValueDone = findVie wById(R.id. uploadFieldDone );
downloadValueDone = findViewById(R.id. downloadFieldDone );

percentValue = findViewById(R.id. percentValue );

}

@Override
protected void onResume() {
super.onResume();
if (!isMobile()) {
disableWIFIAlert();
}
}

public void disableWIFIAlert() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( this);
alertDialogBuilder.setMessage( "In order measure the transfer data rate, please
disable the WIFI connection!" )
.setCancelable( false)
.setPositiveButton( "Disable WIFI" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent wifiIntent = new Intent(
Settings. ACTION_WIFI_SETTINGS );
getApplicationContext().startActivity(wifiIntent);
}
});
alertDialogBuilder.setNegativeButton( "Cancel" ,

88
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
onBackPressed();
}
});
alertDialogBuilder.setTitle( "WIFI Enabled?" );
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}

View.OnClickListener sendData = new View.OnClickListener() {

@Override
public void onClick(View v) {
// disableWIFIAlert();
if (isMobile()) {

if (GlobalStaff. globalLocation == null) {
return;
}
InternetRateObj objToSend = new InternetRateObj();
// TelephonyManager telephonyManager = (TelephonyManager)
getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);

String downV al = downloadValueDone .getText().toString();
double downloadRate = Double. valueOf(downVal.substring( 0,
downVal.indexOf( " ")));

String upVal = uploadValueDone .getText().toString();
double uploadRate = Double. valueOf(upVal.substring( 0, upVal.indexOf( "
")));
double lng = GlobalStaff. globalLocation .getLongitude();
double lat = GlobalStaff. globalLocation .getLatitude();
// double lng = 23.33;
// double l at = 43.55;

InternetRates rates = new InternetRates();

rates.setDownloadRate(downloadRate);
rates.setUploadRate(uploadRate);
objToSend.setInternetRates(rates);

Coordinates c oordinates = new Coordinates();
coordinates.setLng(lng);
coordinates.setLat(lat);
objToSend.setCoordinates(coordinates);

RetrieveNetworkParameters retrriveGSMParameters = new
RetrieveNetworkP arameters( telephonyManager );

objToSend.setSignalStrenght(retrriveGSMParameters.retrieveParameters());

new CustomHttpClient().post(objToSend);
} else Utils.toast("You currently use a WIFI Connection!" );

}
};

/**
* Check if the data connection is on mobile or other provider
*
* @return true if data connection is mobile
*/
private boolean isMobile() {
ConnectivityManager cm = (ConnectivityManager) getApplicat ionContext()
.getSystemService(Context. CONNECTIVITY_SERVICE );

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (null != activeNetwork) {

89
if (activeNetwork.getType() == ConnectivityManager. TYPE_MOBILE )
return true ;
}
return false ;
}

/**
* Define listener for download button
*/
View.OnClickListener startDownloadTestListner = new View.OnClickListener() {
public Thread thread;

@Override
public void onClick(View v) {
final SpeedTestSocket speedTestSocket = new SpeedTestSocket();
speedTestSocket.setSocketTimeout( SOCKET_TIMEOUT );

thread = new Thread(new Runnable() {

@Override
public void run() {
try {

speedTestSocket .startDownload( SPEED_TEST_SERVER_URI_DL );
uploadTestBtn .setClickable( false);
downloadTestBtn .setClickable( false);
} catch (Exception e) {
e.printStackTrace();
}
}
});
speedTestSocket.addSpeedTestListener( new CustomSpeedTesterListener());
thread.start();
}
};

/**
* Define listener for upload button
*/
View.OnClickListener uploadTestListner = new View.OnClickListener() {
public Thread thread;

@Override
public void onClick(View v) {
final SpeedTestSocket speedTestSocket = new SpeedTestSocket();
speedTestSocket.setSocketTimeout( SOCKET_TIMEOUT );

thread = new Thread(new Runnable() {

@Override
public void run() {
try {

speedTestSocket .startUpload( SPEED_TEST_SERVER_URI_UL ,
FILE_SIZE_UPLOAD );
uploadTestBtn .setClickable( false);
downloadTestBtn .setClickable( false);
} catch (Exception e) {
e.printStackTrace();
}
}
});
speedTestSocket.addSpeedTestListener( new CustomSpeedTesterListener());
thread.start();
}
};

}

90
9.3.2 HTTP Co mmunication
package com.sergiud.tarca.mynewdataaquisition.activities;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.sergiud.tarca.mynewdataaquisition.ExternalIntereface.CustomHttpClient;
import com.sergiud.tarca.mynewdataaquisition.Gat heringData.RetrieveNetworkParameters;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.ExernModels.InternetRateObj;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.Coordinates;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.InternetRates;
import com.sergiud.tarca.mynewdataaquisition.R;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;
import com.sergiud.tarca.mynewdataaquisition.listeners.CustomSpeedTeste rListener;

import fr.bmartel.speedtest.SpeedTestSocket;

import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. telephonyManager ;

public class SpeedTestActivity extends AppCompatActivity {

//TODO custom file size
// https://github.com/be rtrandmartel/speed -test-lib
// http://www.activejetbrains.ga

public static ImageButton downloadTestBtn , uploadTestBtn ;
public static Button sendDataBtn ;
public static ProgressBar progressBar ;
public static TextView uploadValue , uploadValueDone ;
public static TextView downloadValue , downloadValueDone , percentValue ;
int SOCKET_TIMEOUT = 5000;
final String SPEED_TEST_SERVER_URI_DL = "http://ipv4.ikoula.testdebit.info/1M.iso" ;
final String SPEED_TEST_SERVER_URI_UL = "http://ipv4.ikoula.testdebit.info/" ;
// upload 10Mo file size.
private static final int FILE_SIZE_UPLOAD = 10000000 ;

@Override
protected void onDestroy() {
super.onDestroy();
}

/**
* Executes when speed test activity is launched
* Initialize the objects and listeners on them
*
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInst anceState);
setContentView(R.layout. activity_speed_test );

downloadTestBtn = findViewById(R.id. startDownload );

91
uploadTestBtn = findViewById(R.id. startUpload );
progressBar = findViewById(R.id. progressBar );
progressBa r.setProgressTintList(ColorStateList. valueOf(Color.RED));
downloadTestBtn .setOnClickListener( startDownloadTestListner );
uploadTestBtn .setOnClickListener( uploadTestListner );

sendDataBtn = findViewById(R.id. sendSpeedResultsBtn );
sendDataBtn .setOnClickListener( sendData );

uploadValue = findViewById(R.id. uploadCurrentRate );
downloadValue = findViewById(R.id. downloadCurrentRate );

uploadValueDone = findViewById(R.id. uploadFieldDone );
downloadVa lueDone = findViewById(R.id. downloadFieldDone );

percentValue = findViewById(R.id. percentValue );

}

@Override
protected void onResume() {
super.onResume();
if (!isMobile()) {
disableWIFIAlert();
}
}

public void disableWIFIAlert() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder( this);
alertDialogBuilder.setMessage( "In order measure the transfer data rate, please
disable the WIFI connection!" )
.setCancelable( false)
.setPositiveButton( "Disable WIFI" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent wifiIntent = new Intent(
Settings. ACTION_WIFI_SETTINGS );
getApplicationContext().startActivity(wifiIntent);
}
});
alertDialogBuilder.setNegativeButton( "Cancel" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
onBackPressed();
}
});
alertDialogBuilder.setTitle( "WIFI Enabled?" );
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}

View.OnClickListener sendData = new View.OnClickListener() {

@Override
public void onClick(View v) {
// disableWIFIAlert();
if (isMobile()) {

if (GlobalStaff. globalLocation == null) {
return;
}
InternetRateObj objToSend = new InternetRateObj();
// TelephonyManager telephonyManager = (TelephonyManager)
getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);

String downVal = downloadValueDone .getText().toString();
double downloadRate = Double. valueOf(downVal.substring( 0,
downVal.indexOf( " ")));

92
String upVal = uploadValueDone .getText().toString();
double uploadRate = Double. valueOf(upVal.substrin g(0, upVal.indexOf( "
")));
double lng = GlobalStaff. globalLocation .getLongitude();
double lat = GlobalStaff. globalLocation .getLatitude();
// double lng = 23.33;
// double lat = 43.55;

InternetRates rates = new InternetRates();

rates.setDownloadRate(downloadRate);
rates.setUploadRate(uploadRate);
objToSend.setInternetRates(rates);

Coordinates coordinates = new Coordinates();
coordinates.setLng(lng);
coordinates.setLat(lat);
objToSend.setCoordinates(coordinates);

RetrieveNetworkParameters retrriveGSMParameters = new
RetrieveNetworkParameters( telephonyMan ager);

objToSend.setSignalStrenght(retrriveGSMParameters.retrieveParameters());

new CustomHttpClient().post(objToSend);
} else Utils.toast("You currently use a WIFI Connection!" );

}
};

/**
* Check if the data connection is on mobile or other provider
*
* @return true if data connection is mobile
*/
private boolean isMobile() {
ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
.getSystemService(Context. CONNECTIVITY_SERVICE );

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (null != activeNetwork) {
if (activeNetwork.getType() == ConnectivityManager. TYPE_MOBILE )
return true ;
}
return false ;
}

/**
* Define listener for download button
*/
View.OnClickListener startDownloadTestListner = new View.OnClickListener() {
public Thread thread;

@Override
public void onClick(View v) {
final SpeedTestSocket speedTestSocket = new SpeedTestSocket();
speedTestSocket.setSocketTimeout( SOCKET_TIMEOUT );

thread = new Thread(new Runnable() {

@Override
public void run() {
try {

speedTestSocket .startDownload( SPEED_TEST_SERVER_URI_DL );
uploadTestBtn .setClickable( false);
downloadTestBtn .setClickable( false);
} catch (Exception e) {
e.printStackTrace();
}

93
}
});
speedTestSocket.addSpeedTestListener( new CustomSpeedTesterListener());
thread.start();
}
};

/**
* Define listener for upload button
*/
View.OnClickListener uploadTestListner = new View.OnClickListener() {
public Thread thread;

@Override
public void onClick(View v) {
final SpeedTestSocket speedTestSocket = new SpeedTestSocket();
speedTestSocket.setSocketTimeout( SOCKET_TIMEOUT );

thread = new Thread(new Runnable() {

@Override
public void run() {
try {

speedTestSocket .startUpload( SPEED_TEST_SERVER_URI_UL ,
FILE_SIZE_UPLOAD );
uploadTestBtn .setClickable( false);
downloadTestBtn .setClickable( false);
} catch (Exception e) {
e.printStackTrace();
}
}
});
speedTestSocket.addSpeedTestListener( new CustomSpeedTesterListener());
thread.start();
}
};

}

9.3.3 DataRetrivers
package com.sergiud.tarca.mynewdataaquisition.GatheringData;

import android.annotation. SuppressLint ;
import android.os.Build;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.tele phony.CellInfoWcdma;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.ConnectionParameters;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;
import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;

import static android.telephony.TelephonyManager.*;

/**
* This class defines the methods retrieving the mobile ne twork connection parameters
*/

94
public class RetrieveNetworkParameters extends PhoneStateListener {
public static final String NETWORK_CLASS_UNKNOWN = "UNKNOWN" ;
public static final String NETWORK_CLASS_2_G = "2G";
public static final String NETWORK_CLASS_3_G = "3G";
public static final String NETWORK_CLASS_4_G = "4G";

public static final int NETWORK_TYPE_LTE_CA = 19;

private TelephonyManager telephonyManager ;

/**
* Constructor that initialize this telephonyManager in order to be used for
extracting parameters values
*
* @param telephonyManager
*/
public RetrieveNetworkParameters(TelephonyManager telephonyManager) {
this.telephonyManager = telephonyManager;
}

/**
* Defines the process of extracting mobile connection parameters
*
* @return ConnectionParameters object with extracted values
*/
@SuppressLint ("MissingPermission" )
public ConnectionParameters retrieveParameters() {
ConnectionParameters connectionParameters = new ConnectionParameters();
CellInfo cellInfo = null;
try {
//retrieve all cells information and select the first one, on which the
mobile terminal is connected
cellInfo = (Cel lInfo) GlobalStaff. telephonyManager .getAllCellInfo().get( 0);

//if connection is GSM
if (cellInfo instanceof CellInfoGsm) {
connectionParameters.setSignalDbm(((CellInfoGsm)
cellInfo).getCellSignalStrength().getDbm());
connectionParameters.setAsuLevel(((CellInfoGsm)
cellInfo).getCellSignalStrength().getAsuLevel());
connectionParame ters.setSignalStrengthLevel(((CellInfoGsm)
cellInfo).getCellSignalStrength().getLevel());
if (Build.VERSION. SDK_INT >= Build.VERSION_CODES. N) {
connectionParameters.setGsmRFchannelNumber(((CellInfoGsm)
cellInfo).getCellI dentity().getArfcn());
}
if (Build.VERSION. SDK_INT >= Build.VERSION_CODES. O) {
connectionParameters.setTimingAdvance(((CellInfoGsm)
cellInfo).getCellSignalStrength().getTimingAdvance());
}

}
//if connection is LTE
if (cellInfo instanceof CellInfoLte) {
connectionParameters.setSignalDbm(((CellInfoLte)
cellInfo).getCellSignalStrength().getDbm());
connectionParameters.setAsuL evel(((CellInfoLte)
cellInfo).getCellSignalStrength().getAsuLevel());
connectionParameters.setSignalStrengthLevel(((CellInfoLte)
cellInfo).getCellSignalStrength().getLevel());
connectionParameters.setTimingAdvance(((CellInfo Lte)
cellInfo).getCellSignalStrength().getTimingAdvance());

if (Build.VERSION. SDK_INT >= Build.VERSION_CODES. N) {
connectionParameters.setLteAbsoluteRFchannelNumber(((CellInfoLte)
cellInfo).getCellIdentity().getEarfcn( ));
}
if (Build.VERSION. SDK_INT >= Build.VERSION_CODES. O) {

95
connectionParameters.setRssnr(((CellInfoLte)
cellInfo).getCellSignalStrength().getRssnr());
connectionParameters.setRsrp(((C ellInfoLte)
cellInfo).getCellSignalStrength().getRsrq());
connectionParameters.setRsrp(((CellInfoLte)
cellInfo).getCellSignalStrength().getRsrp());
}

}
//if connection is 3G
if (cellInfo instanceof CellInfoWcdma) {

connectionParameters.setSignalDbm(((CellInfoWcdma)
cellInfo).getCellSignalStrength().getDbm());
connectionParameters.setAsuLevel(((CellInfoWcdma)
cellInfo).getCellSignalStrength().getAsuLevel ());
connectionParameters.setSignalStrengthLevel(((CellInfoWcdma)
cellInfo).getCellSignalStrength().getLevel());
if (Build.VERSION. SDK_INT >= Build.VERSION_CODES. N) {

connectionParameters.setWcdmaAbsolute RFchannelNumber(((CellInfoWcdma)
cellInfo).getCellIdentity().getUarfcn());
}
}

connectionParameters.setNetworkOperatorName( telephonyManager .getNetworkOperatorName());

connectionParameters.setNetworkOpera tor(telephonyManager .getNetworkOperator());

connectionParameters.setNetworkTypeClass( getNetworkClass (telephonyManager .getNetworkTyp
e()));

connectionParameters.setNetworkTypeName( getNetworkTypeName (telephonyManager .getNetworkT
ype()));
//the case when mobile terminal is not connected to any of cell
towers(remote area or undergrounds with no mobile network signal)
} catch (IndexOutOfBoundsException exception) {
}
//the case when som ething goes wrong with parameters extraction
catch (Exception e) {

Utils.toast("There has been an issue retrieving GSM details. \nPlease try
again later" );
ConnectionLevelsActivity. mainServiceSwitch .setChecked( false);

}
connectionParameters.setSimOperator( telephonyManager .getSimOperator());
connectionParameters.setSubscriberId( telephonyManager .getSubscriberId());
connectionParameters.setDeviceId( telephonyManager .getDeviceId());

return connectionParameters;

}

/*Arbitrary Strength Unit (ASU) is an integer value proportional to the received signal
strength measured by the mobile phone.
In GSM networks, ASU maps to RSSI (received signal strength indicator, see TS
27.007[2] sub cl ause 8.5).

dBm = 2 × ASU – 113, ASU in the range of 0..31 and 99 (for not known or not
detectable).
In UMTS networks, ASU maps to RSCP level (received signal code power, see TS
27.007[2] sub clause 8.69 and TS 25.133 sub clause 9.1.1.3).

dBm = ASU – 116, ASU in the range of -5..91 and 255 (for not known or not
detectable).
In LTE networks, ASU maps to RSRP (reference signal received power, see TS 36.133,
sub-clause 9.1.4). The valid range of ASU is from 0 to 97. For the range 1 to 96, ASU

96
maps to

(ASU – 141) ≤ dBm < (ASU – 140).
*/

/**
* Maps the String of Network Type Name to the integer provided by the Android API
*
* @param type
* @return String representing NetworkTypeName
*/
public static String getNetworkTypeName( int type) {
switch (type) {
case NETWORK_TYPE_GPRS :
return "GPRS";
case NETWORK_TYPE_EDGE :
return "EDGE";
case NETWORK_TYPE_UMTS :
return "UMTS";
case NETWORK_TYPE_HSDPA :
return "HSDPA";
case NETWORK_TYPE_HSUPA :
return "HSUPA";
case NETWORK_TYPE_HSPA :
return "HSPA";
case NETWORK_TYPE_ CDMA:
return "CDMA";
case NETWORK_TYPE_EVDO_0 :
return "CDMA – EvDo rev. 0" ;
case NETWORK_TYPE_EVDO_A :
return "CDMA – EvDo rev. A" ;
case NETWORK_TYPE_EVDO_B :
return "CDMA – EvDo rev. B" ;
case NETWORK_TYPE_1xRTT :
return "CDMA – 1xRTT";
case NETWORK_TYPE_LTE :
return "LTE";
case NETWORK_TYPE_EHRPD :
return "CDMA – eHRPD";
case NETWORK_TYPE_IDEN :
return "iDEN";
case NETWORK_TYPE_HSPAP :
return "HSPA+";
case NETWORK_TYPE_GSM :
return "GSM";
case NETWORK_TYPE_TD_SCDMA :
return "TD_SCDMA" ;
case NETWORK_TYPE_IWLAN :
return "IWLAN";
case NETWORK_TYPE_LTE_CA :
return "LTE_CA" ;
default:
@SuppressLint ("MissingPermission" ) int voiceNetworkType =
GlobalStaff. telephonyManager .getVoiceNetworkType();
return getNetworkTypeName (voiceNetworkType);
}
}

/**
* Maps the String of gNetwork Class name to the integer provided by the Android
API
*
* @param networkType
* @return String representing Network Class
*/
public static String getNetworkClass( int networkType) {
switch (networkType) {
case NETWORK_TYPE_GPRS :
case NETWORK_TYPE_GSM :
case NETWORK_TYPE_EDGE :

97
case NETWORK_TYPE_CDMA :
case NETWORK_TYPE_1xRTT :
case NETWORK_TYPE_IDEN :
return NETWORK_CLASS_2_G ;
case NETWORK_TYPE_UMTS :
case NETWORK_TYPE_EVDO_0 :
case NETWORK_TYPE_EVDO_A :
case NETWORK_TYPE_HSDPA :
case NETWORK_TYPE_HSUPA :
case NETWORK_TYPE_HSPA :
case NETWORK_TYPE_EVDO_B :
case NETWORK_TYPE_EHRPD :
case NETWORK_TYPE_HSPAP :
case NETWORK_TYPE_TD_SCDMA :
return NETWORK_CLASS_3_G ;
case NETWORK_TYPE_LTE :
case NETWORK_TYPE_IWLAN :
case NETWORK_TYPE_LTE_CA :
return NETWORK_CLASS_4_G ;
default:
@SuppressLint ("MissingPermission" ) int voiceNetworkType =
GlobalStaff. telephonyManager .getVoiceNetworkType();
return getNetworkClass (voiceNetworkType);
}
}
}
package com.sergiud.tarca.mynewdataaquisition.GatheringData;

import android.annotation. SuppressLint ;
import android.os.Build;
import android.telephony.TelephonyManager;

import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.DeviceProperties;

/**
* This class defines the method that retrieves the device and SIM information
*/

public class RetriveDeviceInformation {
private final TelephonyManager telephonyManager ;

/**
* Constructor that defines this telephonyManager, which will be used f or
extracting device and SIM details
* @param telephonyManager
*/
public RetriveDeviceInformation(TelephonyManager telephonyManager) {
this.telephonyManager = telephonyManager;
}

/**
* Method that extract the mobile device information, as well as SIM details
* @return DeviceProperties
*/
@SuppressLint ("MissingPermission" )
public DeviceProperties getDeviceProperties() {
DeviceProperties deviceInfo = new DeviceProperties();

deviceInfo.setDeviceId( telephonyManager .getDeviceId());
if (Build.VERSION. SDK_INT >= Build.VERSION_CODES. O) {
deviceInfo.setIMEI(telephonyManager.getImei());
}
try {
deviceInfo.set Mcc(telephonyManager.getNetworkOperator().substring( 0, 3));
deviceInfo.setMnc(telephonyManager.getNetworkOperator().substring( 3));
} catch (Exception e) {
}

deviceInfo.setSimOperator(telephonyManager.getSimOperator());

98
deviceInfo.setNetworkOperatorName(telephonyManager.getNetworkOperatorName());
deviceInfo.setDeviceModel(Build.MODEL);
deviceInfo.setDeviceManufacturer(Build.MANUFACTURER);
deviceInfo.setDevice(Build.DEVICE);
deviceIn fo.setSimCountryISO(telephonyManager.getSimCountryIso());
deviceInfo.setSubscriberID(telephonyManager.getSubscriberId());

return deviceInfo;
}

}
9.3.4 Listners
package com.sergiud.tarca.mynewdataaquisition.listeners;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;

import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;

/**
* This class implements LocationListener methods in order t o handle location changes
*/

public class CustomLocationListener extends ConnectionLevelsActivity implements
LocationListener {

private final Context context;

/**
* Constructor, Initialize this context, so it can be used to show the ale rt if
needed
* @param context
*/
public CustomLocationListener(Context context) {
this.context = context;
}

/**
* This method is executed whatever the location is changed.
* Updated the application global location a s well as Longitude and Latitude View
values
* @param location
*/
@Override
public void onLocationChanged(Location location) {
GlobalStaff.globalLocation = location;
latitudeTV.setText(String.valueOf(location.getLatitude() ));
longitudeTV.setText(String.valueOf(location.getLongitude()));
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override

99
public void onProviderEnabled(String provider) {
}

/**
* This executes whatever the location setting are modified.
* If the GPS is disabled and the use Custom Location input is false, is showing
the alert to enable the GPS in order to application run as expected
* @param s
*/
@Override
public void onProviderDisabled(String s) {
if (!GlobalStaff.useCustomLocation && s.equals(LocationManager.GPS_PROVIDER)) {
showGPSAlert();
}
}

/**
* Called in the moment that GPS provider is disabled , shows alert to enable GPS.
*
*/
public void showGPSAlert() {
AlertDialog. Builder alertDialogBuilder = new AlertDialog. Builder(context);
alertDialogBuilder.setMessage( "In order to use this application you need to
enable GPS. Would you like to enable it now?" )
.setCancelable( false)
.setPositiveButton( "Enable GPS" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent callGPSSettingIntent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startAc tivity(callGPSSettingIntent);
}
});
alertDialogBuilder.setNegativeButton( "Cancel" ,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();

}
});
alertDialogBuilder.setTitle( "GPS established?!" );
AlertDialog alert = alertDialogBuilder.create();
alert.show();
}

}
package com.sergiud.tarca.mynewdataaquisition.listeners;

import com.sergiud.tarca.mynewdataaquisition.activities.SpeedTestActivity;

import java.math.BigDecimal;
import java.text.DecimalFormat;

import fr.bmartel.speedte st.SpeedTestReport;
import fr.bmartel.speedtest.inter.ISpeedTestListener;
import fr.bmartel.speedtest.model.SpeedTestError;

/**
* This class implement the external source ISpeedTestListener methods used in Speed
Test activity
*/

public class CustomSpe edTesterListener extends SpeedTestActivity implements
ISpeedTestListener {

final BigDecimal rateBitsToMegaBytes = new BigDecimal( 1048576);
private final static DecimalFormat dataSpeedFormat = new DecimalFormat( "#.##");

/**

100
* Executes when the upload or download process is done successfully.
* The method enables back the buttons, set data rate result value to view text
objects
* @param report
*/
@Override
public void onCompletion( final SpeedTestRep ort report) {
runOnUiThread( new Runnable() {
@Override
public void run() {
SpeedTestActivity.uploadTestBtn.setClickable( true);
SpeedTestActivity.downloadTestBtn.setClickable( true);
switch (report.getSpeedTestMode()) {
case UPLOAD:
SpeedTestActivity.uploadValue.setText( "0.00 MB/s" );

SpeedTestActivity.uploadValueDone.setText(dataSpeedFormat.format(report.getTransf erRate
Bit().divide(rateBitsToMegaBytes)) + " MB/s");
break;
case DOWNLOAD:
SpeedTestActivity.downloadValue.setText( "0MB/s");

SpeedTestActivity.downloadValueDone.set Text(dataSpeedFormat.format(report.getTransferRa
teBit().divide(rateBitsToMegaBytes)) + " MB/s");
break;
}
}
});

}

/**
* During the upload/download process, this method is updating the current data
rate view text elements and handel the animation of process bar percentage
* @param percent
* @param report
*/
@Override
public void onProgress( final float percent, final SpeedTestReport report) {
SpeedTestAc tivity.progressBar.setProgress(( int) percent);

runOnUiThread( new Runnable() {
@Override
public void run() {
SpeedTestActivity.percentValue.setText(String.valueOf(( int) (percent))
+ "%");
try {
switch (report.getSpeedTestMode()) {
case UPLOAD:

SpeedTestActivity.uploadValue.setText(dataSpeedFormat.format(report.getTransferRateBit(
).divide(rateBitsToMegaBytes)) + " MB/s");

break;
case DOWNLOAD:

SpeedTestActivity.downloadValue.setText(dataSpeedFormat.format(report.getTransferRateBi
t().divide(rateBitsToMegaBytes)) + " MB/s");
break;
}
} catch (Exception e) {
}
}
});
}

/**
* In the case that anything goes wrong,all text view will be resetR.

101
* @param speedTestError
* @param errorMessage
*/
@Override
public void onError(SpeedTestError speedTestError, String errorMessage) {
runOnUiThread( new Runnable() {
@Override
public void run() {
SpeedTestActivity.uploadTestBtn.setClic kable(true);
SpeedTestActivity.downloadTestBtn.setClickable( true);
SpeedTestActivity.uploadValue.setText( "0.00 MB/s" );
SpeedTestActivity.downloadValue.setText( "0.00 MB/s" );
}
});

}
}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.View;
import android.widget.EditText;

/**
* Created by Sergiu on 10 -Jun-18.
*/

public class CustomEditTextListener implements EditText.OnFocusChangeListener{

@Override
public void onFocusChange(View u, boolean hasFocus) {
System.out.println( "focus"+hasFocus);
}

}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.location.Location;
import android.location.LocationManager;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;

/**
* Created by Sergiu on 2 8-Jun-18.
*/

public class CustomMarkerDragListener implements GoogleMap.OnMarkerDragListener {

@Override
public void onMarkerDragStart (Marker marker) {
GlobalStaff. globalLocation = new Location(LocationManager. GPS_PROVIDER );

}

@Override
public void onMarkerDrag(Marker marker) {
LatLng newLocation = marker.getPosition();

ConnectionLevelsActivity. latitudeTV .setText(String. valueOf(newLocation. latitude ));

ConnectionLevelsActivity. longitudeTV .setText(String. valueOf(newLocation. longitude ));

102

}

@Override
public void onMarkerDragEnd(Marker marker) {
float currentZoom = ConnectionLevelsActivity. mMap.getCameraPosition(). zoom;
LatLng newLocation = marker.getPosition();
GlobalStaff. globalLocation .setLatitude(newLocation. latitude );
GlobalStaff. globalLocation .setLongitude(newLocation. longitude );

ConnectionLevelsActivity. latitudeTV .setText(String. valueOf(newLocation. latitude ));

ConnectionLevels Activity. longitudeTV .setText(String. valueOf(newLocation. longitude ));
ConnectionLevelsActivity. mMap.moveCamera(CameraUpdateFactory. newLatLngZoom (new
LatLng(newLocation. latitude , newLocation. longitude ), currentZoom));

}
}
package com.sergiud.tar ca.mynewdataaquisition.listeners.ObjectsListners;

import android.location.Location;
import android.location.LocationManager;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.g ms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;

import static
com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity.mMap;
import static
com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity.mMapMaker;

public class CustomOnMapClickListener implements GoogleMap.OnMapClickListen er {

@Override
public void onMapClick(LatLng latLng) {
if (mMapMaker!= null){
mMapMaker.remove();
}
GlobalStaff.globalLocation = new Location(LocationManager.GPS_PROVIDER);
mMapMaker = ConnectionLevelsAct ivity.mMap.addMarker( new
MarkerOptions().position(latLng).draggable( false).title( "Current custom
position" ).draggable( true));
mMap.setOnMarkerDragListener( new CustomMarkerDragListener());
float currentZoom = ConnectionLevelsActivity.mMap.ge tCameraPosition().zoom;
LatLng newLocation = mMapMaker.getPosition();
GlobalStaff.globalLocation.setLatitude(newLocation.latitude);
GlobalStaff.globalLocation.setLongitude(newLocation.longitude);

ConnectionLevelsActivity.lat itudeTV.setText(String.valueOf(newLocation.latitude));

ConnectionLevelsActivity.longitudeTV.setText(String.valueOf(newLocation.longitude));
ConnectionLevelsActivity.mMap.moveCamera(CameraUpdateFactory.newLatLngZoom( new
LatLng(newLocation.la titude, newLocation.longitude), currentZoom));
}
}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.view.View;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.model.Lat Lng;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;

/**

103
* Created by Sergiu on 29 -Jun-18.
*/

public class CustomOnUseCustomLocationBtnListener implements View.OnClickListener {
@Override
public void onClick(View v) {
double
newLatitude =Double. parseDouble (ConnectionLevelsActivity. latitudeTV .getText().toString()
);
double newLongitude =
Double.parseDouble (ConnectionLevelsActivity. longitudeTV .getText().toString());

float currentZoom = ConnectionLevelsActivity. mMap.getCameraPosition(). zoom;
GlobalStaff. globalLocation .setLatitude( newLatitude );
GlobalStaff. globalLocation .setLongitude(newLongitude);
ConnectionLevel sActivity. mMapMaker .setPosition( new
LatLng(newLatitude ,newLongitude));
ConnectionLevelsActivity. mMap.moveCamera(CameraUpdateFactory. newLatLngZoom (new
LatLng(newLatitude , newLongitude), currentZoom));
}
}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.widget.CompoundButton;

import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;

/**
* Created by Sergiu on 10 -Jun-18.
*/

public class CustomRetryJobSwitchListener implements
CompoundButton.OnCheckedChangeListener {

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
GlobalStaff. isJobRetry = isChecked;

if (isChecked == true) {
buttonView.setTex t("Retry Job is Enabled, toggle to disable" );

} else if (isChecked == false) {
buttonView.setText( "Retry Job is Disabled, toggle to enable" );

}

}
}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.widget.SeekBar;

import com.sergiud.tarca.mynewdataaquisition.Utils.Constants;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;
import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;
import com.sergiud.ta rca.mynewdataaquisition.GlobalStaff;

/**
* Created by Sergiu on 10 -Jun-18.
*/

public class CustomSeekBarListener implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ConnectionLevelsActivity. seekBarProgressTV .setText( "Current data send period is
" + progress);
GlobalStaff. dataSendPeriod = progress;
Utils.setPreferences (Constants. DATE_SEND_PERIOD , progress);
}

104

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.text.Editable;
import android.u til.Patterns;
import android.widget.TextView;

import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;

/**
* Created by Sergiu on 10 -Jun-18.
*/

public class CustomTextWatcher implements android.text.TextWatcher{

@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {

}

@Override
public void afterTextChanged(Editable s) {

if(Patterns. IP_ADDRESS .matcher(s).matches()&&Patterns. WEB_URL.matcher(s).matches()){

}
Utils.toast("no valid url" );

}
}
package com.sergiud.tarca.mynewdataaquisition.listeners.ObjectsListners;

import android.view.View;
import android.widget.CompoundButton;

import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;

import static
com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity. frameLayout ;
import static
com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity. latitudeTV ;
import static
com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity. longitudeTV ;
import static
com.sergiud.tarca.mynewdataaquisition.activitie s.ConnectionLevelsActivity. mainServiceSw
itch;
import static
com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity. manualLocatio
nInputBtn ;

/**
* Created by Sergiu on 28 -Jun-18.
*/

public class UseCustomLocationCustomListener implemen ts
CompoundButton.OnCheckedChangeListener {

105
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Utils.toast("Please tap the map on desired position, \nDrag the marker or,
\nManually input the coordinates" );
frameLayout .setVisibility(View. VISIBLE);
longitudeTV .setEnabled( true);
latitudeTV .setEnabled( true);
manualLocationInputBtn .setVisibility(View. VISIBLE);

} else {
frameLayout .setVisibility(View.INVISIBLE);
longitudeTV.setEnabled( false);
latitudeTV.setEnabled( false);
GlobalStaff.globalLocation= null;
manualLocationInputBtn.setVisibility(View.INVISIBLE);
mainServiceSwitch.setChecked( false);
}
GlobalStaff.useCustomLocation = isChecked;

}
}
9.3.5 Database helper
package com.sergiud.tarca.mynewdataaquisition.persistentData.helper;

import android.content.ContentValues;
import android.co ntent.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.sergiud.tarca.mynewdataaquisition.Models.ExernModels.ExportData Obj;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.Coordinates;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.ConnectionParameters;

import java.util.ArrayList;
import java.util.List;

/**
* This class extents the SQ LiteOpenHelper, it access the local database create in
device.
*/

public class DatabaseHelper extends SQLiteOpenHelper {

private static final String PROCCESED_N = "N";
private static final String PROCCESED_Y = "Y";

private static final String DATABASE_NAME = "localDB" ;
private static final int DATABASE_VERSION = 1;
private static final String TABLE_NAME = "TBL_TEMPORARY_DATA" ;
private static final String INDEX = "key";

private static final String ID = "id";
private s tatic final String LONGITUDE = "longitude" ;
private static final String LATITUDE = "latitude" ;

private static final String DEVICE_ID = "deviceId" ;
private static final String SIGNAL_DBM = "signalDbm" ;
private static final String SIGNAL_STRENGTH_LEVEL = "signalStrengthLevel" ;
private static final String ASU_LEVEL = "asuLevel" ;
private static final String TIMING_ADVANCE = "timingAdvance" ;

private static final String RSSNR = "Rssnr";
private static final String RSRQ = "Rsrq";
private static final String RSRP = "Rsrp";

106
private static final String NETWORK_OPERATOR = "networkOperator" ;
private static final String NETWORK_TYPE_CLASS = "networkTypeClass" ;
private static final String NETWORK_TYPE_NAME = "networkTypeName" ;
private static final String NETWORK_OPERATOR_NAME = "networkOperatorName" ;

private static final String GSM_RF_CHANNEL_NUMBER = "gsmRFchannelNumber" ;
private static final String LTE_ABSOLUTERF_CHANNEL_NUMBER =
"lteAbsoluteRFchannelNumber" ;
private static final String WCDMA_ABSOLUTERF_CHANNEL_NUMBER =
"wcdmaAbsoluteRFchannelNumber" ;

private static final String SUBSCRIBER_ID = "subscriberId" ;
private static final String SIM_OPERATOR = "simOperator" ;
private static final String TIMESTAMP = "timestamp" ;
private static final String PROCESSED = "processed" ;
/*
Define the string to create the table in the database
*/
private final static String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ INDEX + " INTEGER PRIMARY KEY autoincrement, "
+ ID + " INTEGER, "
+ LATITUDE + " DOUBLE, "
+ LONGITUDE + " DOUBLE,"

+ SIGNAL_DBM + " INTEGER, "
+ SIGNAL_STRENGTH_LEVEL + " INTEGER, "
+ ASU_LEVEL + " INTEGER, "
+ TIMING_ADVANCE + " INTEGER, "

+ RSSNR + " INTEGER, "
+ RSRQ + " INTEGER, "
+ RSRP + " INTEGER, "

+ NETWORK_OPERATOR + " VARCHAR, "
+ NETWORK_TYPE_CLASS + " VARCHAR, "
+ NETWORK_TYPE_NAME + " VARCHAR, "
+ NETWORK_OPERATOR_NAME + " VARCHAR, "

+ GSM_RF_CHANNEL_NUMBER + " INTEGER, "
+ LTE_ABSOLUTERF_CHANNEL_NUMBER + " INTEGER, "
+ WCDMA_ABSOLUTERF_CHANNEL_NUMBER + " INTEGER, "

+ DEVICE_ID + " VARCHAR, "
+ SUBSCRIBER_ID + " VARCHAR, "
+ SIM_OPERATOR + " VARCHAR, "

+ PROCESSED + " VARCHAR DEFAULT 'N',"
+ TIMESTAMP + " TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL"
+ ")";

public DatabaseHelper(Context context) {
super(context, DATABASE_NAME , null, DATABASE_VERSION );
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL( CREATE_TABLE );
}

/**
* On upgrade, the database table will dropped in order to fulfill new
modifications, if any.
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabas e db, int oldVersion, int newVersion) {

107
db.execSQL( "DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}

/**
* Inserts the received samples into database TBL_TEMPORARY_DATA table
* @param obj
*/
public void newEntry(ExportDataObj obj) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(ID, obj.getId());
values.put(LONGITUDE, obj.getCoordinates().getLng());
values.put(LATITUDE, obj.getCoordinates().getLat());

values.put(SIGNAL_DBM, obj.getSignalStrenght().getSignalDbm());
values.put(SIGNAL_STRENGTH_LEVEL,
obj.getSignalStrenght().getSignalStrengthLevel());
values.put(ASU_LEVEL, obj.getSignalStrenght().getAsuLevel());
values.put(TIMING_ADVANCE, obj.getSignalStrenght().getTimingAdvance());

values.put(RSSNR, obj.getSignalStrenght().getRssnr());
values.put(RSRQ, obj.getSignalStrenght().getRsrq());
values.put(RSRP, obj.getSignalStrenght().getRsrp());

values.put(GSM_RF_CHANNEL_NUMBER,
obj.getSignalStrenght().getGsmRFchannelNumber());
values.put(LTE_ABSOLUTERF_CHANNEL_NUMBER,
obj.getSignalStrenght().getLteAbsoluteRFchannelNumber());
values.put(WCDMA_ABSOLUTERF_CHANNEL_NUMBER,
obj.getSignalStrenght().getWcdmaAbsoluteRFchannelNumber());

values.put(NETWORK_OPERATOR, obj.getSignalStrenght().getSignalDbm());
values.put(NETWORK_TYPE_CLASS, obj.getSignalStrenght().getNet workTypeClass());
values.put(NETWORK_TYPE_NAME, obj.getSignalStrenght().getNetworkTypeName());
values.put(NETWORK_OPERATOR_NAME,
obj.getSignalStrenght().getNetworkOperatorName());
values.put(SUBSCRIBER_ID, obj.getSignalStrenght().ge tSubscriberId());
values.put(SIM_OPERATOR, obj.getSignalStrenght().getSimOperator());
values.put(DEVICE_ID, obj.getSignalStrenght().getDeviceId());
values.put(TIMESTAMP, obj.getTimestamp());

db.insert(TABLE_NAME, null, values);
}

/**
* Interrogate the local database for failed sent transactions, used by the retry
job
* @return a list of ExportDataObj object that was not successfully sent
*/
public List<ExportDataObj> getUnpprocesedNew() {
List<ExportDataObj> returnObj = new ArrayList();
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT * FROM " + TABLE_NAME + " where " + PROCESSED + "
= '" + PROCCESED_N + "';";

Cursor c = db.rawQuery(sele ctQuery, null);
if (c != null) {
for (int i = 0; i < c.getCount(); i++) {
if (c.moveToPosition(i)) {

ExportDataObj obj = new ExportDataObj();
obj.setId(c.getInt(c.getColumnIndex(I D)));
Coordinates coordinates = new Coordinates();
coordinates.setLat(c.getDouble(c.getColumnIndex(LATITUDE)));
coordinates.setLng(c.getDouble(c.getColumnIndex(LONGITUDE)));
obj.setCoordinates(coordinates);

ConnectionParameters connectionParameters = new
ConnectionParameters();

108

connectionParameters.setSignalDbm(c.getInt(c.getColumnIndex(SIGNAL_DBM)));

connectionParame ters.setSignalStrengthLevel(c.getInt(c.getColumnIndex(SIGNAL_STRENGTH_L
EVEL)));

connectionParameters.setAsuLevel(c.getInt(c.getColumnIndex(ASU_LEVEL)));

connectionParameters.setTimingAdvance(c.getInt(c.getColumnIndex (TIMING_ADVANCE)));

connectionParameters.setRssnr(c.getInt(c.getColumnIndex(RSSNR)));
connectionParameters.setRsrq(c.getInt(c.getColumnIndex(RSRQ)));
connectionParameters.setRsrp(c.getInt(c.getCo lumnIndex(RSRP)));

connectionParameters.setNetworkOperator(c.getString(c.getColumnIndex(NETWORK_OPERATOR))
);

connectionParameters.setNetworkTypeClass(c.getString(c.getColumnIndex(NETWORK_TYPE_CLAS
S)));

connectionParameters.setNetworkOperatorName(c.getString(c.getColumnIndex(NETWORK_OPERAT
OR_NAME)));

connectionParameters.setNetworkTypeName(c.getString(c.getColumnIndex(NETWORK_TYPE_NAME)
));

connectionParamete rs.setGsmRFchannelNumber(c.getInt(c.getColumnIndex(GSM_RF_CHANNEL_NUM
BER)));

connectionParameters.setLteAbsoluteRFchannelNumber(c.getInt(c.getColumnIndex(LTE_ABSOLU
TERF_CHANNEL_NUMBER)));

connectionParameters.setWcdm aAbsoluteRFchannelNumber(c.getInt(c.getColumnIndex(WCDMA_AB
SOLUTERF_CHANNEL_NUMBER)));

connectionParameters.setSimOperator(c.getString(c.getColumnIndex(SIM_OPERATOR)));

connectionParameters.setSubscriberId(c.getStri ng(c.getColumnIndex(SUBSCRIBER_ID)));

connectionParameters.setDeviceId(c.getString(c.getColumnIndex(DEVICE_ID)));
obj.setSignalStrenght(connectionParameters);
obj.setTimestamp(c.getLong(c.getColum nIndex(TIMESTAMP)));
returnObj.add(obj);
}
}
}
return returnObj;
}

/**
* Remove the specified entry from local db.
* Used when the sampled was submitted with success
* @param id
* @return true if there was modifies done over the table entries.
*/
public boolean removeEntryByID( int id) {
SQLiteDatabase db = this.getReadableDatabase();
return db.delete(TABLE_NAME, ID + "=" + id, null) > 0;
}

}

109
9.3.6 Services
package com.sergiud.tarca.mynewdataaquisition.Services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Handler;
import android.os.I Binder;
import android.support.annotation. Nullable ;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

import com.sergiud.tarca.mynewdataaquisition.GatheringData.RetrieveNetworkParameters;
import com.sergiud.tarca.myne wdataaquisition.Models.InternModels.ConnectionParameters;
import com.sergiud.tarca.mynewdataaquisition.Utils.Constants;

import java.util.concurrent.TimeUnit;

import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. globalLocationListner ;
import st atic com.sergiud.tarca.mynewdataaquisition.GlobalStaff. locationManager ;
import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. telephonyManager ;

/**
* This class extends Service. Handles the updates done on elements in the main
activity.
*/
public class GSMDetailsToUiService extends Service {

private Handler uiUpdateHandeler ;
static Runnable uiUpdateThread ;
private RetrieveNetworkParameters retriveGSMParameters ;

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null ;
}

/**
* Executes when the service is created.Initialize the location manager,telephony
manager.
* Also defines a Runnable which at every second will update the UI elements
*/
@Override
public void onCreate() {
locationManager .requestLocationUpdates(LocationManager. GPS_PROVIDER , 3000,
0.5f, globalLocationListner );
uiUpdateHandeler = new Handler();
telephonyManager = (TelephonyManager)
getApplicationContext().getSystemService(Conte xt.TELEPHONY_SERVICE );

retriveGSMParameters = new RetrieveNetworkParameters( telephonyManager );

telephonyManager .listen( new PhoneStateListener(),
PhoneStateListener. LISTEN_CALL_STATE
| PhoneStateListener. LISTEN_CELL_INFO // Requires API 17
| PhoneStateListener. LISTEN_CELL_LOCATION
| PhoneStateListener. LISTEN_DATA_ACTIVITY
| PhoneStateListener. LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener. LISTEN_SERVICE_STATE
| PhoneStateListener. LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener. LISTEN_CALL_FORWARDING_INDICATOR
| PhoneStateListener. LISTEN_MESSAGE_WAITING_INDICATOR );

//define the instruction to run on every se cond
uiUpdateThread = new Runnable() {

110
@Override
public void run() {
uiUpdateHandeler .postDelayed( this,
TimeUnit. SECONDS.toMillis(Constants. uiRefreshInterval ));
Intent i = new Intent(Constants .BROADCAST_FILTER );
ConnectionParameters connectionParameters =
retriveGSMParameters .retrieveParameters();
try {
i.putExtra(Constants. EXTRA_INTENT_SERVICE_TO_FRONT ,
connectionParameters);
} catch (Exception e) {
}
sendBroadcast(i);
}

};
//starts the runnable
uiUpdateHandeler .post(uiUpdateThread );

}

/**
* Executes when application is destroy or in pause state.
* It removes Callbacks over the Runnable.(Stop the thread)
*/
@Override
public void onDestroy() {
super.onDestroy();
//stop thread
uiUpdateHandeler .removeCallbacks( uiUpdateThread );
}

} package com.sergiud.tarca.mynewdataaquisition.Services;

import android.app.Service;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation. Nullable ;

import com.sergiud.tarca.mynewdataaquisition.ExternalIntereface.CustomHttpClient;
import com.sergiud.tarca.mynewdataaquisition.GatheringData.RetrieveNetworkParameters;
import com.sergiud.tarca.mynewdataaquisition.Gl obalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.ExernModels.ExportDataObj;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.ConnectionParameters;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.Coordinates;
import com.sergiud.tarca.mynewdataaquisition.Utils.Utils;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. globalLocationListner ;
import static com.sergiud .tarca.mynewdataaquisition.GlobalStaff. locationManager ;
import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. telephonyManager ;

/**
* This class Extends Service abstract class.
* The processes define in this class run to sent the samples over the HTTP to the
server.
*/
public class MainBackgroundSerivce extends Service {
//define an atomic counter
public static AtomicLong counter = new AtomicLong();
private CustomHt tpClient restServices ;

private Handler onLinePostHandler ;

111
static Runnable onLineRestThread ;
private RetrieveNetworkParameters retriveGSMParameters ;

/**
* Excecutes once, when the service is started
* @param intent
* @param flags
* @param startId
* @return int START_STICKY=1, in order to be able run in background or if screen
is shutoff.
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);

//return Start_Sticky so that service run in background and screen off
return START_STICKY ;
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null ;
}

/**
* Executes once when the Intent for service is created.
* Initialize the Retrieve Network Parameters class, set location updates on
location manager,
* Defines the runnable that retrieve the connection parameters and send them to
server over HTTP
*/
@Override
public void onCreate() {
restServices = new CustomHttpClient();
onLinePostHandler = new Handler();

retriveGSMParameters = new RetrieveNetworkParameters( telephonyManager );
locationMana ger.requestLocationUpdates(LocationManager. GPS_PROVIDER , 3000,
0.5f, globalLocationListner );
// telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE
// | PhoneStateListener.LISTEN_CELL_INFO // Requires API 17
// | PhoneStateListener.LISTEN_CELL_LOCATION
// | PhoneStateListener.LISTEN_DATA_ACTIVITY
// | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
// | PhoneStateListener.LISTEN_SERVICE_STATE
// | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
// | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
// | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR);

//online job
onLineRestThread = new Runnable() {
@Override
public void run() {
onLinePostHandler .postDelayed( this,
TimeUnit. SECONDS.toMillis(GlobalStaff. dataSendPeriod ));

ExportDataObj objToSend = new ExportDataObj();
if (GlobalStaff. globalLocation != null &&
GlobalStaff. globalLocation .getLongitude() != 0.0) {
objToSend.setId( counter.incrementAndGet());

Coordinates coordinates = new Coordinates();
coordinates.setLn g(GlobalStaff. globalLocation .getLongitude());
coordinates.setLat(GlobalStaff. globalLocation .getLatitude());

objToSend.setCoordinates(coordinates);

ConnectionParameters connectionParameters =

112
retriveGSMParameters .retrieveParameters();
objToSend.setSignalStrenght(connectionParameters);

objToSend.setTimestamp(Utils. getCurrentTimeStampLong ());

GlobalStaff. db.newEntry(objToSend);
restServices .post(objToSend);
}

}
};

onLinePostHandler .postDelayed( onLineRestThread , 1000);

}

/**
* Execute when the app is destroyed, or stop command for the service is used .
* Removes the Runnable callbacks.(Stop the thread)
*/
@Override
public void onDestroy() {
super.onDestroy();
//stop thread
onLinePostHandler .removeCallbacks( onLineRestThread );
}

}
package com.sergiud.tarca. mynewdataaquisition.Services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation. Nullable ;
import android.util.Log;

import com.sergiud.tarca.mynewdataaquisition.ExternalIntereface.CustomHttpClient;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.E xernModels.ExportDataObj;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;

/**
* This class Extends Service abstract class.
* In this class is find the operation that try to resent the failed samples
*/

public class RetryJob extends Service {
private Handler offLinePostHandler ;
static Runnable offLineRestThread ;
private CustomHttpClient restServices ;

//how often the run should run
public int jobPeriodicallyTimeInMillis = 60000;
String TAG = this.getClass().getSimpleName();
/**
* Check if there is a data connection, either Mobile or WIFI
* @return true if there is active data connection in place
*/
public boolean isInternetAvailable() {
ConnectivityManager cm = (ConnectivityManager) getApplicationContext()

113
.getSystemService(Context. CONNECTIVITY_SERVICE );

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (null != activeNetwork) {
if (activeNetwork.getType() == ConnectivityManager. TYPE_WIFI )
return true ;

if (activeNetwork.getType() == ConnectivityManager. TYPE_MOBILE )
return true ;
}
return false ;
}

/**
* Executes when the service is create.
* Initialize the Runnable which tries to resend the failed samples, store in local
database.
*/
@Override
public void onCreate() {
restServices = new CustomHttpClient();
offLinePostHandler = new Handler();

offLineRestThread = new Runnable() {
@Override
public void run() {
offLinePostHandler .postDelayed( this, jobPeriodicallyTimeInMillis );
//check if data connection available, in the database table are unprocessed entries and
if job is enabled(by default false)
if (isInternetAvailable() &&
!(GlobalStaff. db.getUnpprocesedNew().isEmpty()) && GlobalStaff. isJobRetry ) {
int unprocessedSamplesNo=
GlobalStaff. db.getUnpprocesedNew().size();
Log.i(TAG,"–––––––– Retry job started –––––-
");
try {
for (ExportDataObj entry : GlobalStaff. db.getUnpprocesedNew())
{
restServices .post(entry);
}
Log.i(TAG,"–––––––– Retry job finished ––––
––\n "+unprocessedSamplesNo + " samples resent" );

} catch (Exception e) {
Log.e(TAG,e.getCause().toString());
}

}
}
};
//starts Runnable
offLinePostHandler.post(offLineRestThread);

}

@Nullable
@Override
public IBinder onBind(Inten t intent) {
return null ;
}
}
9.3.7 Models
package com.sergiud.tarca.mynewdataaquisition.Models.InternModels;

114
import java.io.Serializable;

/**
* This class defines ConnectionParameters object
*/

public class ConnectionParameters implements Serializable {
private String deviceId ;

public ConnectionParameters() {
this.asuLevel =255;
this.signalDbm =2147483647 ;
this.signalStrengthLevel =0;
this.networkTypeClass ="UNKNOWN" ;
this.networkOperatorName ="UNKNOWN";
this.networkOperator ="UNKNOWN" ;
this.networkTypeName ="UNKNOWN" ;
}

private int signalDbm ;
private int signalStrengthLevel ;
private int asuLevel ;
private int timingAdvance ;

private int rssnr;
private int rsrq;
private int rsrp;

private int gsmRFchannelNumber ;
private int lteAbsoluteRFchannelNumber ;
private int wcdmaAbsoluteRFchannelNumber ;

private String networkTypeClass ;
private String networkTypeName ;
private String networkO peratorName ;
private String networkOperator ;
private String subscriberId ;
private String simOperator ;

public String getSubscriberId() {
return subscriberId ;
}

public void setSubscriberId(String subscriberId) {
this.subscriberId = subscriberId;
}

public String getSimOperator() {
return simOperator ;
}

public void setSimOperator(String simOperator) {
this.simOperator = simOperator;
}

public int getRssnr() {
return rssnr;
}

public void setRssnr( int rssnr) {
this.rssnr = rssnr;
}

public int getRsrq() {
return rsrq;
}

public void setRsrq( int rsrq) {
this.rsrq = rsrq;
}

115

public int getRsrp() {
return rsrp;
}

public void setRsrp( int rsrp) {
this.rsrp = rsrp;
}

public int getTimingAdvance() {
return timingAdvance ;
}

public void setTimingAdvance( int timingAdvance) {
this.timingAdvance = timingAdvance;
}

public String getDeviceId() {
return deviceId ;
}

public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}

public String getNetworkTypeClass() {
return networkTypeClass ;
}

public void setNetworkTypeClass(String networkTypeClass) {
this.networkTypeClass = networkTypeClass;
}

public String getNetworkOperator() {
return networkOperator ;
}

public void setNetworkOperator(String networkOperator) {
this.networkOperator = networkOperator;
}

public int getSignalStrengthLevel() {
return signalStrengthLevel ;
}

public void setSignalStrengthLevel( int signalStrengthLevel) {
this.signalStrengthLevel = signalStrengthLevel;
}

public int getAsuLevel() {
return asuLevel ;
}

public void setAsuLevel( int asuLevel) {
this.asuLevel = asuLevel;
}

public String getNetworkTypeName() {
return networkTypeName ;
}

public void setNetwo rkTypeName(String networkTypeName) {
this.networkTypeName = networkTypeName;
}

public String getNetworkOperatorName() {
return networkOperatorName ;
}

116

public void setNetworkOperatorName(String networkOperatorName) {
this.networkOperatorName = networkOperatorName;
}

public int getSignalDbm() {

return signalDbm ;
}

public int getGsmRFchannelNumber() {
return gsmRFchannelNumber ;
}

public void setGsmRFchannelNumber( int gsmRFchan nelNumber) {
this.gsmRFchannelNumber = gsmRFchannelNumber;
}

public void setSignalDbm( int signalDbm) {
this.signalDbm = signalDbm;
}

public int getLteAbsoluteRFchannelNumber() {
return lteAbsoluteRFchannelNumber ;
}

public void setLteAbsoluteRFchannelNumber( int lteAbsoluteRFchannelNumber) {
this.lteAbsoluteRFchannelNumber = lteAbsoluteRFchannelNumber;
}

public int getWcdmaAbsoluteRFchannelNumber() {
return wcdmaAbsoluteRFchannelNumb er;
}

public void setWcdmaAbsoluteRFchannelNumber( int wcdmaAbsoluteRFchannelNumber) {
this.wcdmaAbsoluteRFchannelNumber = wcdmaAbsoluteRFchannelNumber;
}
}
package com.sergiud.tarca.mynewdataaquisition.Models.InternModels;

import java.io.Serializable;

/**
* This class defines Coordinates object
*/

public class Coordinates implements Serializable{
private double lng;

public double getLng() {
return lng;
}

public void setLng(double lng) {
this.lng = lng;
}

public double getLat() {
return lat;
}

public void setLat(double lat) {
this.lat = lat;
}

private double lat;
}
package com.sergiud.tarca.mynewdataaquisition.Models.InternModels;

/**

117
* This class defines Device properties object
*/

public class DeviceProperties {
private String deviceId ;
private String imei;
private String mcc;
private String mnc;
private String simOperator ;
private String networkOperatorName ;
private String simCountryISO ;
private String subscriberID ;
private String deviceModel ;
private String deviceManufacturer ;
private String device;
private String networkTypeName ;
private String networkClass ;
private String networkType ;

public String getNetworkOperatorName() {
return networkOperatorName ;
}

public void setNetworkOperatorName(String networkOperatorName) {
this.networkOperatorName = networkOperatorName;
}

public String getS imCountryISO() {
return simCountryISO ;
}

public void setSimCountryISO(String simCountryISO) {
this.simCountryISO = simCountryISO;
}

public String getImei() {
return imei;
}

public void setImei(String imei) {
this.imei = imei;
}

public String getSimOperator() {
return simOperator ;
}

public void setSimOperator(String simOperator) {
this.simOperator = simOperator;
}

public String getIMEI() {
return imei;
}

public void setIMEI(String IMEI) {
this.imei = IMEI;
}

public String getDeviceId() {
return deviceId;
}

public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}

public String g etMcc() {
return mcc;

118
}

public void setMcc(String mcc) {
this.mcc = mcc;
}

public String getMnc() {
return mnc;
}

public void setMnc(String mnc) {
this.mnc = mnc;
}

public String getSubscriberID() {
return subscriberID;
}

public void setSubscriberID(String subscriberID) {
this.subscriberID = subscriberID;
}

public String getDeviceModel() {
return deviceModel;
}

public void setDevic eModel(String deviceModel) {
this.deviceModel = deviceModel;
}

public String getDeviceManufacturer() {
return deviceManufacturer;
}

public void setDeviceManufacturer(String deviceManufacturer) {
this.deviceManufact urer = deviceManufacturer;
}

public String getDevice() {
return device;
}

public void setDevice(String device) {
this.device = device;
}

public String getNetworkTypeName() {
return networkTypeName;
}

public void setNetworkTypeName(String networkTypeName) {
this.networkTypeName = networkTypeName;
}

public String getNetworkClass() {
return networkClass;
}

public void setNetworkClass(String networkClass) {
this.networkClass = networkClass;
}

public String getNetworkType() {
return networkType;
}

public void setNetworkType(String networkType) {
this.networkType = networkType;

119
}
}
package com.sergiud.tarca.mynewdataaquisition .Models.InternModels;

/**
* This class defines Internet Rates object
*/

public class InternetRates {
double downloadRate ;
double uploadRate ;

public double getDownloadRate() {
return downloadRate ;
}

public void setDownloadRat e(double downloadRate) {
this.downloadRate = downloadRate;
}

public double getUploadRate() {
return uploadRate ;
}

public void setUploadRate( double uploadRate) {
this.uploadRate = uploadRate;
}
}
package com.sergiud.tarca.mynewdataaquisition.Models.ExernModels;

import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.Coordinates;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.ConnectionParameters;

import java.io.Serializable;

/**
* This class defines the object prepared to be sent over HTTP to the server.
*
*/

public class ExportDataObj implements Serializable{
private long id;
private Coordinates coordinates ;
private ConnectionParameters signalStrenght ;
private long timestamp ;

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public Coordinates getCoordinates() {
return coordinates ;
}

public void setCoordinates(Coordinates coordinates) {
this.coordinates = coordinates;
}

public ConnectionParameters getSignalStrenght() {
return signalStrenght ;
}

public void setSignalStrenght(ConnectionParameters signalStrenght) {
this.signalStrenght = signalStrenght;
}

120
public long getTimestamp() {
return timestamp ;
}

public void setTimestamp( long timestamp) {
this.timestamp = timestamp;
}
}
package com.sergiud.tarca.mynewdataaquisition.Models.ExernModels;

import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.InternetRates;

/**
* This class defines the Internet Rate object prepared to be sent over HTTP to the
server when a speed test is ran.
* Extend the ExportDataObject, adding the InternetRates objec t to it structure.
*/

public class InternetRateObj extends ExportDataObj {
private InternetRates internetRates ;

public void setInternetRates(InternetRates rates) {
this.internetRates = rates;
}
}

9.3.8 Misc
package com.sergiud.tarca.mynewdat aaquisition;

import android.content.Context;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.telephony.TelephonyManager;

import com.sergiud.tarca.mynewdataaquisition.persistentData.helper.DatabaseHelper;

/**
* This class contains the objects used over the whole application.
* These objects are public, accessible by any entity in the project.
*/

public class GlobalStaff {
public static Boolean isJobRetry = false;
// public static String serverIpAddress = "192.168.100.6:8080";
public static String serverIpAddress = "mypersonalhost.go.ro" ;
public static int dataSendPeriod ;
public static SharedPreferences pref;
public static DatabaseHelper db;

public static LocationListener globalLocationListner ;
public static LocationManager locationManager ;
public static TelephonyManager telephonyManager ;

public static Location globalLocation = new Location(LocationManager. GPS_PROVIDER );
public static Context appContext ;

public static boolean useCustomLocation =false;
}
package com.sergiud.tarca.mynewdataaquisition.Utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.telephony.TelephonyManager;
import android.util.Patterns;
import android.widget.Toast;

121

import com.sergiud.tarca.mynewdataaquisition.activities.ConnectionLevelsActivity;
import com.sergiud.tarca.mynewdataaquisition.ExternalIntereface.Custom HttpClient;
import com.sergiud.tarca.mynewdataaquisition.GatheringData.RetriveDeviceInformation;
import com.sergiud.tarca.mynewdataaquisition.GlobalStaff;
import com.sergiud.tarca.mynewdataaquisition.Models.InternModels.DeviceProperties;

import java.sql.T imestamp;
import java.util.Calendar;

import static com.sergiud.tarca.mynewdataaquisition.GlobalStaff. serverIpAddress ;
import static com.sergiud.tarca.mynewdataaquisition.Utils.Constants. HOSNAME_ADDRESS ;

/**
* Created by Sergiu on 04 -Jun-18.
*/

public class Utils extends ConnectionLevelsActivity {
/**
* Create an calendar instance in order to generate current timestamp
* @return TimeStamp as long value
*/
public static long getCurrentTimeStampLong() {
return new Timestamp (Calendar.getInstance().getTimeInMillis()).getTime();
}

/**
* This method is used for saving user preferences
* @param key used as key for the preferences
* @param value used for value of the preferences
*/
public static vo id setPreferences(String key, Object value) {
SharedPreferences.Editor editor = GlobalStaff.pref.edit();
if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
}
if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
}
if (value instanceof Long) {
editor.putLong(key, (Long) value);
}
if (value instanceof String) {
editor.putString(key, (String) value);
}

editor.commit();
}

/** Checks the new IP address to matches the pattern of an IP address or host name.
* If correct, stores the new IP as server IP,
* IF incorrect, shows a toast to inform that IP is not valid and was not saved
*
* @param newIpAddress
*/
public static void saveNewIpAddress(String newIpAddress) {
if (!newIpAddress.isEmpty()) {
if (Patterns.IP_ADDRESS.matcher(newIpAddress).matches() ||
Patterns.WEB_URL.matcher(newIpAddress).match es()) {
Utils.setPreferences(HOSNAME_ADDRESS,newIpAddress);
serverIpAddress = newIpAddress;
toast("New Server Ip address is: \n" + serverIpAddress);
} else toast("Not Saved! The URL is not valid, please use a valid url." );
}
}

/**
* Interrogates on preferences for device properties flag,
* if false, tries to send the device information.
*/

122
public static void checkDeviceInformation() {
if (!GlobalStaff.pre f.getBoolean(Constants.DEVICE_PROPERTIES_SEND, false)) {
sendDeviceInforamtions();
}
}

/**
* Shows a toast with received string information
* @param s used as string value in toast
*/
public static void toast(String s) {
Toast.makeText(GlobalStaff.appContext, s, Toast.LENGTH_LONG).show();
}

/**
* Retrieves the device information along with SIM details and send object over
HTTP to th server
*/
private static void sendDeviceInfora mtions() {
TelephonyManager tf = (TelephonyManager)
GlobalStaff.appContext.getSystemService(Context.TELEPHONY_SERVICE);
RetriveDeviceInformation deviceInfo = new RetriveDeviceInformation(tf);
DeviceProperties deviceProperties = devi ceInfo.getDeviceProperties();
String deviceName = deviceProperties.getDeviceManufacturer() + " " +
deviceProperties.getDeviceModel();
setPreferences(Constants.DEVICE_INFO_PROPERTIES, deviceName);

ConnectionLevelsActivity.deviceInfoT V.setText(GlobalStaff.pref.getString(Constants.DEVI
CE_INFO_PROPERTIES, "Unknown" ));

CustomHttpClient httpClient = new CustomHttpClient();
httpClient.postDeviceProperties(deviceProperties);
}

}
package com.sergiud.tarca.mynewdataaquisi tion.Utils;

import com.google.android.gms.maps.model.LatLng;

/**
* This class contains static values for miscellaneous parameters
*/

public abstract class Constants {
public static final String PREFERENCES_NAME = "appSpecificData" ;
public static final String DEVICE_PROPERTIES_SEND = "deviceInfo" ;
public static final String ATOMIC_COUNTER = "id_counter" ;
public static final String BROADCAST_FILTER = "location_update" ;
public static final String EXTRA_INTENT_SERVICE_TO_FRON T = "intentObject" ;
public static final String DEVICE_INFO_PROPERTIES = "device_properties" ;
public static final String HOSNAME_ADDRESS = "ipAddress" ;

public static final String DATE_SEND_PERIOD = "send_period" ;
public static int uiRefres hInterval = 1;
public static double defaultLatitude = 46.7549;
public static double defaultLongitude = 23.568;
public static LatLng defaulLatLnt = new LatLng(defaultLatitude , defaultLongitude );
public static String DEFAULT_HOSNAME_ADDRESS = "mypersonalhost.go.ro" ;
}

123

Client JavaDoc

Database development
CREATE TABLE testDB.DEVICE_PROPERTIES (
deviceId varchar(100) NOT NULL ,
imei varchar(100) NULL,
mcc varchar(100) NULL,
mnc varchar(100) NULL,
simOperator varchar(100) NULL,
networkOperatorName varchar(100) NULL,
networkCountryISO varchar(100) NULL,
subscriberId varchar(100) NULL,
deviceModel varchar(100) NULL,
deviceManufacturer varchar(100) NULL,
device varchar(100) NULL,
networkTypeName varchar(100) NULL,
networkClass varchar(100) NULL,
networkType varchar(100) NULL,
PRIMARY KEY (`subscriberId` )
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COMMENT= 'stores the device and SIM properties’

CREATE TABLE `SIGNAL_LEVEL` (
`index_id` int(11) NOT NULL AUTO_INCREMENT,
`latitude` double NOT NULL DEFAULT '0',
`longitude` double NOT NULL DEFAULT '0',
`signalDbm` int(11) NULL DEFAULT NULL ,
`signalStrengthLevel` int(11) NULL DEFAULT NULL ,
`asuLevel` int(11) NULL DEFAULT NULL ,
`timingAdvance` int(11) NULL DEFAULT NULL ,
`Rssnr` int(11) NULL DEFAULT '0',
`Rsrq` int(11) NULL DEFAULT '0',
`Rsrp` int(11) NULL DEFAULT '0',

124
`networkOperator` varchar(100) NULL,
`networkTypeClass` varchar(100) NULL,
`networkTypeName` varchar(100) NULL,
`networkOperatorName` varchar(100) NULL,
`uploadRate` double NULL DEFAULT NULL ,
`downloadRate` double NULL DEFAULT NULL ,
`simOperator` varchar(100) NULL,
`subscriberId` varchar(100) NULL,
`deviceId` varchar(100) NULL,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY (`subscriberId` )
) ENGINE=InnoDB
AUTO_INCREMENT= 1274
DEFAULT CHARSET=utf8mb4
COMMENT= 'stores signal level on area with LatLng'

125

10 CV-ul autorului
PERSONAL INFORMATION Țarcă Sergiu Daniel

Republicii St, no. 84, Iacobeni 727315, Suceva,Romania
+40 747346305
tarcasergiu@gmail.com

Sex M | Date of birth 02/08/1993 | Nationality Romanian

WORK EXPERIENCE

POSITION
Quality Assurance Engineer
15 July 2015 – until now Quality Assurance Engineer
Betfair Romania Development SRL, Blvd 21 Decembrie 1989 nr. 77 4th floor,
Cluj-Napoca, Romania
▪ Manual and Automation T esting
▪ Selenium WebDriver
▪ T estNG
▪ Postman/SoapUi/ HP Peformance Center
▪ Maven
▪ Create T est Scenarios
▪ Linux
▪ Windows

Business or sector IT/Technology

November 2012 – until now Coordinator/Volunteer
Organizația Studenților din Universitatea T ehnică(OSUT), Ceahlăul Street, no.72, Cluj -Napoca
▪ Implementing projects and improving them
▪ Brainstorming for new projects
▪ T eam leader
Business or sector Volunteer

4 July – 6 July 2014 Volunteer/Bar Department
Asociația Fapte, Unirii St. no.23, ap.54,Cluj -Napoca,Cluj
▪ Products supply
▪ T eam coordination
▪ Serving drinks
Business or sector Volunteer

126

EDUCATION AND TRAINING

PERSONAL SKILLS

28 June – 30 June 2014 Volunteer/Bar Department
S.C. ADWAY DIRECTION SRL Octavian Goga St, no.38. Cluj -Napoca, Cluj
▪ Product supply
▪ Serving drinks
▪ T eam coordinator
Business or sector Volunteer

19 June – 22 June 2014 Volunteer/Bar Department
SC BOILER EVENTS SRL, Mihai Viteazul Boulevard , no. 33B, Zalău, Sălaj
▪ Products supply
▪ Serving drinks
Business or sector Volunteer

November 2012 – July 2018 –
Technical University of Cluj-Napoca,Telecommunications and
Information Technology, Technologies and Telecommunications
Systems, English Section

▪ Programming language
▪ T echnologies in electronic

September 2008 – July 2012
Atestat de Competențe Profesionale in Infromatică
Colegiul Național “Dragoș Vodă ” Câmpulung Moldovenesc

▪ Programming language
Mother tongue(s) Romanian

Other language(s) UNDERSTANDING SPEAKING WRITING
Listening Reading Spoken interaction Spoken production
English B2 C1 B2 B2 C1
Communication skills ▪ Good communication skills acquired through voluntary activity in several events
Organisational / managerial skills ▪ Leadership acquired through coordination of the project and trainings attendance
▪ T eamwork , prompt, able to adapt, gained from experience as a volunteer
▪ Well organized time

127

Job-related skills ▪ Well evaluations of the task
▪ Calm, dedicated , patient
Computer skills ▪ Good knowledge of the most used tools in Microsoft Office
▪ Good command of creative tools : Adobe Photoshop Camtasia Studio
▪ Beginner instruments in Adobe Premier and Adobe After Effects
▪ Advanced knowledge in hardware
Other skills ▪ Impatient to learn new things
▪ Social
▪ Ambitious
▪ Curious
▪ Interested
▪ Persistent
Driving licence ▪ A, B

Similar Posts