Skip to content

Commit

Permalink
Initial support for fused location provider
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed May 19, 2024
1 parent b828888 commit 63600a9
Show file tree
Hide file tree
Showing 9 changed files with 550 additions and 12 deletions.
14 changes: 10 additions & 4 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,18 @@ if (IOS)
endif ()

if (ANDROID)
set(MM_HDRS ${MM_HDRS} position/tracking/androidtrackingbackend.h
position/tracking/androidtrackingbroadcast.h
set(MM_HDRS
${MM_HDRS}
position/tracking/androidtrackingbackend.h
position/tracking/androidtrackingbroadcast.h
position/providers/androidpositionprovider.h
)

set(MM_SRCS ${MM_SRCS} position/tracking/androidtrackingbackend.cpp
position/tracking/androidtrackingbroadcast.cpp
set(MM_SRCS
${MM_SRCS}
position/tracking/androidtrackingbackend.cpp
position/tracking/androidtrackingbroadcast.cpp
position/providers/androidpositionprovider.cpp
)
endif ()

Expand Down
190 changes: 190 additions & 0 deletions app/android/src/uk/co/lutraconsulting/MMAndroidPosition.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package uk.co.lutraconsulting;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.GnssStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Looper;
import android.os.Handler;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.Priority;



public class MMAndroidPosition {

static public abstract class Callback {
public void onPositionChanged(@NonNull Location location, GnssStatus gnssStatus) {
}
}

private static native void jniOnPositionUpdated(int instanceId, Location location, GnssStatus gnssStatus);

static public MMAndroidPosition createWithJniCallback(Context context, boolean useFused, int instanceId) {
Log.i("CPP", "[java] createWithJniCallback");

MMAndroidPosition.Callback callback = new MMAndroidPosition.Callback() {
@Override
public void onPositionChanged(@NonNull Location location, GnssStatus gnssStatus) {
jniOnPositionUpdated(instanceId, location, gnssStatus);
}
};

return new MMAndroidPosition(context, callback, useFused);
}

private final Context mContext;
private final LocationManager mLocationManager;
private final boolean mUseFused;
private FusedLocationProviderClient mFusedLocationClient = null;
private final LocationCallback mLocationCallback;
private final LocationListener mLocationManagerCallback;
private final GnssStatus.Callback mGnssStatusCallback;
private final MMAndroidPosition.Callback mClientCallback;
private boolean mFusedAvailable = false;
private boolean mGpsProviderAvailable = false;
private boolean mIsStarted = false;
private String mErrorMessage;
private GnssStatus mLastGnssStatus;

public MMAndroidPosition(Context context, MMAndroidPosition.Callback clientCallback, boolean useFused) {
mContext = context;
mClientCallback = clientCallback;
mUseFused = useFused;

Log.i("CPP", "[java] constructor!");

mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

if (mUseFused) {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
mFusedAvailable = googleApiAvailability.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
Log.i("CPP", "[java] fused available: " + mFusedAvailable);
if (mFusedAvailable) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
}
} else {
mGpsProviderAvailable = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
Log.i("CPP", "[java] gps provider available: " + mGpsProviderAvailable);
}

mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(@NonNull LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
Log.i("CPP", "[java] FLP " + location.getLatitude() + " " + location.getLongitude());

// call the native function!
mClientCallback.onPositionChanged(location, mLastGnssStatus);
}
}
};

mGnssStatusCallback = new GnssStatus.Callback() {
@Override
public void onSatelliteStatusChanged(@NonNull GnssStatus status) {
//Log.v("LOC", "GNSS Status: " + status.getSatelliteCount() + " satellites.");

// store the satellite info
mLastGnssStatus = status;
}
};

mLocationManagerCallback = new LocationListener() {
@Override
public void onLocationChanged(@NonNull Location location) {
Log.i("CPP", "[java] GPS " + location.getLatitude() + " " + location.getLongitude());

mClientCallback.onPositionChanged(location, mLastGnssStatus);
}
};

Log.i("CPP", "[java] constructor end");

}

