Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Felgo Qt Licensing

Felgo is a cross-platform development SDK based on the Qt framework. Qt is available under different licensing options. Felgo can be used with the GNU LGPL version 3 (LGPL-3.0) and the Qt commercial license offering.

The Felgo license is independent of the Qt license (proprietary license) and does not impact which Qt license model you choose.

Note: The provided information in that section is not legal advice. Under no circumstances FELGO GmbH or its subsidiaries can be made liable for license violations that arise from the usage of open-source software.

Open-Source Qt Licensing Option

The official Felgo Installer ships Qt runtime libraries licensed with the LGPL-3.0 option. Software created with the Felgo SDK links Qt runtime libraries under the LGPL-3.0 as “Combined Work” (Clause 4).

Using this Qt version allows you to create and distribute your Felgo applications under terms of your choice as long as you comply with the LGPL-3.0 licensing terms.

The Felgo-included Qt libraries are built from the Qt source code, which can be found here. To build Qt from source, please refer to Building Qt Sources. The LGPL-3.0 license can be found here: GNU Lesser General Public License (LGPL).

A copy of the license and the Qt source code download link is additionally installed with the Felgo SDK's license agreement.

Note: Felgo for WebAssembly is not available with the open-source licensing option right now and only available for Qt commercial license holders.

Commercial Qt Licensing Option

You can use Felgo with the Qt commercial licensing option if you are a Qt commercial license owner. We provide information on installing Felgo within an existing Qt commercial installation via our contact form.

Qt Sources and Patches

Qt 6.4.1

Source:

