An android application developed under ACMS (Amazon Campus Mentorship Series) project.
Build a web tool which shows a building boundary and all the people moving inside that building. It will capture the movement data using an app which will be installed on the mobile devices of all those people, and that app will keep sending location information to a server periodically. The location accuracy should not be more than 5 meters.
- Java programming language
- Android SDK
- Android Studio IDE
Android Studio, Git, iExplore-server and iExplore-webapp
To import this project into Android Studio, proceed as follows:
- Click File > New > Project from Version Control > Git.
- Enter URL: https://github.com/priyankamadhwal/iExplore-app.git
- Click Clone.
- Configure Google API Console project.
- Download and add credentials.json to app folder.
- Get the Web application type client id from Credentials Page in the API console project and add it to SERVER_CLIENT_ID in /app/src/main/java/com/acms/iexplore/data/Constants.java.
- Edit IP_ADDRESS, PORT_SERVER and PORT_WEB in /app/src/main/java/com/acms/iexplore/data/Constants.java.
- Build the app.
- Install iExplore-server.
- Run server
node app.js - Install iExplore-webapp.
- Run webapp:
ng serve --host <ip address> - Build and run the app.
Note:
- Make sure that the server, webapp and android app are connected to the same network.
- To run the app on emulator use ip address: 10.0.2.2
- If you are runnig the app on emulator, then run the webapp using
ng serveonly.
- Setting up Permissions
- Getting location updates when application is running in foreground
- Creating a notification channel for foreground service
- Getting location updates when application is in background or killed (Service)
- Updating UI from Service using a Broadcast Reciever
- Connecting to server using an HTTP Client
- Adding Geofence for a single building
- Adding Geofences for multiple buildings (stored in DB)
- Authentication
- UI Design
- Unit testing
- Integration testing
(Click to expand)
Runtime permissions
Android M (API 23) introduced runtime permissions, letting user to allow or deny any permission at runtime.
To use location services, this application uses ACCESS_FINE_LOCATION permission and ACCESS_BACKGROUND_LOCATION permission (Android Q and above).
Our solution:
For granting each and every permission, long and tedious code is required. So, to overcome this, we are using Dexter library which simplifies the process of requesting runtime permissions.
Getting location updates
Mainly, there are two different ways to do it:
1. Android Framework Location API
It has 3 location providers:
- NETWORK_PROVIDER
- Calculates location using nearest cell towers and wifi access points.
- Uses ACCESS_COARSE_LOCATION permission which allows the app to get only an approximated location.
- It is fast and battery consumption is low.
- Accuracy is not very good.
- Calculates location using nearest cell towers and wifi access points.
- GPS_PROVIDER
- Gets location values using satellites.
- Uses ACCESS_FINE_LOCATION permission to provide a more precise/accurate location.
- Gives high accuracy of current location.
- Needs continuous power supply.
- Might be slow sometimes.
- Gets location values using satellites.
- PASSIVE_PROVIDER
- Does not request location updates itself.
- Passively receives location information from other applications that are using location services.
- Not reliable because if no other app on the phone is getting location updates, our app won't get them either.
- Accuracy is also very low.
- Does not request location updates itself.
As GPS is most accurate, so using that would be an obvious choice. But inside buildings, sometimes GPS is not available and in that case we might want to switch to Network provider until GPS becomes available again. But it causes huge battery drain to switch to exact location provider and may take a little longer to give the result.
2. FusedLocationProviderClient by Google Play Services
This is built on top of Android’s API and automatically chooses what underlying provider to use on the basis of accuracy, battery usage, speed etc.
According to the docs:
The Google Play services location APIs are preferred over the Android framework location APIs (android.location) as a way of adding location awareness to your app. If you are currently using the Android framework location APIs, you are strongly encouraged to switch to the Google Play services location APIs as soon as possible.
…
The Google Location Services API, part of Google Play Services, provides a more powerful, high-level framework that automatically handles location providers, user movement, and location accuracy. It also handles location update scheduling based on power consumption parameters you provide. In most cases, you'll get better battery performance, as well as more appropriate accuracy, by using the Location Services API.
It's drawback is that app will only be able to run on devices with Google Play services installed in it.
Our solution:
We will be using the FusedLocationProviderClient along with other Google Play Services APIs: Geofencing and Google sign-in.
Services in Android
Background services:
Whenever an application runs in the background using services, it consumes memory and battery which are very limited resources. So, Android O onwards, the application is allowed to create and run background services only for a few minutes after which they are killed by the system.
Some periodic task can be created using a scheduler that will start service again after some given interval, service will do its work and then stop itself again. By this, the application will not be considered battery draining. But there are some limitations in the number of times an app can request location update in background. Also the doze mode and app standby delays the execution by some amount of time if the phone is idle.
Foreground services:
A foreground service will keep the user aware that application is performing some background tasks by displaying a persistent notification and the system will consider it to be something the user is actively aware of and thus not a candidate for killing when low on memory or power.
But as this notification couldn't be dismissed, users may find this behavior annoying.
Our solution:
We will be using a Foreground Service for Android versions O and above as it makes it possible to get uninterrupted continuous location updates which is very essential for this app.
Android Broadcasts
Global vs. Local Broadcasts
Using a global broadcast, any other application can also send and receive broadcast messages to and from our application. This can be a serious security threat for the application. Also global broadcast is sent system-wide, so it is not performance efficient.
Android provides local broadcasts with the LocalBroadcastManager class which provides following benifits:
- Broadcast data won’t leave your app, so don’t need to worry about leaking private data.
- It is not possible for other applications to send these broadcasts to your app, so you don’t need to worry about having security holes they can exploit.
- It is more efficient than sending a global broadcast through the system.
- No overhead of system-wide broadcast.
Our solution:
We are using a BroadcastReceiver to receive the updated location in MainActivity that is going to be broadcast locally from the Service and then update the UI.
Connecting the app with Server
There are a lot of networking libraries that can be used for this purpose- OkHttp, AndroidAsync, Retrofit, Volley, Robospice etc.
Our solution:
We are using Retrofit in this project because of following reasons:
- Easy to understand and use
- Treats the Api calls as simple java method calls
- Handles the Json/Xml parsing itself
- We do not have too many custom requirements in terms of caching and request prioritization
- Good community support
Geofencing
Geofencing combines awareness of the user's current location with awareness of the user's proximity to locations that may be of interest. To mark a location of interest, you specify its latitude and longitude. To adjust the proximity for the location, you add a radius. The latitude, longitude, and radius define a geofence, creating a circular area, or fence, around the location of interest.
Points to consider:
- You can have multiple active geofences, with a limit of 100 per app, per device user.
- For best results, the minimium radius of the geofence should be set between 100 - 150 meters.
- When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor location is available, the accuracy range can be as small as 5 meters. Unless you know indoor location is available inside the geofence, assume that Wi-Fi location accuracy is about 50 meters. When Wi-Fi location isn't available (for example, rural areas) the location accuracy degrades further.
- If there is no reliable data connection, alerts might not be generated. This is because the geofence service depends on the network location provider which in turn requires a data connection.
- The geofence service doesn't continuously query for location, so expect some latency when receiving alerts. Usually the latency is less than 2 minutes, even less when the device has been moving. If Background Location Limits are in effect, the latency is about 2-3 minutes on average. If the device has been stationary for a significant period of time, the latency may increase (up to 6 minutes).
Our solution:
In this app, we are using geofences to determine when a user enters or exits a building. The app will start sending the location updates to server as soon as the ENTER event is triggered and stop the moment the EXIT event is triggered. Also, geofences are being added to monitor multiple buildings so that we can know in which building the user currently is.
Authentication
We should verify a user's identity before giving him access to the app.
Our solution:
Currently, we are just using the Google sign-in option to let the user quickly and easily register/sign-in to our app with their existing Google account.
- https://github.com/Karumi/Dexter
- https://www.youtube.com/watch?v=ycja50TzjoU
- https://stackoverflow.com/a/42964535
- https://medium.com/@maheshikapiumi/android-location-services-7894cea13878
- https://developer.android.com/training/location/request-updates
- https://medium.com/@kevalpatel2106/how-to-handle-background-services-in-android-o-f96783e65268
- https://android.jlelse.eu/local-broadcast-less-overhead-and-secure-in-android-cfa343bb05be
- https://androidwave.com/foreground-service-android-example/
- https://www.youtube.com/watch?v=rNYaEFl6Fms
- https://www.youtube.com/watch?v=nmAtMqljH9M
- https://developer.android.com/training/location/geofencing
- https://developers.google.com/identity/sign-in/android/start-integrating