public String errorMessage() {
return mErrorMessage;
}

public boolean start() {
Log.i("CPP", "[java] start()");

if (mIsStarted)
return false;

Log.e("CPP", "[java] here 0");

if (mUseFused && !mFusedAvailable) {
mErrorMessage = "FUSED_NOT_AVAILABLE";
Log.e("CPP", "[java] FUSED_NOT_AVAILABLE");
return false;
}

if (!mUseFused && !mGpsProviderAvailable) {
mErrorMessage = "GPS_NOT_AVAILABLE";
Log.e("CPP", "[java] GPS_NOT_AVAILABLE");
return false;
}

if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
mErrorMessage = "MISSING_PERMISSIONS";
Log.e("CPP", "[java] MISSING_PERMISSIONS");
return false;
}

Log.e("CPP", "[java] here 1");

if (mUseFused) {
LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 1000).build();

mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, Looper.getMainLooper());
}
else {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 0.F, mLocationManagerCallback, Looper.getMainLooper());
Log.e("CPP", "[java] here 2");
}

mLocationManager.registerGnssStatusCallback(mGnssStatusCallback, new Handler(Looper.getMainLooper()));

Log.i("CPP", "[java] started!");

mIsStarted = true;
return true;
}

public boolean stop() {
Log.i("CPP", "[java] stop()");

if (!mIsStarted)
return false;

if (mUseFused) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
} else {
mLocationManager.removeUpdates(mLocationManagerCallback);
}

mLocationManager.unregisterGnssStatusCallback(mGnssStatusCallback);

Log.i("CPP", "[java] stopped!");

mIsStarted = false;
return true;
}
}
23 changes: 17 additions & 6 deletions app/position/positionkit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

#include "position/providers/internalpositionprovider.h"
#include "position/providers/simulatedpositionprovider.h"
#ifdef ANDROID
#include "position/providers/androidpositionprovider.h"
#include <android/log.h>
#endif

#include "appsettings.h"
#include "inpututils.h"
Expand Down Expand Up @@ -105,6 +109,16 @@ AbstractPositionProvider *PositionKit::constructProvider( const QString &type, c
QQmlEngine::setObjectOwnership( provider, QQmlEngine::CppOwnership );
return provider;
}
#ifdef ANDROID
else if ( id == QStringLiteral( "android_fused" ) || id == QStringLiteral( "android_gps" ) )
{
bool fused = ( id == QStringLiteral( "android_fused" ) );
__android_log_print( ANDROID_LOG_INFO, "CPP", "MAKE PROVIDER %d", fused );
AbstractPositionProvider *provider = new AndroidPositionProvider( fused );
QQmlEngine::setObjectOwnership( provider, QQmlEngine::CppOwnership );
return provider;
}
#endif
else // id == devicegps
{
AbstractPositionProvider *provider = new InternalPositionProvider();
Expand Down Expand Up @@ -132,13 +146,10 @@ AbstractPositionProvider *PositionKit::constructActiveProvider( AppSettings *app
return constructProvider( QStringLiteral( "internal" ), QStringLiteral( "simulated" ) );
}
}
else if ( providerId == QStringLiteral( "devicegps" ) )
{
return constructProvider( QStringLiteral( "internal" ), QStringLiteral( "devicegps" ) );
}
else if ( providerId == QStringLiteral( "simulated" ) )
else if ( providerId == QStringLiteral( "devicegps" ) || providerId == QStringLiteral( "simulated" ) ||
providerId == QStringLiteral( "android_fused" ) || providerId == QStringLiteral( "android_gps" ) )
{
return constructProvider( QStringLiteral( "internal" ), QStringLiteral( "simulated" ) );
return constructProvider( QStringLiteral( "internal" ), providerId );
}
else
{
Expand Down
Loading

0 comments on commit 63600a9

Please sign in to comment.