The Felgo-shipped Qt libraries apply the following patches:

  • Android QtDeclarative ("media content URIs")
     diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp
     index 4f18389864..e5e9730caf 100644
     --- a/src/qml/qml/qqmlfile.cpp
     +++ b/src/qml/qml/qqmlfile.cpp
     @@ -476,7 +476,9 @@ bool QQmlFile::isSynchronous(const QString &url)
      static bool hasLocalContentAuthority(const QUrl &url)
      {
          const QString authority = url.authority();
     -    return authority.isEmpty()
     +    // workaround for https://bugreports.qt.io/browse/QTBUG-111207
     +    // return true for content:// URIs, where get "media" as authority
     +    return authority.startsWith("media") || authority.isEmpty()
                  || authority == QLatin1String(authority_externalstorage)
                  || authority == QLatin1String(authority_downloads_documents)
                  || authority == QLatin1String(authority_media_documents);
     @@ -556,7 +558,9 @@ static bool hasLocalContentAuthority(const QString &url, qsizetype schemeLength)
              return true; // no authority is a local authority.
    
          const QString authorityAndPath = url.sliced(offset);
     -    return authorityAndPath.startsWith(QLatin1String(authority_externalstorage))
     +    // workaround for https://bugreports.qt.io/browse/QTBUG-111207
     +    // return true for content:// URIs, where get "media" as authority
     +    return authorityAndPath.startsWith("media") || authorityAndPath.startsWith(QLatin1String(authority_externalstorage))
               || authorityAndPath.startsWith(QLatin1String(authority_downloads_documents))
               || authorityAndPath.startsWith(QLatin1String(authority_media_documents));
      }
  • Android QtConnectivity ("Bluetooth Permission Check")
      .../qbluetoothdevicediscoveryagent_android.cpp     | 116 +++++++++++++--------
      1 file changed, 72 insertions(+), 44 deletions(-)
    
     diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
     index b52313e0..f096e875 100644
     --- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
     +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
     @@ -133,57 +133,85 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
          if (setErrorIfPowerOff())
              return;
    
     -    auto precisePermission = QStringLiteral("android.permission.ACCESS_FINE_LOCATION");
     -    auto preciseCheckRes = QtAndroidPrivate::checkPermission(precisePermission).result();
     -    if (preciseCheckRes != QtAndroidPrivate::Authorized) {
     -        auto preciseRequestRes = QtAndroidPrivate::requestPermission(precisePermission).result();
     -        if (preciseRequestRes != QtAndroidPrivate::Authorized) {
     -            qCWarning(QT_BT_ANDROID) <<
     -                "Search not possible due to missing permission (ACCESS_FINE_LOCATION)";
     -            errorString = QBluetoothDeviceDiscoveryAgent::tr(
     -                "Missing Location permission. Search is not possible.");
     -            lastError = QBluetoothDeviceDiscoveryAgent::MissingPermissionsError;
     -            emit q->errorOccurred(lastError);
     -            return;
     -        }
     -    }
     -    qCDebug(QT_BT_ANDROID) << "ACCESS_FINE_LOCATION permission available";
     +    // get all permissions requested through the manifest
     +    QSet<QString> manifestPermissions;
    
     -    // Double check Location service is turned on
     -    bool locationTurnedOn = true; // backwards compatible behavior to previous Qt versions
     -    const  QJniObject locString = QJniObject::getStaticObjectField(
     -                "android/content/Context", "LOCATION_SERVICE", "Ljava/lang/String;");
     +    // Java:
     +    // PackageInfo packageInfo = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_PERMISSIONS);
     +    // String[] requestedPermissions = packageInfo.requestedPermissions;
    
     -    const QJniObject locService =
     -            QJniObject(QNativeInterface::QAndroidApplication::context()).callMethod<jobject>(
     -                "getSystemService",
     -                locString.object<jstring>());
     +    QJniEnvironment env;
     +    auto activity = QJniObject(QtAndroidPrivate::activity());
     +    auto packageName = activity.callObjectMethod("getPackageName", "()Ljava/lang/String;");
     +    auto pm = activity.callObjectMethod("getPackageManager", "()Landroid/content/pm/PackageManager;");
     +    jint perms = QJniObject::getStaticField<jint>("android/content/pm/PackageManager", "GET_PERMISSIONS");
     +    auto pi = pm.callObjectMethod("getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;", packageName.object(), perms);
     +    auto requestedPermissions = pi.getObjectField("requestedPermissions", "[Ljava/lang/String;");
    
     -    if (locService.isValid()) {
     -        if (QNativeInterface::QAndroidApplication::sdkVersion() >= 28) {
     -            locationTurnedOn = bool(locService.callMethod<jboolean>("isLocationEnabled"));
     -        } else {
     -            // check whether there is any enabled provider
     -            QJniObject listOfEnabledProviders =
     -                    locService.callMethod<QtJniTypes::List>("getProviders", true);
     -
     -            if (listOfEnabledProviders.isValid()) {
     -                int size = listOfEnabledProviders.callMethod<jint>("size");
     -                locationTurnedOn = size > 0;
     -                qCDebug(QT_BT_ANDROID) << size << "enabled location providers detected.";
     -            }
     -        }
     +    for(int i = 0; i < env->GetArrayLength(requestedPermissions.object<jobjectArray>()); i++) {
     +        QJniObject ele(env->GetObjectArrayElement(requestedPermissions.object<jobjectArray>(), i));
     +
     +        manifestPermissions << ele.toString();
          }
    
     -    if (!locationTurnedOn) {
     -        qCWarning(QT_BT_ANDROID) << "Search not possible due to turned off Location service";
     -        lastError = QBluetoothDeviceDiscoveryAgent::LocationServiceTurnedOffError;
     -        errorString = QBluetoothDeviceDiscoveryAgent::tr("Location service turned off. Search is not possible.");
     -        emit q->errorOccurred(lastError);
     -        return;
     +    auto precisePermission = QStringLiteral("android.permission.ACCESS_FINE_LOCATION");
     +    if (!manifestPermissions.contains(precisePermission)) {
     +        // location permission not declared in manifest, skip check for permission and services enabled
     +        // (bluetooth works without location permission, if android:usesPermissionFlags="neverForLocation" is set on the bluetooth permission)
     +        qCDebug(QT_BT_ANDROID) << "No location permission declared through manifest, not requesting.";
          }
     +    else {
     +        auto preciseCheckRes = QtAndroidPrivate::checkPermission(precisePermission).result();
     +        if (preciseCheckRes != QtAndroidPrivate::Authorized) {
     +            auto preciseRequestRes = QtAndroidPrivate::requestPermission(precisePermission).result();
     +            if (preciseRequestRes != QtAndroidPrivate::Authorized) {
     +                qCWarning(QT_BT_ANDROID) <<
     +                    "Search not possible due to missing permission (ACCESS_FINE_LOCATION)";
     +                errorString = QBluetoothDeviceDiscoveryAgent::tr(
     +                    "Missing Location permission. Search is not possible.");
     +                lastError = QBluetoothDeviceDiscoveryAgent::MissingPermissionsError;
     +                emit q->errorOccurred(lastError);
     +                return;
     +            }
     +        }
     +        qCDebug(QT_BT_ANDROID) << "ACCESS_FINE_LOCATION permission available";
     +
     +        // Double check Location service is turned on
     +        bool locationTurnedOn = true; // backwards compatible behavior to previous Qt versions
     +        const  QJniObject locString = QJniObject::getStaticObjectField(
     +                    "android/content/Context", "LOCATION_SERVICE", "Ljava/lang/String;");
     +
     +        const QJniObject locService =
     +                QJniObject(QNativeInterface::QAndroidApplication::context()).callMethod<jobject>(
     +                    "getSystemService",
     +                    locString.object<jstring>());
     +
     +        if (locService.isValid()) {
     +            if (QNativeInterface::QAndroidApplication::sdkVersion() >= 28) {
     +                locationTurnedOn = bool(locService.callMethod<jboolean>("isLocationEnabled"));
     +            } else {
     +                // check whether there is any enabled provider
     +                QJniObject listOfEnabledProviders =
     +                        locService.callMethod<QtJniTypes::List>("getProviders", true);
     +
     +                if (listOfEnabledProviders.isValid()) {
     +                    int size = listOfEnabledProviders.callMethod<jint>("size");
     +                    locationTurnedOn = size > 0;
     +                    qCDebug(QT_BT_ANDROID) << size << "enabled location providers detected.";
     +                }
     +            }
     +        }
    
     -    qCDebug(QT_BT_ANDROID) << "Location turned on";
     +        if (!locationTurnedOn) {
     +            qCWarning(QT_BT_ANDROID) << "Search not possible due to turned off Location service";
     +            lastError = QBluetoothDeviceDiscoveryAgent::LocationServiceTurnedOffError;
     +            errorString = QBluetoothDeviceDiscoveryAgent::tr("Location service turned off. Search is not possible.");
     +            emit q->errorOccurred(lastError);
     +            return;
     +        }
     +
     +        qCDebug(QT_BT_ANDROID) << "Location turned on";
     +    }
    
          if (!(ensureAndroidPermission(BluetoothPermission::Scan) &&
                ensureAndroidPermission(BluetoothPermission::Connect))) {
Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded