【问题标题】:How to autorun application with background service in Delphi?如何在 Delphi 中使用后台服务自动运行应用程序?
【发布时间】:2015-12-10 19:45:47
【问题描述】:

是否有可能在 Delphi 10 Seattle 中创建一个 android 应用程序(带有后台服务),它会在启动 android 设备后自动启动?

我找到了一个解决方案(Auto start Delphi XE5 Android App after boot),但它是针对Delphi XE5版本的,没有自动启动后台服务的选项。

你们中有人尝试过解决这个问题吗?如果是,请与我们分享您的解决方案?

更新:

我不知道怎么了。

  1. 将广播接收器添加到使用中

  2. 注册广播接收器

    procedure TForm1.CreateBroadcastReceiver;
    begin
      if not Assigned(BroadcastReceiver) then
        begin
          BroadcastReceiver:= TCSBroadcastReceiver.Create(nil);
          BroadcastReceiver.OnReceive:= BroadcastReceiverOnReceive;
          BroadcastReceiver.RegisterReceive;
          BroadcastReceiver.Add('android.intent.action.BOOT_COMPLETED');
        end;
    end;
    
  3. 设置 BroadcastReceiver OnReceive

    procedure TForm1.BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent);
    var
      Inx: JIntent;
    begin
      if JStringToString(csIntent.getAction).Contains('android.intent.action.BOOT_COMPLETED') then
        begin
          Inx := TJIntent.Create;
          Inx.setClassName(csContext, StringToJString('com.embarcadero.firemonkey.FMXNativeActivity'));
          Inx.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK);
          TAndroidHelper.Context.startActivity(Inx);
        end;
    end;
    
  4. 更新AndroidManifest.xml

<receiver android:name="com.embarcadero.rtl.notifications.NotificationAlarm" />
<receiver android:name="com.embarcadero.ProjectBCTA"
  android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
    <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>
  1. 启用RECEIVE_BOOT_COMPLETED权限

  2. 启动了应用程序。

  3. 已停止应用程序。

  4. 重新启动机器。

  5. 重新启动系统后显示错误消息应用程序已停止

我做错了什么。什么是错误?

【问题讨论】:

  • 得知这个Broadcast Receiver不能用,因为它不是服务,只是动态的。
  • 你应该尝试创建自己的jar文件,然后合并到项目中的其他jar文件到Libraries中?见docwiki.embarcadero.com/RADStudio/Seattle/en/…
  • 嗨,KJAN。您是否曾经仅使用 Delphi 代码成功地为 BOOT_COMPLETED 编写了 BroadcastReceiver?我也卡在这里了。您的方法可能会失败,因为需要 BroadcastReceiver 来启动应用程序并创建主表单,但在您的代码中,表单会创建 BroadcastReceiver。

标签: android delphi service autorun delphi-10-seattle


【解决方案1】:

只有在活动/组件明确请求它开始运行时,Android 服务才会开始运行。您仍然需要创建和注册一个BroadcastReceiver 以接收BOOT_COMPLETED 事件(如the XE5 article you linked to 描述)并让您的事件处理程序根据需要启动您的服务:

Creating Android Services | Starting a Service

【讨论】:

  • 我已经创建了广播接收器(使用这个:stackoverflow.com/questions/33609494/…)。我应该如何在系统启动过程中注册BOOT_COMPLETED?比如注册android.intent.action.PHONE_STATE的时候?必须是其他手动编辑的内容吗?
  • 您必须编辑项目的Manifest File 以启用RECEIVE_BOOT_COMPLETED 权限并注册以接收BOOT_COMPLETED 意图。幸运的是,在 IDE 中,您可以进入 Project Options 并启用 Uses Permissions 部分中的 Receive boot completed 选项。但是您必须直接编辑AndroidManifest.xml 才能注册BOOT_COMPLETED。 XE5 文章向您展示了如何做到这一点。
  • 感谢您的建议。明天我会试试这个程序,让你知道这一切是怎么发生的。
  • 所以我尝试创建。重新启动系统后,我得到了错误瞭望塔应用程序停止。看看我的更新答案。错误在哪里?
  • 你告诉我们。调试代码并告诉我们在失败之前它走了多远。 TForm1.CreateBroadcastReceiver() 是否被调用(以及它是从哪里调用的)? TForm1.BroadcastReceiverOnReceive() 被调用了吗? TAndroidHelper.Context.startActivity() 被调用了吗?顺便说一句,所有 FireMonkey 应用程序都使用 FMXNativeActivity,因此您无法使用该类名启动特定应用程序。此外,无论如何,这不是启动服务的正确方法。您在我的回答中阅读了the link 吗?
【解决方案2】:

上周我在工作中使用 Delphi Tokyo 10.2 成功解决了自动启动应用程序的问题。我目前正在考虑启动后台服务,而不是启动后的应用程序作为启动屏幕和应用程序当前在每次设备启动时“弹出”。 (我在研究如何仅启动服务时偶然发现了你的问题,我将在下周末尝试建议的“startService”Java 方法的变体。经历了痛苦之后,我可以减轻你的痛苦。)

