Skip to content

Commit

Permalink
Check for google play services, fall back to non-fused (qt), disable …
Browse files Browse the repository at this point in the history
…android non-fused implementation for now
  • Loading branch information
wonder-sk committed Jun 4, 2024
1 parent 63600a9 commit f5b56f7
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 7 deletions.
16 changes: 14 additions & 2 deletions app/android/src/uk/co/lutraconsulting/MMAndroidPosition.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ public void onPositionChanged(@NonNull Location location, GnssStatus gnssStatus)

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

// find out whether fused provider could be actually used
static public boolean isFusedLocationProviderAvailable(Context context) {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
return googleApiAvailability.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
}

// get more details why FLP is not available (e.g. play services missing, disabled, updating...)
static public String fusedLocationProviderErrorString(Context context) {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
return googleApiAvailability.getErrorString(googleApiAvailability.isGooglePlayServicesAvailable(context));
}

// called from C++ code
static public MMAndroidPosition createWithJniCallback(Context context, boolean useFused, int instanceId) {
Log.i("CPP", "[java] createWithJniCallback");

Expand Down Expand Up @@ -71,8 +84,7 @@ public MMAndroidPosition(Context context, MMAndroidPosition.Callback clientCallb
mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

if (mUseFused) {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
mFusedAvailable = googleApiAvailability.isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
mFusedAvailable = isFusedLocationProviderAvailable(context);
Log.i("CPP", "[java] fused available: " + mFusedAvailable);
if (mFusedAvailable) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
Expand Down
9 changes: 9 additions & 0 deletions app/position/positionkit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,15 @@ AbstractPositionProvider *PositionKit::constructProvider( const QString &type, c
else if ( id == QStringLiteral( "android_fused" ) || id == QStringLiteral( "android_gps" ) )
{
bool fused = ( id == QStringLiteral( "android_fused" ) );
if ( fused && !AndroidPositionProvider::isFusedAvailable() )
{
// TODO: inform user + use AndroidPositionProvider::fusedErrorString() output?

// fallback to the default - at this point the Qt Positioning implementation
AbstractPositionProvider *provider = new InternalPositionProvider();
QQmlEngine::setObjectOwnership( provider, QQmlEngine::CppOwnership );
return provider;
}
__android_log_print( ANDROID_LOG_INFO, "CPP", "MAKE PROVIDER %d", fused );
AbstractPositionProvider *provider = new AndroidPositionProvider( fused );
QQmlEngine::setObjectOwnership( provider, QQmlEngine::CppOwnership );
Expand Down
23 changes: 21 additions & 2 deletions app/position/providers/androidpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void jniOnPositionUpdated( JNIEnv *env, jclass clazz, jint instanceId, jobject l
AndroidPositionProvider::AndroidPositionProvider( bool fused, QObject *parent )
: AbstractPositionProvider( fused ? QStringLiteral( "android_fused" ) : QStringLiteral( "android_gps" ),
QStringLiteral( "internal" ),
fused ? tr( "Android (fused)" ) : tr( "Android (gps)" ), parent )
fused ? tr( "Internal (fused)" ) : tr( "Internal (gps)" ), parent )
, mFused( fused )
, mInstanceId( ++sLastInstanceId )
{
Expand Down Expand Up @@ -215,6 +215,25 @@ AndroidPositionProvider::~AndroidPositionProvider()

}

bool AndroidPositionProvider::isFusedAvailable()
{
jobject context = QNativeInterface::QAndroidApplication::context();

return QJniObject::callStaticMethod<jboolean>( "uk/co/lutraconsulting/MMAndroidPosition", "isFusedLocationProviderAvailable",
"(Landroid/content/Context;)Z", context );
}

QString AndroidPositionProvider::fusedErrorString()
{
jobject context = QNativeInterface::QAndroidApplication::context();

QJniObject str = QJniObject::callStaticObjectMethod( "uk/co/lutraconsulting/MMAndroidPosition", "fusedLocationProviderErrorString",
"(Landroid/content/Context;)Ljava/lang/String;", context );

return str.toString();
}


void AndroidPositionProvider::startUpdates()
{
__android_log_print( ANDROID_LOG_INFO, "CPP", "[c++] start updates" );
Expand All @@ -237,7 +256,7 @@ void AndroidPositionProvider::startUpdates()
return;
}

setState( tr( "Waiting for fix..." ), State::Connected );
setState( tr( "Connected" ), State::Connected );
}

void AndroidPositionProvider::stopUpdates()
Expand Down
6 changes: 6 additions & 0 deletions app/position/providers/androidpositionprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ class AndroidPositionProvider : public AbstractPositionProvider
virtual void stopUpdates() override;
virtual void closeProvider() override;

//! Checks whether the fused location provider can be used (i.e. Google Play services are present)
static bool isFusedAvailable();
//! If fused provider is not available, returns error string that could be presented to users.
//! It is not very human friendly, but at least something (e.g. "SERVICE_DISABLED")
static QString fusedErrorString();

public slots:

private:
Expand Down
18 changes: 15 additions & 3 deletions app/position/providers/positionprovidersmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include "inpututils.h"
#include "coreutils.h"

#ifdef ANDROID
#include "position/providers/androidpositionprovider.h"
#endif

PositionProvidersModel::PositionProvidersModel( QObject *parent ) : QAbstractListModel( parent )
{
if ( !InputUtils::isMobilePlatform() )
Expand All @@ -33,19 +37,27 @@ PositionProvidersModel::PositionProvidersModel( QObject *parent ) : QAbstractLis

#ifdef ANDROID
PositionProvider internalFused;
internalFused.name = tr( "Android (fused)" );
internalFused.description = tr( "Using GPS, Wifi and sensors" );
internalFused.name = tr( "Internal (fused)" );
if ( AndroidPositionProvider::isFusedAvailable() )
internalFused.description = tr( "Using GPS, Wifi and sensors" );
else
internalFused.description = tr( "Not available (%1)" ).arg( AndroidPositionProvider::fusedErrorString() );
internalFused.providerType = "internal";
internalFused.providerId = "android_fused";
mProviders.push_front( internalFused );

// This one should have pretty much the same behavior as the provider
// implemented using Qt Positioning, so let's skip it. When we ditch
// Qt's implementation on Android, this can be used as a fallback.
#if 0
PositionProvider internalGps;
internalGps.name = tr( "Android (gps)" );
internalGps.name = tr( "Internal (gps)" );
internalGps.description = tr( "Using GPS only" );
internalGps.providerType = "internal";
internalGps.providerId = "android_gps";
mProviders.push_front( internalGps );
#endif
#endif
}

PositionProvidersModel::~PositionProvidersModel() = default;
Expand Down

0 comments on commit f5b56f7

Please sign in to comment.