En esta página

Servicios Android

Puedes crear servicios Android usando Qt. Un servicio es un componente que se ejecuta en segundo plano, por lo que no tiene interfaz de usuario. Es útil para realizar operaciones a largo plazo, como registrar el GPS, esperar notificaciones de redes sociales, etc. Un servicio continuará ejecutándose incluso si la aplicación que lo inició se cierra.

Montar el servicio

Para empezar, crea un directorio de paquetes Android como se indica en Extending Qt with Android Facilities. Este directorio contiene el archivo AndroidManifest.xml. Dentro del directorio package, crea un directorio src, donde se crearán todos tus paquetes y clases Java.

Crear la Clase de Servicio

Cuando decida utilizar QtService o Android Service, el mismo razonamiento que con Activity se aplica aquí. A menos que estés usando características que requieran que las librerías Qt sean cargadas, como las llamadas nativas de Qt y el manejo de eventos, extender Service debería funcionar.

Puedes crear un servicio extendiendo la clase QtService o Service a tu clase Java. Dependiendo de si quieres usar características de Qt en tu servicio o llamar a funciones nativas de C++ desde Java, necesitas extender QtService o Service. Empecemos con un servicio sencillo, como el siguiente:

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.qtproject.qt.android.bindings.QtService;

public class QtAndroidService extends QtService
{
    private static final String TAG = "QtAndroidService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Creating Service");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "Destroying Service");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int ret = super.onStartCommand(intent, flags, startId);

        // Do some work

        return ret;
    }
}

Iniciar el servicio

Android permite iniciar servicios bajo demanda o en tiempo de arranque. También puedes hacer ambas cosas usando Qt.

Iniciar un servicio bajo demanda

Puedes iniciar el servicio de las siguientes maneras:

  • Directamente desde C++ usando QAndroidIntent y QJniObject, creando un Intent de servicio y llamando al método startService() de la actividad principal de la app:
    // Outside of the function body
    Q_DECLARE_JNI_CLASS(Intent, "android/content/Intent")
    Q_DECLARE_JNI_CLASS(ComponentName, "android/content/ComponentName")
    Q_DECLARE_JNI_CLASS(QtAndroidService, "org/qtproject/example/qtandroidservice/QtAndroidService")
    
    // Inside function body
    using namespace QtJniTypes;
    using namespace QNativeInterface;
    
    auto *androidApp = qGuiApp->nativeInterface<QAndroidApplication>();
    Q_ASSERT(androidApp);
    Context context = androidApp->context();
    
    QJniEnvironment env;
    auto serviceClass = env.findClass(Traits<QtAndroidService>::className());
    Intent serviceIntent(context, serviceClass);
    context.callMethod<ComponentName>("startService", serviceIntent);
  • Iniciar el servicio llamando a un método Java. La forma más sencilla es crear un método estático en tu clase de servicio:
    public static void startQtAndroidService(Context context) {
            context.startService(new Intent(context, QtAndroidService.class));
    }

    Luego puedes llamarlo desde C++ usando la siguiente llamada JNI:

    using namespace QtJniTypes;
    using namespace QNativeInterface;
    // ...
    auto *androidApp = qGuiApp->nativeInterface<QAndroidApplication>();
    Q_ASSERT(androidApp);
    Context context = androidApp->context();
    QtAndroidService::callStaticMethod<void>("startQtAndroidService", context);

Iniciar un servicio en tiempo de arranque

Para ejecutar un servicio en tiempo de arranque, necesitas un BroadcastReceiver.

Cree una clase Java personalizada:

public class QtBootServiceBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startServiceIntent = new Intent(context, QtAndroidService.class);
        context.startService(startServiceIntent);
    }
}

Añada el siguiente uses-permission en el cuerpo de la sección <manifest> del archivo AndroidManifest.xml:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Añada también la definición receiver en el cuerpo de la sección <application>:

<receiver android:name=".QtBootServiceBroadcastReceiver" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
Limitaciones
  • Android 15.0 introdujo algunas limitaciones en el lanzamiento de servicios en primer plano, después de recibir BOOT_COMPLETED. Para obtener más información, consulta Restricciones en BOOT_COMPLETED.
  • Android 8.0 introdujo algunas limitaciones en la ejecución de servicios en segundo plano, lo que significa que el uso de una clase normal Service podría no funcionar. Para obtener más información, consulta la recomendación de Android de utilizar servicios en primer plano o JobIntentService.

Gestionar el servicio en AndroidManifest.xml

Para que el servicio sea utilizable en una aplicación Android, debes declararlo en el archivo AndroidManifest.xml. Empecemos añadiendo la sección del servicio:

  • Cuando extiendas Service, simplemente declara la sección de servicio como un servicio normal de Android. Añade lo siguiente dentro de la sección <application>:
    <service android:name=".QtAndroidService" android:exported="true">
        <meta-data android:name="android.app.background_running" android:value="true"/>
    </service>

    De esta forma el servicio se iniciará en el mismo proceso que QtActivity, lo que te permite usar llamadas nativas C++ desde código Java. Puedes ejecutarlo en un proceso separado pero de esa forma no podrás usar ninguna llamada nativa para la comunicación porque las librerías Qt no están cargadas para ese proceso. Para ejecutarlo en un proceso separado, añade esto a la etiqueta de servicio:

    android:process=":qt_service"
  • Cuando extiendas QtService, necesitas declarar otros elementos para cargar todas las librerías necesarias requeridas para Qt, principalmente los mismos elementos que en la sección <activity> para QtActivity. Añade lo siguiente:
    <service android:process=":qt_service" android:name=".QtAndroidService" android:exported="true">
        <meta-data android:name="android.app.lib_name" android:value="service"/>
        <meta-data android:name="android.app.background_running" android:value="true"/>
    </service>

Nota: Asegúrese de definir lo siguiente para ejecutar el servicio en segundo plano:

<meta-data android:name="android.app.background_running" android:value="true"/>

Hay algunas variaciones sobre cómo declarar servicios. Algunas de ellas ya se utilizan en el fragmento de manifiesto anterior. Dependiendo de su caso de uso, ejecute el servicio en el mismo proceso que QtActivity o en un proceso separado.

Servicio en el mismo proceso que QtActivity

Para ejecutar un servicio en el mismo proceso que QtActivity, declare la cabecera del servicio como sigue:

<service android:name=".QtAndroidService" android:exported="true">

Servicio en proceso separado

Para ejecutar un servicio en un proceso dedicado, declare la cabecera del servicio como sigue:

<service android:process=":qt_service" android:name=".QtAndroidService" android:exported="true">

Qt carga el archivo .so definido en android.app.lib_name meta-data , y llama a la función main() con todos los argumentos establecidos en android.app.arguments meta-data . Cuando se ejecuta en un proceso independiente, puede iniciar el servicio utilizando el mismo archivo lib que la actividad principal o un archivo lib independiente.

Utilizar el mismo archivo lib .so

Utilizar el mismo archivo lib .so que la actividad principal significa que el servicio utilizará el mismo punto de entrada con un argumento extra para distinguirlo de la actividad principal. Puedes manejar la ejecución de tu aplicación en la función main() de acuerdo a los argumentos proporcionados. Añade la siguiente declaración de argumentos al cuerpo de tu servicio:

<meta-data android:name="android.app.arguments" android:value="-service"/>

A continuación, asegúrate de que el servicio android.app.lib_name es el mismo que la actividad principal, añade lo siguiente:

<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>

Cuando se utiliza el mismo archivo lib .so, la función main() de su aplicación se ejecuta dos veces, una para iniciar la actividad principal y la segunda para iniciar el servicio. Por lo tanto, tienes que manejar cada ejecución según el argumento proporcionado. Una forma de lograrlo es la siguiente:

if (argc <= 1) { // código para manejar la ejecución de la actividad principal} else if (argc > 1 && strcmp(argv[1], "-service") == 0) {    qDebug() << "Service starting with from the same .so file";
    QAndroidService app(argc, argv); return app.exec(); } else {    qWarning() << "Unrecognized command line argument";
   return-1; }
Utilice un archivo .so Lib separado

En este caso, necesita tener un subproyecto con una plantilla lib que proporcione un ejecutable diferente para el servicio. Un proyecto de ejemplo es:

  • En CMake:
    find_package(Qt6 REQUIRED COMPONENTS Core)
    
    qt_add_library(service SHARED
        servicemessenger.h
        service_main.cpp
    )
    
    target_link_libraries(service
        PRIVATE
            Qt::Core
            Qt::CorePrivate
    )
  • En qmake:
    TEMPLATE = lib
    TARGET = service
    CONFIG += dll
    QT += core core-private
    
    SOURCES += \
        service_main.cpp
    
    HEADERS += servicemessenger.h

En el service_main.cpp podrías tener lo siguiente:

#include <QDebug>#include <QAndroidService>#include <QtCore/private/qandroidextras_p.h>int main(int argc, char *argv[]){
    qWarning() << "Service starting from a separate .so file";
    QAndroidService app(argc, argv); return app.exec(); }

Define el android.app.lib_name para el servicio en el AndroidManifest.xml:

<meta-data android:name="android.app.lib_name" android:value="service"/>

Comunicación con el servicio

Qt para Android ofrece una variedad de métodos de comunicación entre procesos (IPC) para comunicarse con los Servicios de Android. Dependiendo de la estructura de su proyecto, puede utilizar llamadas nativas C++ de Java Service o Android BroadcastReceiver.

Llamadas nativas C++ desde Java Service

Esto puede funcionar con servicios que se ejecutan en el mismo proceso que QtActivity e incluso si Service está extendido.

Para obtener más información, consulte el ejemplo de notificador de Qt para Android.

Uso de Android BroadcastReceiver

Android BroadcastReceiver permite el intercambio de mensajes entre el sistema Android, aplicaciones, actividades y servicios. De forma similar a otras características de Android, Qt puede utilizar receptores de difusión para intercambiar mensajes entre QtActivity y su servicio. Empecemos con la lógica para enviar un mensaje desde tu servicio. Añade lo siguiente en la implementación de tu servicio, que llama a sendBroadcast():

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    int ret = super.onStartCommand(intent, flags, startId);

    Intent sendToUiIntent = new Intent();
    sendToUiIntent.setAction(ActivityUtils.BROADCAST_CUSTOM_ACTION);
    sendToUiIntent.putExtra("message", "simple_string");

    Log.i(TAG, "Service sending broadcast");
    sendBroadcast(sendToUiIntent);

    return ret;
}

Luego, necesitas crear y registrar el receptor de broadcast desde la actividad principal de Qt. La forma más sencilla es crear una clase personalizada con un método e implementar toda esa lógica en Java. En el siguiente ejemplo, el servicio envía un mensaje "simple_string" a Qt llamando al método nativo sendToQt():

public class ServiceBroadcastUtils {

    private static native void sendToQt(String message);

    private static final String TAG = "ActivityUtils";
    public static final String BROADCAST_CUSTOM_ACTION = "org.qtproject.example.qtandroidservice.broadcast.custom";

    public void registerServiceBroadcastReceiver(Context context) {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BROADCAST_CUSTOM_ACTION);
        context.registerReceiver(serviceMessageReceiver, intentFilter);
        Log.i(TAG, "Registered broadcast receiver");
    }

    private BroadcastReceiver serviceMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "In OnReceive()");
            if (BROADCAST_CUSTOM_ACTION.equals(intent.getAction())) {
                String message = intent.getStringExtra("message");
                sendToQt(message);
                Log.i(TAG, "Service sent back message to C++: " + message);
            }
        }
    };
}

Para hacer uso de todo eso, inicie su servicio como se muestra en Iniciar el Servicio, y luego registre el receptor de difusión llamando al método registerServiceBroadcastReceiver():

