Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Foreground service stops working when the main application has been closed



  • Hi,
    I'm working on android 7.0 and I'm trying to write an android service using Qt.
    Basically what I'm trying to do is a simple service who replies to commands received on ZMQ and for this task I'm using a foreground service since I want that the service continues to run even if the application that has started it has been closed.

    This is my java service:

    public class QtAndroidService extends Service
    {
        private static final String TAG = "QtAndroidService";
        private Notification.Builder serviceNotificationBuilder         = null;
        private static native void startZMQ();
    
        @Override
        public void onCreate() {
            super.onCreate();
            NotificationManager notification_manager =
                            (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        NotificationChannel channel = new NotificationChannel(getResources().getString(R.string.service_notification_channel_id),
                                getResources().getString(R.string.service_notification_channel_name),
                                NotificationManager.IMPORTANCE_LOW);
    
                        channel.setShowBadge(false);
    
                        notification_manager.createNotificationChannel(channel);
    
                        serviceNotificationBuilder = new Notification.Builder(this, getResources().getString(R.string.service_notification_channel_id))
                                .setSmallIcon(R.drawable.ic_stat_notify_service)
                                .setContentTitle(getResources().getString(R.string.service_notification_title))
                                .setContentText(getResources().getString(R.string.service_notification_text));
                                //.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
                    } else {
                        serviceNotificationBuilder = new Notification.Builder(this)
                                .setPriority(Notification.PRIORITY_LOW)
                                .setSmallIcon(R.drawable.ic_stat_notify_service)
                                .setContentTitle(getResources().getString(R.string.service_notification_title))
                                .setContentText(getResources().getString(R.string.service_notification_text));
                                //.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
                    }
    
                    startForeground(getResources().getInteger(R.integer.service_foreground_notification_id), serviceNotificationBuilder.build());
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i(TAG, "Destroying Service");
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            super.onStartCommand(intent, flags, startId);
            new Thread(new Runnable() {
                            public void run() {
                                startZMQ();
                            }
                        }).start();
    
    
            return Service.START_STICKY;
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    

    I started the service in this way

    JNINativeMethod methods[] {{"startZMQ", "()V", reinterpret_cast<void *>(startZMQ)}};
        QAndroidJniObject javaClass("org/qtproject/example/qtandroidservice/QtAndroidService");
    
        QAndroidJniEnvironment env;
        jclass objectClass = env->GetObjectClass(javaClass.object<jobject>());
        env->RegisterNatives(objectClass,
                             methods,
                             sizeof(methods) / sizeof(methods[0]));
        env->DeleteLocalRef(objectClass);
    
        QAndroidIntent serviceIntent(QtAndroid::androidActivity().object(),
                                            "org/qtproject/example/qtandroidservice/QtAndroidService");
        //serviceIntent.putExtra("name", name.toUtf8());
        QAndroidJniObject result = QtAndroid::androidActivity().callObjectMethod(
                    "startService",
                    "(Landroid/content/Intent;)Landroid/content/ComponentName;",
                    serviceIntent.handle().object());
    

    and this is the zeromq server function:

    static void startZMQ(JNIEnv *env, jobject /*thiz*/)
    {
            void *context = zmq_ctx_new ();
            void *responder = zmq_socket (context, ZMQ_REP);
            int rc = zmq_bind (responder, "tcp://*:5555");
            assert (rc == 0);
    
            while (1) {
                char buffer [10];
                zmq_recv (responder, buffer, 10, ZMQ_NOBLOCK);
                printf ("Received Hello\n");
                sleep (1);          //  Do some 'work'
                zmq_send (responder, "World", 5, 0);
            }
    }
    

    The service works fine until I keep the application open but when I close the application (but the service keeps running since it is a foreground service) the service stops to work (from my client application I don't see any reply to my requests using zeromq).

    I tried exteding from QtService instead of Service but the app randomly crashes and the service never works (I also do not see the foreground service icon so I think that there is a problem starting a QtService as foreground service).
    What I'm doing wrong? How can I obtain a working service (with the main application, which launched the service, closed) who correctly replies throught zeromq?

    Thanks


Log in to reply