我的情况有点特殊。我有一个前端 QML/Qt UI 和一个用 C# 编写的后端应用程序,我正在开发它们来替换旧软件。我之前使用的是带有多合一 Xamarin UI 的 Android 平板电脑。这个新组合将取代那个应用程序。问题是在旧的 Android 平板电脑上安装新软件,我们需要一些方法来运行我们的 C# 后端,而不必用另一种语言复制它或将它构建到 UI 中。
我去掉了 Xamarin UI 的所有内容,所以现在它只是一个空白的 UI,在项目中有一个前台服务。我测试了在 Xamarin 活动中执行/启动前台服务以确保其正常工作。该服务每秒都会持续发出哔哔声(作为我可以让它工作的概念证明)。
[Service(Exported = true, Name = "com.backend.RUN_BACKEND")]
public class ForegroundBackendService : Service
//This is the function that gets called currently when the intent
//comes in. I create a notification, start foreground service,
//launch the process/task, and then return a sticky result.
public override StartCommandResult OnStartCommand(Intent intent,
StartCommandFlags flags, int startId)
导出的设置应该意味着该服务将可用于Android平板电脑上的任何应用程序。另一个应用程序应该能够使用“com.backend.RUN_BACKEND”名称来执行此前台服务。
Xamarin 项目/应用名为 TestProject。这是在 Android 8.1 最低/8.1 目标上运行(Qt UI 也在那里运行)。
Qt 应用程序是用 Qt 6.5.0 构建的,但似乎大多数示例都有点过时,并且像 QtAndroid 这样的库已被替换。
下面的代码似乎接近我正在寻找的代码,但 QAndroidApplication::androidActivity().object 似乎不再可用。所以我想弄清楚执行服务的新语法是什么。
QAndroidIntent serviceIntent(QAndroidApplication::androidActivity().object(),
"org/qtproject/example/qtandroidservice/QtAndroidService");
QJniObject result = QAndroidApplication::androidActivity().callObjectMethod(
"startService",
"(Landroid/content/Intent;)Landroid/content/ComponentName;",
serviceIntent.handle().object());
从 Qt UI 执行名为“com.backend.RUN_BACKEND”的 ForegroundBackgroundService 的语法/代码是什么?
提前致谢,非常感谢您的帮助!
###编辑/更新:###
所以我找到了一个有用的链接。
链接到我已经遇到过的这个页面,但我现在正在更深入地研究它。
所以现在我想弄清楚等效的语法是什么。我是 Qt/Android/Android 服务的新手,所以也许答案很明显,我只是想念它。
让我困惑的是 QAndroidApplication::androidActivity() 有成员 object() 和 callObjectMethod()。以下是 QNativeInterface::QAndroidApplication 中可用的列表。它不一样,所以我想弄清楚如何编写一段等效的代码。
context() : int
hideSplashScreen(int)
isActivityContext() : bool
runOnAndroidMainThread(const std::function<QVariant ()> &, const
QDeadlineTimer)
: QFuture<QVariant>
sdkVersion() : int
基于此信息,任何人都可以使用新的 QNativeInterface::QAndroidApplication 列出等效的代码吗?
我还在深入研究,希望我能弄明白。
###编辑2###
好吧,我忽略了我之前发布的 QtBug 报告链接上的一些评论。我发现了一些新代码。
QJniObject jClass = QJniObject("poc/dialogue/Hello", "
(Landroid/app/Activity;)V", QtAndroidPrivate::activity());
jClass.callMethod<void ("showDialogue");
//This seems to solve part of the problem
QAndroidIntent serviceIntent =
QAndroidIntent(QtAndroidPrivate::activity(),
"com.example.MyService");
//Now I need some sort of piece of code that is equivalent to this
QJniObject result =
QAndroidApplication::androidActivity().callObjectMethod(
"startService",
"(Landroid/content/Intent;)Landroid/content/ComponentName;",
serviceIntent.handle().object());
我还需要从 Java SDK 执行函数,因此前几行仍然有用。
###编辑 3###
我现在有没有突出显示的代码,所以我认为我正朝着正确的方向前进。
这看起来对吗?
QAndroidIntent serviceIntent =
QAndroidIntent(QtAndroidPrivate::activity(),
"com.example.MyService");
QJniObject startService = QJniObject();
QJniObject intentResult =
startService.callObjectMethod("startService",
"(Landroid/content/Intent;)Landroid/content/ComponentName;",
serviceIntent.handle().object());
上面的代码有没有明显的错误。我现在要测试它,所以我想我会知道的。
###编辑 4###
我正在研究我认为的解决方案。
//I have this line of code but it produces an error
QAndroidIntent serviceIntent =
QAndroidIntent(QtAndroidPrivate::activity(),
"SOB.Bacon.com.backend.RunBackend");
//JNI DETECTED ERROR IN APPLICATION: illegal class name
//SOB.Bacon/com.backend.RunBackend' F zygote : runtime.cc:550]
//(should be of //the form 'package/Class', [Lpackage/Class;' or
'[[B') F zygote : runtime.cc:550] //in call to FindClass
我已经尝试了“SOB.Bacon/com.backend.RunBackend”的所有交互,例如“SOB/Bacon/com/backend/RunBackend”和“SOB.Bacon.com.backend.RunBackend”。似乎没有任何效果。
我知道这项服务有效。我创建了第二个基本的空白 Xamarin 项目,它做了一件简单的事情,项目加载并使用此代码启动另一个应用程序的前台服务。砰,服务开始发出哔哔声,我知道它起作用了。它仅使用包名称“SOB.Bacon”和类名称“com.backend.RunBackend”启动它。所以我应该能够从 Qt 做完全相同的事情。
这是在其他 Xamarin 应用程序中启动导出服务的 Xamarin 代码。只是为了展示我在 Qt 中想要实现的目标。
const string REMOTE_SERVICE_COMPONENT_NAME =
"com.backend.RunBackend";
// This is the name of the service, according the value of
ServiceAttribute.Name
const string REMOTE_SERVICE_PACKAGE_NAME = "SOB.Bacon";
// Provide the package name and the name of the service with a
ComponentName object.
ComponentName cn = new ComponentName(REMOTE_SERVICE_PACKAGE_NAME,
REMOTE_SERVICE_COMPONENT_NAME);
Intent serviceToStart = new Intent();
serviceToStart.SetComponent(cn);
StartForegroundService(serviceToStart);
我不明白为什么 Qt 似乎找不到这个包/服务。它确实存在,所以希望我只是遗漏了一些明显的东西。
任何人都可以阐明这一点吗?
我的意思是在 Qt 中复制上述 Xamarin 代码有多难。我觉得我很亲近。
任何帮助将不胜感激我现在正在兜圈子。