Qt: Request Android app permissions

Each Android app, based to the "interaction" with system, have to declare what resources need to access through some special info called permissions. Normally these permission are declared inside the AndroidManifest.xml and this was enough. However, from android version 23 (Marshmallow) and above some part of these permissions (classified as more "critical") have to be manually requested to the user who have to accept for authorize the app to use it.


Full example code can be found here

Fortunately there is no need to develop native java code since Qt team already provided high level function to make the permission request, it just need some explanation for learn how to correctly use it. Basically the code to request a permission is only the following:

void MainWindow::on_RequestPermissionButton_clicked()
{
    if(QtAndroid::androidSdkVersion() >= 23)
    {
        const QString PermissionID("android.permission.READ_EXTERNAL_STORAGE");

        if(QtAndroid::checkPermission(PermissionID) != QtAndroid::PermissionResult::Granted)
        {
            if(QtAndroid::shouldShowRequestPermissionRationale(PermissionID))
            {
                QMessageBox::information(this, "Info", "Please, this permission is requested for bla bla bla");
            }
            QtAndroid::requestPermissions(QStringList() << PermissionID, std::bind(&MainWindow::RequestPermissionsResults, this, _1));
            return;
        }

        QMessageBox::information(this, "Info", "Permission is already granted");
    }
}

void MainWindow::RequestPermissionsResults(const QtAndroid::PermissionResultMap &ResultMap)
{
    if(ResultMap["android.permission.READ_EXTERNAL_STORAGE"] == QtAndroid::PermissionResult::Granted)
        QMessageBox::information(this, "Info", "Permission granted!");
    else
        QMessageBox::warning(this, "Error", "Permission denied!");
}

In this example we'll try to request the READ_EXTERNAL_STORAGE permission. At first the permission name is the same string you put on AndroidManifest.xml than no difficult here. The first call is the following:

QtAndroid::checkPermission(PermissionID)

Here we ask to the system if we already have the required permission. In case the permission is already granted there is nothing to do and the app can proceed. If the permission is not grated you have to ask for the authorization by using the second call:

QtAndroid::requestPermissions(QStringList() << PermissionID, std::bind(&MainWindow::RequestPermissionsResults, this, _1));

Here you ask for the permission. Please note the first param is a list of string. That mean you can ask for multiple permission in one call. Second param is a callback function that will be called with the result of user choice. This function is asynchronous but it exist also a synchrony function with a timeout, check the documentation here. The result of this call is the following system messagebox for the user, you can not modify this messagebox in any way since it's managed directly by the system:



If case the user will deny the request you can retry but before try to ask for the permission again is recommended to call this function:

QtAndroid::shouldShowRequestPermissionRationale(PermissionID)

This function is quite particular and return true only in the case a first attempt to ask to permission has been denied. Basically it "suggest" to show a message to the user explaining why your app need the specific permission before retry to ask for permission again. Now please note a very important particular. Teorically you can ask for the same permission infinitely, however from the second time you ask for the same permission the system message window will appear as following:



As you can note in this case there is a checkbox allowing the user to not be annoyed by your request anymore (Don't ask again). If the user will check it and will deny the request again any next request for the permission will be automatically denied without show any message than be careful in decide when ask for permission and, above all, to explain very clearly why you need that permission.


Comments

  1. This approach didn't work for me. I keep getting "Your application encountered a fatal error and cannot continue." Granted I did this with the Android emulator. same error on my phone too.

    ReplyDelete
    Replies
    1. I found your git repo and use the files in there instead. Granted they were the same as what I had before but this time they worked on both.

      Delete

Post a Comment

Popular posts from this blog

Access GPIO from Linux user space

Android: adb push and read-only file system error

Tree in SQL database: The Nested Set Model