Qt应用未运行时如何通知用户?Qt Quick 2安卓端实现咨询
Great question! Since Qt's cross-platform APIs don't cover background tasks and system notifications when the app isn't running (especially on Android), you'll need to combine Qt with native Android functionality. Here's how to approach both parts of your problem:
Qt doesn't have a built-in class for background tasks that run when the app is closed—this is a platform-specific feature. On Android, the recommended way to handle periodic background work is using WorkManager (Google's official library for deferrable, repeatable tasks). Here's a step-by-step breakdown:
Step 1: Add Android WorkManager to your Qt project
You'll need to include the WorkManager dependencies in your Android build. Edit thebuild.gradlefile (located inandroid/build.gradleof your Qt project) to add:dependencies { implementation "androidx.work:work-runtime:2.8.1" }Step 2: Create a native Android Worker class
Write a Java/Kotlin class that extendsWorker—this will handle the GET request and check for new messages. For example, a Java Worker:import androidx.work.Worker; import androidx.work.WorkerParameters; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class MessageCheckWorker extends Worker { public MessageCheckWorker(Context context, WorkerParameters params) { super(context, params); } @Override public Result doWork() { // Perform GET request to check for new messages try { URL url = new URL("https://your-server.com/check-new-messages"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // Add any auth headers if needed conn.setRequestProperty("Authorization", "Bearer YOUR_USER_TOKEN"); int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String response = in.readLine(); in.close(); // Parse response to check for new messages if (hasNewMessages(response)) { // Trigger notification (we'll cover this in the next section) NotificationHelper.showNewMessageNotification(getApplicationContext()); } } return Result.success(); } catch (Exception e) { e.printStackTrace(); return Result.retry(); } } private boolean hasNewMessages(String response) { // Implement your logic to parse the server response // Example: return response.contains("\"new_messages\": true"); return false; } }Step 3: Schedule the periodic work
You need to schedule the Worker to run at intervals. You can do this either from your Qt code (via JNI) or from a native AndroidApplicationclass. Here's how to schedule it from Qt using JNI:#include <QAndroidJniObject> #include <QAndroidJniEnvironment> void scheduleMessageCheck() { QAndroidJniObject context = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); if (context.isValid()) { QAndroidJniObject workManager = QAndroidJniObject::callStaticObjectMethod("androidx/work/WorkManager", "getInstance", "(Landroid/content/Context;)Landroidx/work/WorkManager;", context.object()); QAndroidJniObject constraints = QAndroidJniObject::callStaticObjectMethod("androidx/work/Constraints", "Builder", "()Landroidx/work/Constraints$Builder;").callObjectMethod("build", "()Landroidx/work/Constraints;"); QAndroidJniObject periodicRequest = QAndroidJniObject::callStaticObjectMethod("androidx/work/PeriodicWorkRequest", "Builder", "(Ljava/lang/Class;JJ)Landroidx/work/PeriodicWorkRequest$Builder;", QAndroidJniObject::fromString("com.yourpackage.MessageCheckWorker").object(), 15L * 60L * 1000L, 5L * 60L * 1000L).callObjectMethod("setConstraints", "(Landroidx/work/Constraints;)Landroidx/work/PeriodicWorkRequest$Builder;", constraints.object()).callObjectMethod("build", "()Landroidx/work/PeriodicWorkRequest;"); workManager.callMethod<void>("enqueueUniquePeriodicWork", "(Ljava/lang/String;Landroidx/work/ExistingPeriodicWorkPolicy;Landroidx/work/PeriodicWorkRequest;)V", QAndroidJniObject::fromString("MessageCheck").object(), QAndroidJniObject::getStaticObjectField("androidx/work/ExistingPeriodicWorkPolicy", "REPLACE", "Landroidx/work/ExistingPeriodicWorkPolicy;").object(), periodicRequest.object()); } }Call this function when your app starts to set up the periodic check.
Qt's QNotification only works when the app is active. To show notifications when the app is closed, you need to use Android's native NotificationManager. Here's how to implement this:
Step 1: Create a Notification Helper class
Add a native Android class to handle notification creation:import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.os.Build; import androidx.core.app.NotificationCompat; public class NotificationHelper { private static final String CHANNEL_ID = "new_messages_channel"; public static void showNewMessageNotification(Context context) { // Create notification channel (required for Android 8.0+) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "New Messages", NotificationManager.IMPORTANCE_DEFAULT); channel.setDescription("Notifications for new messages from other users"); NotificationManager manager = context.getSystemService(NotificationManager.class); manager.createNotificationChannel(channel); } // Build the notification NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) // Replace with your app's notification icon .setContentTitle("New Message") .setContentText("You have unread messages from other users") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setAutoCancel(true); // Optional: Launch your Qt app when the notification is clicked // Intent intent = new Intent(context, org.qtproject.qt5.android.bindings.QtActivity.class); // PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // builder.setContentIntent(pendingIntent); // Show the notification NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(1, builder.build()); } }Step 2: Declare permissions in AndroidManifest.xml
Edit your Qt project'sAndroidManifest.xmlto add necessary permissions and components:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Required for Android 13+ --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Optional, for keeping device awake during the request --> <application ...> <!-- Disable default WorkManager initializer if needed --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <meta-data android:name="androidx.work.WorkManagerInitializer" android:value="androidx.startup" tools:node="remove" /> </provider> </application>
Instead of polling the server periodically, a more efficient approach is to use push notifications via FCM. This way, your server sends a push message directly to the device when a new message arrives, and Android handles displaying the notification even if the app isn't running. You can integrate FCM with Qt using JNI to call native Android FCM APIs, which will handle receiving and displaying notifications automatically.
内容的提问来源于stack exchange,提问作者mohsen




