QJniObject, Android Activity, Extras and more

The first error I ran into was about an unknown module androidextras:

There’s some documentation about Changes to Extras in Qt 6: https://doc.qt.io/qt-6/extras-changes-qt6.html

Please remove QT += androidextras from .pro.

QJniObject, AndroidActivity

There are many places where I’m using QAndroidJniObject, per ex. to set the Screen Orientation or checkMimeType or Manage Storage Permission (see Scoped Storage). Also in many cases I’m using QtAndroid::androidActivity.

  • QAndroidJniObject
    • -> QJniObject
  • QtAndroid::androidActivity
    • -> QNativeInterface::QAndroidApplication::context()
  • QtAndroid::startActivity
    • -> QtAndroidPrivate::startActivity

From example Screen Orientation:

QJniObject activity = QNativeInterface::QAndroidApplication::context();

From example CheckMimeType:

QAndroidActivityResultReceiver

In some customer apps and also ekke’s SHARE Example App the QAndroidActivityResultReceiver Class was used. To use this class with Qt 6.6, please follow these steps:

  • QMake .pro:
    • Add Qt += core-private
  • From C++:
    • remove #include QAndroidActivityResultReceiver
    • add #include <QtCore/private/qandroidextras_p.h>
    • use QJniObject instead of QAndroidJniObject as described above

Package names in JAVA Code

From Android Templates 6.6 you know that Qt changed in Android Manifest

  • import org.qtproject.qt5.android.bindings.QtActivity;
    • -> import org.qtproject.qt.android.bindings.QtActivity;
  • import org.qtproject.qt5.android.QtNative;
    • -> import org.qtproject.qt.android.QtNative;

So it could be that some of your Java Code reclaims a wrong package – please change:

Custom Android FileProvider

Are you already using an Android FileProvider to share data from your App ?

Qt is using an own Qt FileProvider to support Qt DesktopServices. See Custom Android FileProvider to learn, how both can co-exist.

Android Permissions not covered from Qt Permissions API

Qt has added Application Permissions in a crossplatform way to new Qt Permissions API. You have learned HowTo use them per ex. for Bluetooth Permissions or Camera Permissions. All of the Permissions stuff is WIP, so we still have to deal with platform specific code.

Qt 6.6 supports API 33 which is required for Apps published to Google Play Store.

There are some behavior changes from Google as described for Granular Media Permissions. THX @MikeWhite mentioning this at Qt Discord Server and creating QTBUG-116834.

Qt 5.15 / API 31/32 – READ / WRITE EXTERNAL

Android Manifest

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

This Permission will be generated by default if <!-- %%INSERT_PERMISSIONS --> is part of the Manifest.

Request Permission WRITE_EXTERNAL_STORAGE:

#if defined(Q_OS_ANDROID)
// we don't need permissions if we only share files to other apps using FileProvider
// but we need permissions if other apps share their files with our app and we must access those files
bool ApplicationUI::checkPermission() {
    QtAndroid::PermissionResult r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
    if(r == QtAndroid::PermissionResult::Denied) {
        QtAndroid::requestPermissionsSync( QStringList() << "android.permission.WRITE_EXTERNAL_STORAGE" );
        r = QtAndroid::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE");
        if(r == QtAndroid::PermissionResult::Denied) {
            qDebug() << "Permission denied";
            emit noAccessToExternalStorage();
            return false;
        }
   }
    qDebug() << "YEP: Permission OK";
   return true;
}
#endif

Qt 6.6 / API 33 – READ / WRITE EXTERNAL – MEDIA IMAGES

Now for Qt 6.6 and API 33 it’s different.

Android Manifest

The new READ_MEDIA_IMAGES permission isn’t part of the Qt-generated default permissions, so you must add:

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>

Request Permission READ_MEDIA_IMAGES

Thanks to @MikeWhite providing the code (QTBUG-116834) to check the permission:

QMake .pro: 
Qt += core-private

C++:
#ifdef Q_OS_ANDROID
    #include <QCoreApplication>
    #include <QtCore/private/qandroidextras_p.h>
#endif
...
#ifdef Q_OS_ANDROID
bool checkPermission() {
    QList<bool> permissions;

    auto r = QtAndroidPrivate::checkPermission("android.permission.READ_EXTERNAL_STORAGE").result();
    if (r != QtAndroidPrivate::Authorized)
    {
        r = QtAndroidPrivate::requestPermission("android.permission.READ_EXTERNAL_STORAGE").result();
        if (r == QtAndroidPrivate::Denied)
            permissions.append(false);
    }
    r = QtAndroidPrivate::checkPermission("android.permission.WRITE_EXTERNAL_STORAGE").result();
    if (r != QtAndroidPrivate::Authorized)
    {
        r = QtAndroidPrivate::requestPermission("android.permission.WRITE_EXTERNAL_STORAGE").result();
        if (r == QtAndroidPrivate::Denied)
            permissions.append(false);
    }
    r = QtAndroidPrivate::checkPermission("android.permission.READ_MEDIA_IMAGES").result();
    if (r != QtAndroidPrivate::Authorized)
    {
        r = QtAndroidPrivate::requestPermission("android.permission.READ_MEDIA_IMAGES").result();
        if (r == QtAndroidPrivate::Denied)
            permissions.append(false);
    }
    return (permissions.count() != 3);
}
#endif

TBD