ConnectOut-sdp/sdp2023

View on GitHub
app/src/main/java/com/sdpteam/connectout/event/location/LocationHelper.java

Summary

Maintainability
A
0 mins
Test Coverage
C
77%
package com.sdpteam.connectout.event.location;

import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

import java.util.Objects;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import androidx.core.app.ActivityCompat;

public class LocationHelper {

    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
    private static LocationHelper INSTANCE;
    private final FusedLocationProviderClient fusedLocationClient;
    private Location lastLocation;

    LocationHelper(Context context) {
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
    }

    public LocationHelper() {
        fusedLocationClient = null; // for test
    }

    /**
     * Returns a singleton instance of the {@link LocationHelper} class.
     * If the instance has not been created yet, a new instance will be created.
     *
     * @param context The context used to create the instance
     * @return The singleton instance of the {@link LocationHelper} class
     */
    public static synchronized LocationHelper getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new LocationHelper(context.getApplicationContext());
        }
        return INSTANCE;
    }

    public static LatLng toLatLng(Location location) {
        Objects.requireNonNull(location);
        return new LatLng(location.getLatitude(), location.getLongitude());
    }

    /**
     * Gets the last known location of the device.
     * If the location is already available, the provided {@link LocationCallback} will be called immediately
     * with the last known location. Otherwise, the method will request location permission and retrieve the
     * last known location if permission is granted. Otherwise it will request permission to the user.
     *
     * @param activity The activity used to request location permission (needed for checking permission)
     * @param callback The callback to receive the location result
     */
    @SuppressLint("MissingPermission")
    public void getLastLocation(Activity activity, LocationCallback callback) {
        if (lastLocation != null) {
            callback.onResult(lastLocation);
            return;
        }

        if (hasPermission(activity)) {
            fusedLocationClient.getLastLocation()
                    .addOnSuccessListener(location -> {
                        lastLocation = location;
                        callback.onResult(location);
                    })
                    .addOnFailureListener(callback::onError);
        } else {
            ActivityCompat.requestPermissions(activity, new String[]{ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
        }
    }

    public boolean hasPermission(Activity activity) {
        return ActivityCompat.checkSelfPermission(activity, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED;
    }

    public interface LocationCallback {

        void onResult(Location location);

        default void onError(Exception e) {
            e.printStackTrace();
            onResult(null);
        }
    }
}