如何从 Qt Android 应用程序在 Xamarin Android 应用程序中执行前台服务

问题描述 投票:0回答:0

我的情况有点特殊。我有一个前端 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 的语法/代码是什么?

提前致谢,非常感谢您的帮助!

###编辑/更新:###

所以我找到了一个有用的链接。

如何在 QT6 中访问 Android 活动

链接到我已经遇到过的这个页面,但我现在正在更深入地研究它。

QAndroid应用程序

所以现在我想弄清楚等效的语法是什么。我是 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 代码有多难。我觉得我很亲近。

任何帮助将不胜感激我现在正在兜圈子。

android qt xamarin java-native-interface android-service
© www.soinside.com 2019 - 2024. All rights reserved.