QJniEnvironment env;
jclass javaClass = env.findClass("org/qtproject/example/qtandroidservice/ActivityUtils");
QJniObject classObject(javaClass);
const QJniObject context(QNativeInterface::QAndroidApplication::context());
classObject.callMethod<void>("registerServiceBroadcastReceiver",
                             "(Landroid/content/Context;)V",
                             context.object());

Utilizando Qt Remote Objects

Qt Remote Objects ofrece una forma sencilla de compartir APIs entre procesos Qt. El concepto principal es el servidor en el proceso de servicio, y tienen una réplica en la aplicación Qt, entonces esas dos partes son capaces de intercambiar datos entre sí, utilizando señales y ranuras.

Preparar la réplica

Consideremos un ejemplo de servicio con un archivo lib .so separado. Define un archivo .rep que defina nuestra clase de comunicación:

class ServiceMessenger {
    SLOT(void ping(const QString &message));
    SIGNAL(pong(const QString &message));
}

La clase se define en el sub-proyecto de servicio como servicemessenger.h:

#include "rep_servicemessenger_source.h"

class ServiceMessenger : public ServiceMessengerSource {
public slots:
    void ping(const QString &name) override {
        emit pong("Hello " + name);
    }
};

A continuación, añada el archivo .rep tanto a la aplicación principal como al servicio en la aplicación principal.

  • En CMake:
    find_package(Qt6 REQUIRED COMPONENTS RemoteObjects)
    
    qt_add_repc_replicas(service
        ../servicemessenger.rep
    )
    
    target_link_libraries(service PRIVATE Qt6::RemoteObjects)
  • En qmake:
    QT += remoteobjects
    REPC_REPLICA += servicemessenger.rep

Y en el subproyecto de servicio:

  • En CMake:
    find_package(Qt6 REQUIRED COMPONENTS RemoteObjects)
    
    qt_add_repc_sources(service
        ../servicemessenger.rep
    )
    target_link_libraries(service PRIVATE Qt6::RemoteObjects)
  • En qmake:
    QT += remoteobjects
    REPC_SOURCE += servicemessenger.rep

Conectar la fuente y la réplica

Defina el nodo de origen Qt Remote Objects en la función main() del subproyecto de servicio:

#include "servicemessenger.h"#include <QDebug>#include <QAndroidService>#include <QtCore/private/qandroidextras_p.h>int main(int argc, char *argv[]){
    qWarning() << "QtAndroidService starting from separate .so";
    QAndroidService app(argc, argv);    QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica"))); ServiceMessenger serviceMessenger; srcNode.enableRemoting(&serviceMessenger); return app.exec(); }

A continuación, en la función main() de la aplicación, conéctate al nodo origen:

QRemoteObjectNode repNode; repNode.connectToNode(QUrl(QStringLiteral("local:replica")));QSharedPointer<ServiceMessengerReplica> rep(repNode.acquire<ServiceMessengerReplica>());bool res =  rep->waitForSource(); Q_ASSERT(res);QObject::connect(rep.data(), &ServiceMessengerReplica::pong, [](const QString &mensaje){    qDebug() << "Service sent: " << message;
});  rep->ping("¡Qt y Android son amigos!");

Este ejemplo envía un mensaje desde el proceso de la aplicación principal al servicio. El servicio responde con el mismo mensaje, que se imprime en el logcat de depuración.

Nota: Se puede utilizar el mismo método cuando se utiliza el mismo archivo .so lib. Para más información, vea Usar el mismo archivo .so lib.

Usando QAndroidBinder

QAndroidBinder es una clase de conveniencia que permite la comunicación entre procesos implementando los métodos más importantes de Binder. Permite enviar objetos QByteArray o QVariant entre procesos.

Nota: Qt para Android tiene una limitación que obliga a ejecutar sólo un servicio a la vez cuando se ejecutan varios servicios en un mismo proceso. Por lo tanto, se recomienda ejecutar cada servicio en su propio proceso. Para más información, consulte QTBUG-78009.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.