Demonstrates how to run an Android service in a separate process, and how to communicate between the service process and the main process using Qt Remote Objects.
This example demonstrates how to create and run an Android service in a separate process from the main application process, and then exchange data between QML/C++ and the Java service using Qt Remote Objects .
When clicking the
Send to Service
button, the name entered in the QML view, Qt, in this case, is sent to the Android service. Then, the service replies back with a message
Hello Qt
which is printed in the QML view.
要运行范例从 Qt Creator ,打开 欢迎 模式,然后选择范例从 范例 。更多信息,拜访 构建和运行范例 .
To start a service in its own process, extend the
QtService
class for your service. Extending
QtService
allows the service to load the necessary Qt libraries used for Qt, like
Qt Remote Objects
libraries.
Start by creating the Java service class. The following class extends
QtService
and acts as your service entry point:
package org.qtproject.example.qtandroidservice; import android.content.Context; import android.content.Intent; import org.qtproject.qt5.android.bindings.QtService; import android.util.Log; 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"); } }
This class can have any logic you want using Java code. However, you don't need any logic to communicate with Qt as that will be done using Qt Remote Objects.
To use the service, it must be declared in the
AndroidManifest.xml
file as follows:
<service android:process=":qt_service" android:name=".QtAndroidService"> <meta-data android:name="android.app.lib_name" android:value="service"/> <meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/> <meta-data android:name="android.app.repository" android:value="default"/> <meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/> <meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/> <!-- Deploy Qt libs as part of package --> <meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/> <!-- Run with local libs --> <meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/> <meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/> <meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/> <meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/> <meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/> <!-- Run with local libs --> <!-- Background running --> <meta-data android:name="android.app.background_running" android:value="true"/> <!-- Background running --> </service>
The important part of this service declaration is the
lib_name
part. It will ensure that the service is run by the service's own lib file:
<meta-data android:name="android.app.lib_name" android:value="service"/>
To start the service, call the following function from the application's
main()
:
void startService() { QAndroidIntent serviceIntent(QtAndroid::androidActivity().object(), "org/qtproject/example/qtandroidservice/QtAndroidService"); QAndroidJniObject result = QtAndroid::androidActivity().callObjectMethod( "startService", "(Landroid/content/Intent;)Landroid/content/ComponentName;", serviceIntent.handle().object()); }
QAndroidService
is used to create the service process. For the service to start from its own
.so
lib file, create a sub-project with the following
.pro
文件:
TEMPLATE = lib TARGET = service CONFIG += dll
要使用
Qt Remote Objects
, define a
.rep
文件:
class QtAndroidService { SLOT(void sendToService(const QString &name)); SIGNAL(messageFromService(const QString &message)); }
定义
.rep
source file in the service project
.pro
:
REPC_SOURCE += ../common/qtandroidservice.rep
And in the application's
.pro
文件:
REPC_REPLICA += ../common/qtandroidservice.rep
Then define the class used by Qt Remote Objects, which has a
sendToService()
slot and a
messageFromService()
signal:
#include "rep_qtandroidservice_source.h" class QtAndroidService : public QtAndroidServiceSource { public slots: void sendToService(const QString &name) override { emit messageFromService("Hello " + name); }; };
Include the class in the previous snippet in
main.cpp
:
#include "rep_qtandroidservice_replica.h"
Now, in the service's
service_main.cpp
, create the
QRemoteObjectHost
node and start
QAndroidService
:
#include "qtandroidservice_ro.h" #include <QDebug> #include <QAndroidService> int main(int argc, char *argv[]) { qWarning() << "QtAndroidService starting from separate .so"; QAndroidService app(argc, argv); QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica"))); QtAndroidService qtAndroidService; srcNode.enableRemoting(&qtAndroidService); return app.exec(); }
In the application's
main.cpp
, create the client node and connect it to the source node created in the service and connect it to the QML view:
QRemoteObjectNode repNode; repNode.connectToNode(QUrl(QStringLiteral("local:replica"))); QSharedPointer<QtAndroidServiceReplica> rep(repNode.acquire<QtAndroidServiceReplica>()); engine.rootContext()->setContextProperty("qtAndroidService", rep.data()); bool res = rep->waitForSource(); Q_ASSERT(res); rep->sendToService("Qt");
Then, add a Connections element to watch for the incoming messages from the service:
Connections { target: qtAndroidService function onMessageFromService(message) { pongText.text = message } }
And set the
onClicked
for the sending button to:
onClicked: qtAndroidService.sendToService(pingText.text)
另请参阅 Android Service with Qt Remote Objects - Same Lib File , Android 服务 , Qt for Android ,和 Qt Android Extras .