基本上,对于较新的编译器,您不再需要 Danny Wind 的文章中修改“Classes.dex”文件的步骤。我在下面描述的内容适用于东京,如果它以同样的方式运作,也可能适用于西雅图,我相信它确实如此。

您不能使用 Delphi 代码注册 BroadcastReceiver。这必须在 Java 中完成,编译后的类在 JAR 中。 Danny Wind 的 Java 包将继续发挥作用,前提是您将问题的第 4 步包含在清单文件中,并将问题的第 5 步包含在项目的 Android 权限中。

顺便说一句,您不应该编辑“AndroidManifest.xml”文件,而应该编辑“AndroidManifest.template.xml”文件。

如果您了解如何为后台服务添加 JAR,您可以按照相同的方法为“BOOT_COMPLETED”添加包含 BroadcastReceiver 的 JAR,方法是转到“Android”目标平台下的“Libraries”文件夹并右键- 鼠标单击并选择“添加”。在这种情况下,您无需添加后台服务 JAR(应该已经存在),而是添加包含 BroadcastReceiver 的 JAR。

为了将 Java 编译成一个类,然后将其包含在一个 JAR 中,我使用以下批处理文件,该文件基于 Danny Wind 的文章和 Delphi 运行的命令来编译它为后台服务(您可以在消息窗口的输出选项卡中看到):

@ECHO OFF
rem Path to Android classes JAR-file
SET ANDROID_JAR="C:\Users\Public\Documents\Embarcadero\Studio\19.0\PlatformSDKs\android-sdk-windows\platforms\android-26\android.jar"
rem Setup parameters
SET SOURCE_FILE=%1
SET JAR_FILE=%2
IF x%2 == x SET JAR_FILE=%SOURCE_FILE%
SET CONFIGURATION=%3
IF x%3 == x SET CONFIGURATION=Debug
rem Ensure directory to hold Java Class files exists for Java Archive
MKDIR JavaClasses\%JAR_FILE% 2> NUL
rem Indicate actions
ECHO .
ECHO Compiling %SOURCE_FILE%.java to %SOURCE_FILE%.class and storing in %CONFIGURATION%\%JAR_FILE%.jar...
ECHO .
rem Compile Java Class file
"%JAVASDK%\javac" -Xlint:deprecation -classpath %ANDROID_JAR% -bootclasspath %ANDROID_JAR% -d JavaClasses\%JAR_FILE% -target 1.6 -g -source 1.6 %SOURCE_FILE%.java
rem Create Java Archive file containing class file
"%JAVASDK%\jar" cf %CONFIGURATION%\%JAR_FILE%.jar -C .\JavaClasses\%JAR_FILE% com
rem Clean-up
SET ANDROID_JAR=""
SET SOURCE_FILE=""
SET JAR_FILE=""
SET CONFIGURATION=""

批处理文件有 3 个参数:

  1. Java 文件的名称,减去任何扩展名。
  2. JAR 文件的名称,减去任何扩展名。
  3. 配置名称(即“Debug”或“Release”)

如果只有一个参数,JAR 文件名将与 Java 文件同名,配置将设置为“Debug”。

如果只有两个参数,配置将设置为“Debug”。

注意,批处理文件现在不对参数进行任何错误检查。

批处理文件在调用“javac”时使用的参数与 Danny Wind 的文章中的参数略有不同。这些我取自 Delphi IDE 使用的东西(如输出选项卡中所示)。

您需要更改设置环境变量“ANDROID_JAR”的行,以获得编译器“android.jar”文件的正确路径。

您还需要将名为“JAVASDK”的环境变量设置为 Java SDK 的“bin”文件夹的路径。在我的机器上是“C:\Program Files\Java\jdk1.8.0_60\bin”。这是我通过“系统属性/高级/环境变量”设置的。

编译和归档后,包含 BroadcastReceiver 的 JAR 将位于“Debug”或“Release”文件夹中,具体取决于您选择的配置。

将包含 BroadcastReceiver 的 JAR 添加到您的项目后,较新版本的 Delphi 会自动将 JAR 文件链接到“Classes.dex”,最终链接到您应用的 APK。

将 APK 部署到您的设备,至少运行一次应用,然后重新启动您的设备。启动完成后,您应该会看到您的应用启动。

【讨论】:

  • 你是对的。不再需要合并 .dex。 :-)
【解决方案3】:

您可以更改 DanyWind 的 BroadcastReceiver 以启动服务而不是应用程序(主机):

package com.dannywind.delphi;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;

public class BootReceiver extends BroadcastReceiver
{

        @Override
        public void onReceive(Context context, Intent intent) 
        {
           Intent launchintent = new Intent();
           launchintent.setClassName(context, "com.embarcadero.services.MyLocationService");           
           context.startService(launchintent);  
        }

} 

您还需要更新 build.bat 中的所有 XE5 路径以指向 D10 或更高版本的等效路径。

Danny 的 build.bat 将 BootReceiver.dex 与默认的 Embaracdero Classes.dex 合并,而不是使用您的应用程序(主机)生成的 classes.dex。必须更正批处理文件中的路径。更详细的描述见我的回答here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多