Hello everyone interested in Qt for Android.
Following my previous post on debugging in Qt for Android, I've now looked into how to retrieve GPS values. There are two main approaches: the first uses the Qt Library, and the second involves handling values with JNI and simply displaying them. In this article, we’ll go through the first approach.
There isn’t much information available online for accessing GPS in Qt for Android, so I obtained some data through ChatGPT. However, some of the information provided was inaccurate, requiring me to verify details periodically.
Since we need to obtain permission before accessing GPS values, let’s implement this step first.
1. Testing Environment for Qt for Android
1.1) Development Environment and Required Libraries
I worked with Qt 6.7.3 for Android and NDK 25.1.
To retrieve GPS values using the Qt Library, you’ll need to add the Positioning library when installing Qt. You can check if it's installed or add it by running the "Maintenance Tool."
Navigate to "Tools -> Qt Maintenance Tool -> Start Maintenance Tool". A window similar to the installation screen will appear. Log in, then choose "Add or Remove Components".
Under Qt -> Qt6.7.3 -> Additional Libraries, select Qt Positioning for installation.
1.2) Emulator (AVD)
I created an emulator with Android 13 (SDK 33).
2. Project Creation and Configuration
2.1) Project Creation
Start by selecting Qt Widget Application. You can freely set the project name and configurations. For testing, I recommend choosing QWidget as the base class.
During Kit Selection, choose Android Qt 6.7.3 Clang x86_64. If you want to test on an actual smartphone, select Android Qt 6.7.3 Clang arm64-v8a or armeabi-v7a. (Assuming that Android SDK settings are already configured in Qt Creator.)
2.2) Project Configuration
(1) Android SDK Settings
In the generated project, go to "Projects -> Build Android APK -> Application" and select android-34 as the SDK version.
If there’s a version mismatch, you’ll see an error instructing you to match the version.
Click the Create Templates button to generate the Android package files.
Once templates are created, you’ll find an android folder under Other Files in the Projects panel, containing configuration files for app services and permissions.
(2) Adding Location Permissions
To use GPS, add the ACCESS_FINE_LOCATION permission. There are two location permissions: ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION.
For this test, we’ll use the ACCESS_FINE_LOCATION permission.
Differences between ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION:
- ACCESS_FINE_LOCATION
- Precision: Provides highly accurate location information, using GPS or network providers to obtain exact coordinates.
- Usage: Navigation apps, location-based games, and services requiring precise location data.
- ACCESS_COARSE_LOCATION
- Precision: Provides less accurate location information, estimating location via cellular networks or Wi-Fi.
- Usage: Weather apps, location-based ads, and services that only need approximate location.
(3) Adding the Library
In the project file, add positioning alongside core and gui in the .pro file.
3. Writing JNI Source Code to Obtain Permissions
3.1) Creating the JNI (Java Native Interface) Folder for Permission Requests
To use JNI, you need to create a folder and place the .java file inside it. The path should be created according to the package name that appears when you click on the AndroidManifest.xml file.
For this test, I set the package name as "org.gpsproject.getLibGPS".
In the Projects section, switch to File System view. Right-click on the android folder, and create subfolders to match the package name structure (e.g., src\org\gpsproject\getLibGPS).
3.2) Creating the JNI (Java) File for Permissions
In the subfolder created above, right-click and select Add New to create a Java File.
I named the file jniUtil.java to allow for future additions.
Once you’ve created the folder and Java file, switch back to the Projects view for better organization.
3.3) Permission Request Code
The code will include functions to request permission and to verify if permission has been granted.
package org.gpsproject.getLibGPS;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class JniUtil {
private static final int REQUEST_CODE = 1001;
// Permission request method
public static void requestPermission(Context context, String permission) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context, new String[]{permission}, REQUEST_CODE);
}
}
// Permission Check Method
public static boolean checkPermission(Context context, String permission) {
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
}
4. Writing Permission Code in Qt
4.1) UI Screen
Add a Push Button to the widget screen to initiate the permission request. Set the object name to btnGetPermission.
4.2) Writing widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
void requestPermission(const QString &permission);
bool hasPermission(const QString &permission);
private slots :
void slotBtnGetPermission();
};
#endif // WIDGET_H
4.3) Writing widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QJniObject>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->btnGetPermission, &QPushButton::clicked, this, &Widget::slotBtnGetPermission);
}
Widget::~Widget()
{
delete ui;
}
void Widget::slotBtnGetPermission()
{
requestPermission("android.permission.ACCESS_FINE_LOCATION");
bool hasFineLocationPermission = hasPermission("android.permission.ACCESS_FINE_LOCATION");
qDebug() << "Has ACCESS_FINE_LOCATION permission:" << hasFineLocationPermission;
}
void Widget::requestPermission(const QString &permission) {
QJniObject permissionStr = QJniObject::fromString(permission);
QJniObject::callStaticMethod<void>(
"org/gpsproject/getLibGPS/JniUtil",
"requestPermission",
"(Landroid/content/Context;Ljava/lang/String;)V",
QNativeInterface::QAndroidApplication::context(),
permissionStr.object<jstring>()
);
}
bool Widget::hasPermission(const QString &permission) {
QJniObject permissionStr = QJniObject::fromString(permission);
jboolean result = QJniObject::callStaticMethod<jboolean>(
"org/gpsproject/getLibGPS/JniUtil",
"checkPermission",
"(Landroid/content/Context;Ljava/lang/String;)Z",
QNativeInterface::QAndroidApplication::context(),
permissionStr.object<jstring>()
);
return result;
}
5. Verifying the Execution Result
If there are no issues with the source code, the app with a "Get Permission" button will run. When you click the "Get Permission" button, a prompt will appear asking if you want to allow access to location information. For multiple tests, select "Only this time".
The first time you press the "Get Permission" button, it will return false for permission, but pressing it again should confirm true for permission.
This concludes the tutorial on how to allow permissions for using GPS in a "Qt for Android App." I initially thought it would be quick, but it took longer as I wrote and checked the settings, so I divided it into two parts.
You can refer to the above content to obtain other permissions as well.
Thank you.
'Programming > Qt' 카테고리의 다른 글
Setting Up adb Debugging and Viewing Logcat Messages with Qt (2) | 2024.11.06 |
---|---|
Android Emulator 사용 시 intel HAXM is deprecated 해결 방법 (2) | 2024.11.05 |
Qt6.x 조금 빠르게 설치하기(mirror 서버 이용) (2) | 2024.11.02 |
VirtualBox 가상환경의 리눅스(Ubuntu)에 안드로이드용 Qt 설치 및 AVD(Emulator)에서 실행해 보기 (2) | 2024.09.13 |
Qt를 이용한 멀티캐스트 수신 코드 및 테스트 (Multicast Receiver) (0) | 2024.07.10 |