Location based services
Location based services are also known as LBS.
LBA apps follow the location and offer extra services such as locating facilities close at hand,
presenting suggestions for route planning etc.
In a local based service application, map is one of the key component, which present a visual
appearance of our location.
Getting the Maps API key
We have to apply for a free google maps API key before we integrate google maps into the android
application. When we apply for the key, we should also concur to google’s terms of use.
Displaying the Map
This has 2 main responsibilities;
Modify the AndroidManifest.xml file by adding the <uses-library> element and internet
permission.
Add the MapView element to your UI displaying the google maps.
Changing views
We can change the views of the map by setting it to satellite/street/map view.
Program
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_start_location_updates"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:onClick="startLocationButtonClick"
android:text="@string/start_updates" />
<Button
android:id="@+id/btn_stop_location_updates"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:enabled="false"
android:onClick="stopLocationButtonClick"
android:text="@string/stop_updates" />
<Button
android:id="@+id/btn_get_last_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:onClick="showLastKnownLocation"
android:text="@string/get_last_location" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:gravity="center_horizontal"
android:text="Location updates will be received only when app is
foreground" />
<TextView
android:id="@+id/location_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textColor="#333"
android:textSize="18sp" />
<TextView
android:id="@+id/updated_on"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:textSize="12sp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.location">
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>
package com.example.location;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
TextView txtLocationResult;
TextView txtUpdatedOn;
Button btnStartUpdates;
Button btnStopUpdates;
// location last updated time
private String mLastUpdateTime;
// location updates interval - 10sec
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
// fastest updates interval - 5 sec
// location updates will be received if another app is requesting the
locations
// than your app can handle
private static final int REQUEST_CHECK_SETTINGS = 100;
// bunch of location related apis
private Location mCurrentLocation;
// boolean flag to toggle the ui
private Boolean mRequestingLocationUpdates;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// initialize the necessary libraries
init();
// restore the values from saved instance state
restoreValuesFromBundle(savedInstanceState);
}
private void init() {
txtLocationResult = findViewById(R.id.location_result);
txtUpdatedOn = findViewById(R.id.updated_on);
btnStartUpdates = findViewById(R.id.btn_start_location_updates);
btnStopUpdates = findViewById(R.id.btn_stop_location_updates);
}
/**
* Restoring values from saved instance state
*/
private void restoreValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("is_requesting_updates")) {
mRequestingLocationUpdates =
savedInstanceState.getBoolean("is_requesting_updates");
}
if (savedInstanceState.containsKey("last_known_location")) {
mCurrentLocation =
savedInstanceState.getParcelable("last_known_location");
}
if (savedInstanceState.containsKey("last_updated_on")) {
mLastUpdateTime =
savedInstanceState.getString("last_updated_on");
}
}
updateLocationUI();
}
/**
* Update the UI displaying the location data
* and toggling the buttons
*/
private void updateLocationUI() {
if (mCurrentLocation != null) {
txtLocationResult.setText(
"Lat: " + mCurrentLocation.getLatitude() + ", " +
"Lng: " + mCurrentLocation.getLongitude()
);
// giving a blink animation on TextView
txtLocationResult.setAlpha(0);
txtLocationResult.animate().alpha(1).setDuration(300);
// location last updated time
txtUpdatedOn.setText("Last updated on: " + mLastUpdateTime);
}
toggleButtons();
}
private void toggleButtons() {
if (mRequestingLocationUpdates) {
btnStartUpdates.setEnabled(false);
btnStopUpdates.setEnabled(true);
}
else {
btnStartUpdates.setEnabled(true);
btnStopUpdates.setEnabled(false);
}
}
/**
* Starting location updates
* Check whether location settings are satisfied and then
* location updates will be requested
*/
public void startLocationButtonClick(View view) {
}
public void stopLocationButtonClick(View view) {
}
private void startLocationUpdates() {
}
public void stopLocationUpdates() {
// Removing location updates
}
public void showLastKnownLocation(View view) {
if (mCurrentLocation != null) {
Toast.makeText(getApplicationContext(), "Lat: " +
mCurrentLocation.getLatitude() + ", Lng: " +
mCurrentLocation.getLongitude(), Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(getApplicationContext(), "Last known location is
not available!",
Toast.LENGTH_SHORT).show();
}
}
@Override
public void onResume() {
super.onResume();
// Resuming location updates depending on button state and
// allowed permissions
if (mRequestingLocationUpdates && checkPermissions()) {
startLocationUpdates();
}
updateLocationUI();
}
private boolean checkPermissions() {
int permissionState = ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
return permissionState == PackageManager.PERMISSION_GRANTED;
}
@Override
protected void onPause() {
super.onPause();
if (mRequestingLocationUpdates) {
// pausing location updates
stopLocationUpdates();
}
}
}
Maps
Program
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
/>
package com.example.maps;
import androidx.fragment.app.FragmentActivity;
import android.os.Bundle;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends FragmentActivity implements
OnMapReadyCallback {
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Obtain the SupportMapFragment and get notified when the map is
ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment)
getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the
camera.
* In this case, we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device.
* This method will only be triggered once the user has installed
Google Play services and returned to the app.
*/
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng pt = new LatLng(21, 57);
mMap.addMarker(new
MarkerOptions().position(pt).title("scmsgroup.org"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(pt));
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.maps">
<!--
The ACCESS_COARSE/FINE_LOCATION permissions are not required to
use
Google Maps Android API v2, but you must specify either coarse or
fine
location permissions for the 'MyLocation' functionality.
-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
/>
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/title_activity_maps">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>