【问题标题】:How to build an Android app as system service如何将 Android 应用程序构建为系统服务
【发布时间】:2019-08-20 04:14:33
【问题描述】:

我遇到了一个应用程序的问题,该应用程序被构建为作为 Android 服务运行,应该在启动时启动,无需任何用户交互或现有活动。

从其他来源,我们知道这基本上是不可能的:http://commonsware.com/blog/2011/07/13/boot-completed-regression-confirmed.html

目前出于测试目的,该应用程序有一个非常简单的 GUI,它注册了一个广播接收器,如下所示:

public class MyAppReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            Intent serviceIntent = new Intent(context, MyAppService.class);
            context.startService(serviceIntent);
        }
    }
}

如果用户至少启动一次应用程序以允许接收者获取ACTION_BOOT_COMPLETED,这将非常有用。

我们的目标是完全移除 GUI,同时让应用程序在启动时启动,而无需用户执行任何操作。请注意,此软件不会部署在 Play 商店中,而是构建为自定义 AOSP 构建的一部分,不供公众使用。

我找到的唯一解决方案是将应用程序构建为系统服务,方法是将其添加到 Android 应用程序框架中。

参见参考资料:

http://www.androidenea.com/2009/12/adding-system-server-to-android.html http://processors.wiki.ti.com/index.php/Android-Adding_SystemService

但是我对这种可能性的优缺点有点困惑,希望有人能回答以下问题:

1) 应用程序是否需要与整个系统一起构建(来自源的AOSP),因此它不能部署为APK?

2) 有没有什么方法可以在系统建成后更新应用程序(使用 APK)?

3) 以这种方式(作为系统服务)运行应用程序是否可能或方便,纯粹是因为它需要在启动时启动,而不是因为其他原因(例如从中实例化代码)等等)?

应用程序本身并没有什么特别之处 - 它是一个客户端/远程服务器模型,用于报告系统统计数据以供研究。

编辑

为完整性添加清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="org.myapp.myapp"
  android:versionCode="1"
  android:versionName="22.0">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.INTERNET" />

<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">

    <activity android:name="myapp"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <service
        android:name="org.myapp.myappclient.myappservice"
        android:label="myappservice">
        <intent-filter>
            <action android:name="org.myapp.myappclient.myappservice" />
        </intent-filter>
    </service>

    <receiver
        android:enabled="true"
        android:name="org.myapp.myappclient.myappreceiver"
        android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

</application>

【问题讨论】:

  • “请注意,此软件不会部署在 Play 商店中,而是构建为自定义 AOSP 构建的一部分,不供公众使用。” -- 我假设可以将预安装的应用程序设置为已经从停止状态中移出。如果您购买 Android 手机,并查看已安装应用程序列表,则有许多不是“系统服务”的预加载条目(例如,“Basic Daydreams”、“Certificate Installer”、“Face Unlock”) 、“Google 备份传输”、“Nfc 服务”,只是从我坐在这里的 Nexus 4 中挑选一些)。
  • 这是一个很好的观点,我没有考虑过。该应用程序必须安装在 /system/app 下,以避免用户卸载它。我确实从源代码构建了整个系统,但是我还不知道在不间断状态下构建应用程序的最佳方法。我会做更多的研究!
  • 是的,我还不够系统级的人知道你是怎么做到的。可能仅仅在系统分区上就足够了。

标签: java android android-service android-source android-framework


【解决方案1】:

如果你正在修改 AOSP 你可以创建一个“持久化应用”

https://developer.android.com/guide/topics/manifest/application-element#persistent

这会出现在清单中的应用程序标签上

<application
  persistent="true"
  ...
>

应用程序是否应该始终保持运行——如果应该,则为“true”,否则为“false”。默认值为“假”。应用程序通常不应设置此标志;持久性模式仅适用于某些系统应用程序。

它必须是一个系统应用程序才能工作。

它将在启动时启动,任何带有此标志的应用程序都会在从 init 触发 BOOT_COMPLETED 意图之前启动。

好处是:

  • 它会导致应用通过 ActivityManager 保持活动状态
  • 如果应用死机,它将自动神奇地重新启动
  • 生命周期更改不会导致您的应用关闭

然后你可以生成服务,或者做任何你想做的事情。

我确信 5 年后它不会有帮助,但可能会帮助其他人:-)

【讨论】:

    【解决方案2】:
    1. 理论上您应该能够单独部署您的 apk,但您可能仍需要修改启动过程以将您的服务包含到要启动的程序/服务列表中。

    2. 是的,你可以。只需确保使用相同的密钥对应用程序包进行签名即可。

    3. 这取决于。为了确保您的服务在您的用户安装应用程序然后离开它的情况下能够正常运行,是否值得去修改应用程序框架?我想您可以在某处包含一个发行说明,以通知用户该应用在安装后至少运行一次后才能运行。

    更新

    1. 也许你可以让你的 Launcher 应用来处理它。
    2. 我认为这里有些混乱。预装应用不一定是系统应用。如果您的应用程序不需要特殊权限,那么它只是一个预安装的用户应用程序。想想大多数手机都附带 Facebook 或 Youtube,而且这些应用可以在以后更新。

    【讨论】:

    • 1.你认为这会在 init.rc 中吗?我确实有一些通过 init.rc 启动的服务(ADB、SuperSU 等),但它们都引用了 Unix 可执行文件,我找不到太多关于如何在启动时运行 Java 应用程序的信息。我想它必须在加载 Dalvik 之后发生。 2.所以可以更新系统应用程序吗?解决了很多麻烦! 3. 忘了提到用户是孩子,所以我不能依靠他们的行为来运行应用程序/服务,所以真的只要让它工作就可以了!
    【解决方案3】:

    1.不需要创建系统服务,只是一个在后台运行的普通服务,你不需要GUI所以不要使用活动而是服务。 3.如果作为系统服务,当出现错误时,整个系统将被重置。

    【讨论】:

    • 谢谢 我不知道系统服务崩溃时操作系统的行为 - 这绝对是一个缺点。作为对 1. 的回应,如果没有用户至少运行一次服务,它似乎无法工作:vogella.com/tutorials/AndroidBroadcastReceiver/…
    • 这是 在你的 AndroidManifest.xml 中吗?
    • 是的,它在清单中:我将完整的 XML 添加到我的原始帖子中。
    • “我遇到了一个应用程序的问题,该应用程序被构建为作为 Android 服务运行,应该在启动时启动,无需任何用户交互或现有活动。”既然您不需要活动,为什么不尝试只使用服务。并且不要忘记修改 Android.mk 并添加“LOCAL_CERTIFICATE := platform”。
    • 好的,我可以尝试在构建源中包含没有活动的应用程序。值得一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 2018-07-06
    • 1970-01-01
    • 2013-03-17
    • 2019-11-22
    • 2013-04-26
    • 2015-06-14
    相关资源
    最近更新 更多