Creating a GPS Library Module
GPS (Global Positioning System) is a location service that captures the location of the user’s device. This feature is used widely in many service apps; mostly to show the location of customers or the sellers and to share a person’s location. In this article, we’ll look at how to create a GPS library module and publish it on JitPack.
Creating a GPS Module
-
Create an Android Project
Launch android studio, select ‘Start Project’, and select ‘Empty Activity’. Click ‘Finish’ and wait for the project to be prepared. This may take up to a few seconds to a few minutes depending on your computer.
-
Create a Library Module
The next step is to create a library module that will host the GPS logic. To create this module click File->New->New Module->Android Library.
Give the library the name ‘GPS Library’ and the package name ‘com.library.gps’.
-
Add Manifest Permission
Add the location permissions to the manifest. These are permissions that are used by the app to request access to the phone’s location feature.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Add the location dependency to get access to the location features library.
implementation 'com.google.android.gms:play-services-location:16.0.0
Adding a gps.xml for the Library Module
The GPS Library will launch as a dialog on the activity that it is called from. To achieve this, we add the gps.xml layout as a dialog layout with all the elements we want to view. Create the gps.xml file by clicking on res->New->Android Resource Directory. For the resource, option selects the layout option. Finally, give the file the name ‘gps’ and click on ‘Finish’. On this layout, we will add the ‘textviews’ to show the coordinates; the buttons to stop and start gps, and a button to close the dialog.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/common_google_signin_btn_text_dark_default">
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="144dp"
android:layout_marginEnd="8dp"
android:background="@android:color/holo_green_dark"
android:text="Start"
android:textColor="@color/common_google_signin_btn_text_dark_pressed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/txt_latitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:padding="4dp"
android:text="0.00000"
android:textAlignment="center"
android:textColor="@color/common_google_signin_btn_text_dark_focused"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/txt_longitude"
app:layout_constraintEnd_toStartOf="@+id/divider"
app:layout_constraintTop_toTopOf="@+id/txt_longitude" />
<TextView
android:id="@+id/txt_longitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="40dp"
android:padding="4dp"
android:text="0.00000"
android:textAlignment="center"
android:textColor="@color/common_google_signin_btn_text_dark_focused"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@+id/divider"
app:layout_constraintTop_toBottomOf="@+id/btn_start" />
<View
android:id="@+id/divider"
android:layout_width="1dp"
android:layout_height="50dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:text="Latitude"
android:textColor="@android:color/holo_red_dark"
app:layout_constraintEnd_toEndOf="@+id/txt_latitude"
app:layout_constraintTop_toBottomOf="@+id/txt_latitude" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="Longitude"
android:textColor="@android:color/holo_red_dark"
app:layout_constraintStart_toStartOf="@+id/txt_longitude"
app:layout_constraintTop_toBottomOf="@+id/txt_longitude" />
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:background="@android:color/holo_red_dark"
android:text="Stop"
android:textColor="@color/common_google_signin_btn_text_dark_pressed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<Button
android:id="@+id/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="8dp"
android:background="@android:color/holo_blue_dark"
android:text="Close"
android:textColor="@android:color/background_light"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_stop" />
</android.support.constraint.ConstraintLayout>
Add the Java Class to implement GPS
To implement our GPS in the module, we’ll need to create a Java class that will handle the code. To create the class right-click on the package folder, select a new java class. Name this class GPS.java. Once launched, it should look like this:
public class GPS {
}
To complete this implementation we follow these three steps:
- Define the class as a dialog
- Declare all the layout elements
- Add the location service code
Define the class as a dialog
package com.library.gps;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
public class GPS extends LinearLayout {
private AlertDialog alertDialog;
public GPS(Context context) {
super(context);
initialize(context);
}
public GPS(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
private void initialize(Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
final View view = LayoutInflater.from(context).inflate(R.layout.gps, null);
builder.setView(view);
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
builder.setCancelable(true);
alertDialog = builder.create();
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
}
public void dismiss(){
alertDialog.dismiss();
}
public void show(){
alertDialog.show();
}
}
Declare layout elements
startBtn= view.findViewById(R.id.btn_start);
stopBtn= view.findViewById(R.id.btn_stop);
closeBtn= view.findViewById(R.id.btn_close);
latitudeTxt= view.findViewById(R.id.txt_latitude);
longitudeTxt= view.findViewById(R.id.txt_longitude);
Add location service code
private synchronized void setUpGClient() {
googleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
getMyLocation();
}
@Override
public void onLocationChanged(Location location) {
mylocation = location;
if (mylocation != null) {
String Latitude = String.valueOf(mylocation.getLatitude());
String Longitude = String.valueOf(mylocation.getLongitude());
longitudeTxt.setText(Longitude);
latitudeTxt.setText(Latitude);
}
}
public void getMyLocation(){
if(googleApiClient!=null) {
if (googleApiClient.isConnected()) {
int permissionLocation = ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
locationRequest = new LocationRequest();
locationRequest.setInterval(20);
locationRequest.setFastestInterval(20);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi
.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
int permissionLocation = ContextCompat
.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi
.getLastLocation(googleApiClient);
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
}
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
getMyLocation();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
private void CheckGpsStatus() {
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
GpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
The complete GPS.java should look like this:
package com.library.gps;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.ColorDrawable;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.LocationListener;
public class GPS extends LinearLayout implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
TextView latitudeTxt, longitudeTxt;
Button startBtn, stopBtn, closeBtn;
private Location mylocation;
LocationRequest locationRequest;
GoogleApiClient googleApiClient;
LocationManager locationManager;
boolean GpsStatus = false;
private AlertDialog alertDialog;
public GPS(Context context) {
super(context);
initialize(context);
}
public GPS(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context);
}
private void initialize(Context context){
AlertDialog.Builder builder = new AlertDialog.Builder(context);
final View view = LayoutInflater.from(context).inflate(R.layout.gps, null);
builder.setView(view);
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
startBtn= view.findViewById(R.id.btn_start);
stopBtn= view.findViewById(R.id.btn_stop);
closeBtn= view.findViewById(R.id.btn_close);
latitudeTxt= view.findViewById(R.id.txt_latitude);
longitudeTxt= view.findViewById(R.id.txt_longitude);
builder.setCancelable(true);
alertDialog = builder.create();
alertDialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CheckGpsStatus();
if (GpsStatus) {
if(googleApiClient!=null) {
getMyLocation();
}else{
setUpGClient();
}
} else {
Toast.makeText(getContext(), "Please Enable GPS First", Toast.LENGTH_LONG).show();
}
}
});
closeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
alertDialog.dismiss();
}
});
}
public void dismiss(){
alertDialog.dismiss();
}
public void show(){
alertDialog.show();
}
private synchronized void setUpGClient() {
googleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
googleApiClient.connect();
getMyLocation();
}
@Override
public void onLocationChanged(Location location) {
mylocation = location;
if (mylocation != null) {
}
}
public void getMyLocation(){
if(googleApiClient!=null) {
if (googleApiClient.isConnected()) {
int permissionLocation = ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
locationRequest = new LocationRequest();
locationRequest.setInterval(20);
locationRequest.setFastestInterval(20);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi
.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
int permissionLocation = ContextCompat
.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION);
if (permissionLocation == PackageManager.PERMISSION_GRANTED) {
mylocation = LocationServices.FusedLocationApi
.getLastLocation(googleApiClient);
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
}
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
getMyLocation();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
private void CheckGpsStatus() {
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
GpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
}
In Part B of the article, we will test the library we just created in an app module and connect the project to Github.