You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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:

1. Implement Background Periodic Checks for New Messages

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 the build.gradle file (located in android/build.gradle of 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 extends Worker—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 Android Application class. 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.

2. Notify Users When the App Isn't Running

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's AndroidManifest.xml to 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>
    
Alternative: Use Firebase Cloud Messaging (FCM)

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

火山引擎 最新活动