如何在 Android 上将 Qt 应用程序安装为系统应用程序?
Posted
技术标签:
【中文标题】如何在 Android 上将 Qt 应用程序安装为系统应用程序?【英文标题】:How do I install a Qt app as a system app on Android? 【发布时间】:2021-08-17 15:03:34 【问题描述】:我正在构建一个嵌入式 android 设备,我有一个 Qt/QML
应用我想安装为系统应用。
但是,当我在将其移至 /system/app
或 /system/priv-app
后尝试启动它时,我收到一个弹出框“您的应用程序遇到了致命错误,无法继续”
我在最简单的 QML 项目上尝试了这个,并且尽可能地使用了标准的模拟器配置,但仍然遇到了问题
当我写这个问题时,我现在正在 Windows 上执行此操作,但我在尝试从我的主要 Linux 开发机器上执行此操作时也遇到了同样的问题。
为此我遵循的步骤(有些可能与实际执行的顺序不同,我在反复试验后从记忆中回忆):
-
安装 Android Studio Canary (2021.1.1 Canary 7)
安装 Android 29 SDK 和 x86 模拟器映像(Google API,而不是 Google Play),创建 Pixel 5 API 29 虚拟设备
从 Qt 维护工具/在线安装程序安装适用于 Android 的 Qt 5.15.2
安装 AdoptOpenJDK 8
运行 Qt Creator,前往 Tools->Options->Devices->Android,将其指向 AdoptOpenJDK 安装,让它设置所需的工具,并验证所有内容都有绿色复选标记
开始一个新项目并选择 Qt Quick “Swipe” 模板(最低限度的 QML 示例),5.15.2 for Android。在本例中命名为“QMLhello”。
在 5.15.2 multi-abi 的“构建”设置下的“项目”选项卡中,展开“qmake”部分并选中“x86”复选框,以便为 Android 模拟器构建 ABI
验证 Qt Creator 可以作为“普通”应用构建和运行应用(绿色的“运行”按钮成功部署和启动应用,并且可以在页面之间滑动)
我为准备将应用程序移至系统而执行的步骤:
-
将环境变量
studio.emu.params
添加到用户环境,内容为-writable-system
重新启动 Android Studio 并冷启动 AVD 模拟器以使用环境变量中指定的可写系统启动
adb devices
将模拟器列为设备
adb root
和 adb remount
成功重新挂载
我在四处翻找之后尝试了什么,将 *** 上的一些旧答案结合到我的尝试中:
adb shell
mv /data/app/org.qtproject.example.QMLhello-LpZtuoO0ejyQPg_I-8pWnQ==/lib/x86/* /system/lib
mv /data/app/org.qtproject.example.QMLhello-LpZtuoO0ejyQPg_I-8pWnQ== /system/app
那个 lib 目录的内容是:
generic_x86:/data/app/org.qtproject.example.QMLhello-LpZtuoO0ejyQPg_I-8pWnQ==/lib/x86 # ls -al
total 32892
drwxr-xr-x 2 system system 4096 2021-08-17 10:48 .
drwxr-xr-x 3 system system 4096 2021-08-17 10:48 ..
-rwxr-xr-x 1 system system 18100 1981-01-01 01:01 libQMLhello_x86.so
-rwxr-xr-x 1 system system 5885892 1981-01-01 01:01 libQt5Core_x86.so
-rwxr-xr-x 1 system system 4916776 1981-01-01 01:01 libQt5Gui_x86.so
-rwxr-xr-x 1 system system 1548420 1981-01-01 01:01 libQt5Network_x86.so
-rwxr-xr-x 1 system system 478836 1981-01-01 01:01 libQt5QmlModels_x86.so
-rwxr-xr-x 1 system system 47632 1981-01-01 01:01 libQt5QmlWorkerScript_x86.so
-rwxr-xr-x 1 system system 4236260 1981-01-01 01:01 libQt5Qml_x86.so
-rwxr-xr-x 1 system system 181004 1981-01-01 01:01 libQt5QuickControls2_x86.so
-rwxr-xr-x 1 system system 1392176 1981-01-01 01:01 libQt5QuickTemplates2_x86.so
-rwxr-xr-x 1 system system 4880080 1981-01-01 01:01 libQt5Quick_x86.so
-rwxr-xr-x 1 system system 562364 1981-01-01 01:01 libQt5RemoteObjects_x86.so
-rwxr-xr-x 1 system system 931652 1981-01-01 01:01 libc++_shared.so
-rwxr-xr-x 1 system system 56196 1981-01-01 01:01 libplugins_bearer_qandroidbearer_x86.so
-rwxr-xr-x 1 system system 26304 1981-01-01 01:01 libplugins_imageformats_qgif_x86.so
-rwxr-xr-x 1 system system 34944 1981-01-01 01:01 libplugins_imageformats_qicns_x86.so
-rwxr-xr-x 1 system system 22208 1981-01-01 01:01 libplugins_imageformats_qico_x86.so
-rwxr-xr-x 1 system system 399040 1981-01-01 01:01 libplugins_imageformats_qjpeg_x86.so
-rwxr-xr-x 1 system system 18112 1981-01-01 01:01 libplugins_imageformats_qtga_x86.so
-rwxr-xr-x 1 system system 432080 1981-01-01 01:01 libplugins_imageformats_qtiff_x86.so
-rwxr-xr-x 1 system system 18112 1981-01-01 01:01 libplugins_imageformats_qwbmp_x86.so
-rwxr-xr-x 1 system system 673576 1981-01-01 01:01 libplugins_imageformats_qwebp_x86.so
-rwxr-xr-x 1 system system 1200076 1981-01-01 01:01 libplugins_platforms_qtforandroid_x86.so
-rwxr-xr-x 1 system system 150600 1981-01-01 01:01 libplugins_qmltooling_qmldbg_debugger_x86.so
-rwxr-xr-x 1 system system 67868 1981-01-01 01:01 libplugins_qmltooling_qmldbg_inspector_x86.so
-rwxr-xr-x 1 system system 14076 1981-01-01 01:01 libplugins_qmltooling_qmldbg_local_x86.so
-rwxr-xr-x 1 system system 14076 1981-01-01 01:01 libplugins_qmltooling_qmldbg_messages_x86.so
-rwxr-xr-x 1 system system 22332 1981-01-01 01:01 libplugins_qmltooling_qmldbg_native_x86.so
-rwxr-xr-x 1 system system 45316 1981-01-01 01:01 libplugins_qmltooling_qmldbg_nativedebugger_x86.so
-rwxr-xr-x 1 system system 84564 1981-01-01 01:01 libplugins_qmltooling_qmldbg_preview_x86.so
-rwxr-xr-x 1 system system 63504 1981-01-01 01:01 libplugins_qmltooling_qmldbg_profiler_x86.so
-rwxr-xr-x 1 system system 22268 1981-01-01 01:01 libplugins_qmltooling_qmldbg_quickprofiler_x86.so
-rwxr-xr-x 1 system system 55248 1981-01-01 01:01 libplugins_qmltooling_qmldbg_server_x86.so
-rwxr-xr-x 1 system system 14072 1981-01-01 01:01 libplugins_qmltooling_qmldbg_tcp_x86.so
-rwxr-xr-x 1 system system 52096 1981-01-01 01:01 libqml_QtGraphicalEffects_private_qtgraphicaleffectsprivate_x86.so
-rwxr-xr-x 1 system system 50948 1981-01-01 01:01 libqml_QtGraphicalEffects_qtgraphicaleffectsplugin_x86.so
-rwxr-xr-x 1 system system 9928 1981-01-01 01:01 libqml_QtQml_Models.2_modelsplugin_x86.so
-rwxr-xr-x 1 system system 18128 1981-01-01 01:01 libqml_QtQml_RemoteObjects_qtqmlremoteobjects_x86.so
-rwxr-xr-x 1 system system 69520 1981-01-01 01:01 libqml_QtQml_StateMachine_qtqmlstatemachine_x86.so
-rwxr-xr-x 1 system system 9932 1981-01-01 01:01 libqml_QtQml_WorkerScript.2_workerscriptplugin_x86.so
-rwxr-xr-x 1 system system 9920 1981-01-01 01:01 libqml_QtQml_qmlplugin_x86.so
-rwxr-xr-x 1 system system 9924 1981-01-01 01:01 libqml_QtQuick.2_qtquick2plugin_x86.so
-rwxr-xr-x 1 system system 600836 1981-01-01 01:01 libqml_QtQuick_Controls.2_Fusion_qtquickcontrols2fusionstyleplugin_x86.so
-rwxr-xr-x 1 system system 1611660 1981-01-01 01:01 libqml_QtQuick_Controls.2_Imagine_qtquickcontrols2imaginestyleplugin_x86.so
-rwxr-xr-x 1 system system 744164 1981-01-01 01:01 libqml_QtQuick_Controls.2_Material_qtquickcontrols2materialstyleplugin_x86.so
-rwxr-xr-x 1 system system 602016 1981-01-01 01:01 libqml_QtQuick_Controls.2_Universal_qtquickcontrols2universalstyleplugin_x86.so
-rwxr-xr-x 1 system system 652988 1981-01-01 01:01 libqml_QtQuick_Controls.2_qtquickcontrols2plugin_x86.so
-rwxr-xr-x 1 system system 378820 1981-01-01 01:01 libqml_QtQuick_Templates.2_qtquicktemplates2plugin_x86.so
-rwxr-xr-x 1 system system 40492 1981-01-01 01:01 libqml_QtQuick_Window.2_windowplugin_x86.so
Qt 在作为系统应用程序运行时尝试从 /system/lib 加载,所以我需要将它们移到那里(this *** answer 中引用的补丁集已合并)
以下是 logcat 的日志,从我点击启动器中的应用图标到它似乎已终止:
08-17 10:25:34.303 1965 4949 I ActivityTaskManager: START u0 act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=org.qtproject.example.QMLhello/org.qtproject.qt5.android.bindings.QtActivity bnds=[37,1236][238,1560] from uid 10109
08-17 10:25:34.308 1965 2005 E system_server: Invalid ID 0x00000000.
08-17 10:25:34.308 1965 1965 W ActivityManager: Unable to start service Intent act=android.service.appprediction.AppPredictionService cmp=com.google.android.as/com.google.android.apps.miphone.aiai.app.AiAiPredictionService U=0: not found
08-17 10:25:34.308 1965 1965 W RemoteAppPredictionService: could not bind to Intent act=android.service.appprediction.AppPredictionService cmp=com.google.android.as/com.google.android.apps.miphone.aiai.app.AiAiPredictionService using flags 67108865
08-17 10:25:34.308 1965 2298 W InputReader: Device has associated, but no associated display id.
08-17 10:25:34.309 1965 2298 I chatty : uid=1000(system) Binder:1965_6 identical 28 lines
08-17 10:25:34.309 1965 2298 W InputReader: Device has associated, but no associated display id.
08-17 10:25:34.310 4888 4888 W ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@e48f5bf
08-17 10:25:34.314 1965 2298 W InputReader: Device has associated, but no associated display id.
08-17 10:25:34.314 1965 2298 I chatty : uid=1000(system) Binder:1965_6 identical 8 lines
08-17 10:25:34.314 1965 2298 W InputReader: Device has associated, but no associated display id.
08-17 10:25:34.329 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 10108928
08-17 10:25:34.356 4888 4888 E Qt : It looks like app deployed as system app. It may be necessary to specify path to system lib directory using android.app.system_libs_prefix metadata variable in your AndroidManifest.xml
08-17 10:25:34.356 4888 4888 E Qt : Using /system/lib/ as default path
08-17 10:25:34.358 4888 4888 W System : ClassLoader referenced unknown path:
08-17 10:25:34.384 1965 2005 W InputReader: Device has associated, but no associated display id.
08-17 10:25:34.384 1965 2005 I chatty : uid=1000(system) android.anim identical 8 lines
08-17 10:25:34.384 1965 2005 W InputReader: Device has associated, but no associated display id.
08-17 10:25:34.387 4888 4913 W System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Bundle.containsKey(java.lang.String)' on a null object reference
08-17 10:25:34.387 4888 4913 W System.err: at org.qtproject.qt5.android.QtNative$4.run(QtNative.java:495)
08-17 10:25:34.387 4888 4913 W System.err: at org.qtproject.qt5.android.QtThread$2.run(QtThread.java:87)
08-17 10:25:34.387 4888 4913 W System.err: at org.qtproject.qt5.android.QtThread$1.run(QtThread.java:61)
08-17 10:25:34.387 4888 4913 W System.err: at java.lang.Thread.run(Thread.java:919)
08-17 10:25:34.387 4888 4888 W System.err: java.lang.Exception:
08-17 10:25:34.388 4888 4888 W System.err: at org.qtproject.qt5.android.bindings.QtLoader.loadApplication(QtLoader.java:268)
08-17 10:25:34.388 4888 4888 W System.err: at org.qtproject.qt5.android.bindings.QtLoader.startApp(QtLoader.java:505)
08-17 10:25:34.388 4888 4888 W System.err: at org.qtproject.qt5.android.bindings.QtActivityLoader.onCreate(QtActivityLoader.java:166)
08-17 10:25:34.388 4888 4888 W System.err: at org.qtproject.qt5.android.bindings.QtActivity.onCreateHook(QtActivity.java:267)
08-17 10:25:34.388 4888 4888 W System.err: at org.qtproject.qt5.android.bindings.QtActivity.onCreate(QtActivity.java:274)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.Activity.performCreate(Activity.java:7802)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.Activity.performCreate(Activity.java:7791)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)08-17 10:25:34.388 4888 4888 W System.err: at android.os.Handler.dispatchMessage(Handler.java:107)
08-17 10:25:34.388 4888 4888 W System.err: at android.os.Looper.loop(Looper.java:214)
08-17 10:25:34.388 4888 4888 W System.err: at android.app.ActivityThread.main(ActivityThread.java:7356)
08-17 10:25:34.388 4888 4888 W System.err: at java.lang.reflect.Method.invoke(Native Method)
08-17 10:25:34.388 4888 4888 W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
08-17 10:25:34.389 4888 4888 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
08-17 10:25:34.438 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1495040
08-17 10:25:34.449 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.451 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.452 4888 4909 D EGL_emulation: eglMakeCurrent: 0xe3010e40: ver 2 0 (tinfo 0xe2feea20)
08-17 10:25:34.460 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1495040
08-17 10:25:34.464 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 1495040
08-17 10:25:34.466 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.469 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.479 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 10108928
08-17 10:25:34.483 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.489 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.492 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 10108928
08-17 10:25:34.493 4888 4909 D EGL_emulation: eglMakeCurrent: 0xe3010e40: ver 2 0 (tinfo 0xe2feea20)
08-17 10:25:34.499 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.526 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.527 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.530 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.532 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.545 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.546 1754 2456 D gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 10108928
08-17 10:25:34.548 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.561 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.563 4888 4909 D EGL_emulation: eglMakeCurrent: 0xe3010e40: ver 2 0 (tinfo 0xe2feea20)
08-17 10:25:34.565 1755 2673 W EmuHWC2 : validate: layer 19 CompositionType 1, fallback
08-17 10:25:34.569 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.583 1755 2673 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.584 1965 2009 I ActivityTaskManager: Displayed org.qtproject.example.QMLhello/org.qtproject.qt5.android.bindings.QtActivity: +255ms
08-17 10:25:34.586 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.599 1755 2673 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.611 1755 2673 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.616 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.618 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.633 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.634 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.635 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.640 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.649 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.651 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.652 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.655 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.666 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.668 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.670 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.673 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.683 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.685 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.685 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.691 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.699 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.701 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.704 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.709 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.716 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.718 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.721 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.725 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.733 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.735 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.741 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.746 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.750 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.752 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0612d20
08-17 10:25:34.757 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.761 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.766 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.768 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf0613080
08-17 10:25:34.772 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.775 2120 2352 D EGL_emulation: eglMakeCurrent: 0xe2f6dde0: ver 2 0 (tinfo 0xc15443d0)
08-17 10:25:34.783 1755 1755 W EmuHWC2 : validate: layer 20 CompositionType 1, fallback
08-17 10:25:34.786 1755 1755 W EmuHWC2 : No layers, exit, buffer 0xf06130e0
08-17 10:25:34.848 1768 1768 E Layer : [Surface(name=AppWindowToken607c35c token=Token3592dcf ActivityRecord84abe2e u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t8)/@0x2c802ff - animation-leash#0] No local sync point found
08-17 10:25:34.848 1768 1768 E Layer : [Surface(name=AppWindowToken607c35c token=Token3592dcf ActivityRecord84abe2e u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t8)/@0x2c802ff - animation-leash#0] No local sync point found
08-17 10:25:34.848 1768 1768 E Layer : [Surface(name=AppWindowToken8151314 token=Token6bf8967 ActivityRecord6996926 u0 org.qtproject.example.QMLhello/org.qtproject.qt5.android.bindings.QtActivity t11)/@0x8dbcc29 - animation-leash#0] No local sync point found
08-17 10:25:34.848 1768 1768 E Layer : [Surface(name=AppWindowToken8151314 token=Token6bf8967 ActivityRecord6996926 u0 org.qtproject.example.QMLhello/org.qtproject.qt5.android.bindings.QtActivity t11)/@0x8dbcc29 - animation-leash#0] No local sync point found
08-17 10:25:34.850 2955 3141 D EGL_emulation: eglMakeCurrent: 0xe2f75c00: ver 2 0 (tinfo 0xbeb4d200)
08-17 10:25:34.852 2308 2944 D EGL_emulation: eglMakeCurrent: 0xe2f66840: ver 2 0 (tinfo 0xe3005990)
08-17 10:25:34.867 2955 3134 I PBSessionCacheImpl: Deleted sessionId[497328440469] from persistence.
08-17 10:25:34.889 2955 3112 W SearchServiceCore: Abort, client detached.
08-17 10:25:34.898 1768 1768 W SurfaceFlinger: couldn't log to binary event log: overflow.
它在异常中引用的那行代码QtLoader.java line 268,如果“调用”失败,它似乎只是抛出一个空字符串异常,而没有任何关于它调用失败原因的信息。
进一步挖掘,看起来原因来自QtNative.java line 495,它在尝试调用 info.metaData.containsKey 时遇到 NullPointerException。但是我无法理解为什么对于普通应用程序没有失败的系统应用程序会失败。
我还缺少什么?
【问题讨论】:
从:***.com/a/24685920/295004 你复制到/system/priv-app
而不是/system/app
。相关:source.android.com/devices/tech/config/perms-allowlist
@MorrisonChang 啊,是的,也试过了,抱歉应该在问题中提到
【参考方案1】:
我的错误是将库移动到/system/lib
。我相信我可能在必要时盲目地复制了先前答案的所有步骤,并且 Qt 和/或 Android 中可能已经发生了一些变化,这导致了我的问题。
出于我的目的,只需将目录从/data/app/
完全移动 到/system/priv-app
,保留库子目录就足够了。
adb install appname.apk
adb remount
adb shell
cd /data/app
mv appname* /system/priv-app
reboot
QtLoader 能够从/system/lib
加载一些共享库,足以进行下一步。但下一步需要首先将库放在/system/priv-app/org.qtproject.example.QMLhello-LpZtuoO0ejyQPg_I-8pWnQ==/lib/x86
处(至少在x86 模拟器的情况下 - 根据需要替换其他拱门)
否则,它有可能会遇到NullPointerException
并无法启动。
可能的解决方法
在AndroidManifest.xml
中的<application>
下面直接添加一些<meta-data>
详情
这是 QtNative.java 代码的 sn-p,截至 5.15.2 版本的第 489-497 行(添加了行号)
// ...
/* 489 */ File f = new File(nativeLibraryDir + mainLibNameTemplate);
/* 490 */ if (!f.exists())
/* 491 */ try
/* 492 */ ApplicationInfo info = getContext().getApplicationContext().getPackageManager()
/* 493 */ .getApplicationInfo(getContext().getPackageName(), PackageManager.GET_META_DATA);
/* 494 */ String systemLibraryDir = QtNativeLibrariesDir.systemLibrariesDir;
/* 495 */ if (info.metaData.containsKey("android.app.system_libs_prefix"))
/* 496 */ systemLibraryDir = info.metaData.getString("android.app.system_libs_prefix");
/* 497 */ f = new File(systemLibraryDir + mainLibNameTemplate);
// ...
489:当 QtNative.java 去加载主应用程序库时,它首先检查 ./lib/x86
子文件夹,在这种情况下。
492-493:当它找不到时,它会在应用程序清单中查找一些元数据,以查看应用程序是否告诉它去哪里查找。但是,当应用程序级别没有元数据时,对象的metaData
成员为空。
-
不检查 null,因此会抛出
NullPointerException
空指针是怎么产生的?
Qt默认为该项目生成的AndroidManifest.xml(附在下面)不包含任何<meta-data>
直接在<application>
级别下的标签--而是包含在@987654336中@。 loadMainLibrary
函数应该查看 activityInfo
而不是(或除了)applicationInfo
,并事先检查 null。
这似乎是 Qt 中的一个错误,我会据此报告,但 5.15.x 不会再获得任何开源更新。
<?xml version="1.0"?>
<manifest package="org.qtproject.example.QMLhello" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="QMLhello" android:extractNativeLibs="true">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="QMLhello" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<!-- Application arguments -->
<!-- meta-data android:name="android.app.arguments" android:value="arg1 arg2 arg3"/ -->
<!-- Application arguments -->
<meta-data android:name="android.app.lib_name" android:value="QMLhello"/>
<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="1"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="1"/>
<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="jar/QtAndroid.jar:jar/QtAndroidBearer.jar"/>
<meta-data android:name="android.app.static_init_classes" android:value=""/>
<!-- Used to specify custom system library path to run with local system libs -->
<!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<meta-data android:value="@string/unsupported_android_version" android:name="android.app.unsupported_android_version"/>
<!-- Messages maps -->
<!-- Splash screen -->
<!-- Orientation-specific (portrait/landscape) data is checked first. If not available for current orientation,
then android.app.splash_screen_drawable. For best results, use together with splash_screen_sticky and
use hideSplashScreen() with a fade-out animation from Qt Android Extras to hide the splash screen when you
are done populating your window with content. -->
<!-- meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" / -->
<!-- meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" / -->
<!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
<!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
<!-- auto screen scale factor -->
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
<!-- auto screen scale factor -->
<!-- extract android style -->
<!-- available android:values :
* default - In most cases this will be the same as "full", but it can also be something else if needed, e.g., for compatibility reasons
* full - useful QWidget & Quick Controls 1 apps
* minimal - useful for Quick Controls 2 apps, it is much faster than "full"
* none - useful for apps that don't use any of the above Qt modules
-->
<meta-data android:name="android.app.extract_android_style" android:value="default"/>
<!-- extract android style -->
</activity>
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
</application>
</manifest>
【讨论】:
以上是关于如何在 Android 上将 Qt 应用程序安装为系统应用程序?的主要内容,如果未能解决你的问题,请参考以下文章