【问题标题】:Android service crashes when app killed/restarted by the system当应用程序被系统杀死/重新启动时,Android 服务崩溃
【发布时间】:2019-08-06 04:38:19
【问题描述】:

我正在尝试在 Android 上的 nativescript 中制作专门的虚拟助手。为此,我需要一个后台服务不断监听唤醒词。现在我设法提供了一项服务,但是在使用 START_STICKY 杀死应用程序后重新启动它时,它会因com.tns.NativeScriptException: Failed to create JavaScript extend wrapper for class 'tk/ozymandias/ServiceTest/Service' 而崩溃。

这里是服务:

@JavaProxy("tk.ozymandias.ServiceTest.Service")
class Service extends android.app.Service {
    private timerId: number;

    onBind():android.os.IBinder {
        return null;
    }

    onCreate(): void {
        super.onCreate();
        if (!this.timerId) {
            this.timerId = setInterval(() => {
                console.log("PING");
            }, 1000);
        }
    }

    onStartCommand(intent: android.content.Intent, flags: number, startId: number) {
        return android.app.Service.START_STICKY;
    }

    onDestroy(): void {
        super.onDestroy();
        clearInterval(this.timerId);
    }
}

这是堆栈跟踪:

An uncaught Exception occurred on "main" thread.
Unable to create service tk.ozymandias.ServiceTest.Service: com.tns.NativeScriptException: Failed to create JavaScript extend wrapper for class 'tk/ozymandias/ServiceTest/Service'

StackTrace:
java.lang.RuntimeException: Unable to create service tk.ozymandias.ServiceTest.Service: com.tns.NativeScriptException: Failed to create JavaScript extend wrapper for class 'tk/ozymandias/ServiceTest/Service'
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:3349)
    at android.app.ActivityThread.-wrap4(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1677)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
    at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:108)
Caused by: com.tns.NativeScriptException: Failed to create JavaScript extend wrapper for class 'tk/ozymandias/ServiceTest/Service'
    at com.tns.Runtime.createJSInstanceNative(Native Method)
    at com.tns.Runtime.createJSInstance(Runtime.java:778)
    at com.tns.Runtime.initInstance(Runtime.java:751)
    at tk.ozymandias.ServiceTest.Service.onCreate(Service.java:29)
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:3339)
    ... 9 more

您可以看到最小的示例项目here。 要触发错误,您需要实际终止应用程序,使用后退按钮退出就可以了。

编辑:here's a new repo with working code

【问题讨论】:

    标签: android typescript nativescript


    【解决方案1】:

    我不确定您使用的是哪个 Android 版本,但正如 @Bilal 提到的,Android 8 中处理服务的方式已完全改变,因此如果您希望同时支持早期和最新版本,则必须运行特定服务基于版本号。

    以下是从NativeScript Geo Location plugin for fetching location in background复制的示例,您必须遵循类似的内容,并在android 8及更高版本中使用JobService。

    if (application.android) {
        if (device.sdkVersion < "26") {
            (<any>android.app.Service).extend("com.nativescript.location.BackgroundService", {
                onStartCommand: function (intent, flags, startId) {
                    this.super.onStartCommand(intent, flags, startId);
                    return android.app.Service.START_STICKY;
                },
                onCreate: function () {
                    _startWatch();
                },
                onBind: function (intent) {
                    console.log("on Bind Services");
                },
                onUnbind: function (intent) {
                    console.log('UnBind Service');
                },
                onDestroy: function () {
                    console.log('service onDestroy');
                    _clearWatch();
                }
            });
        } else {
            (<any>android.app).job.JobService.extend("com.nativescript.location.BackgroundService26", {
                onStartJob() {
                    console.log('service onStartJob');
                    _startWatch();
                    return true;
                },
                onStopJob(jobParameters: any) {
                    console.log('service onStopJob');
                    this.jobFinished(jobParameters, false);
                    _clearWatch();
                    return false;
                },
            });
        }
    }
    

    【讨论】:

      【解决方案2】:

      希望我的回答能提供一些帮助。

      在 android 8 及以上版本中,服务发生了很大变化。

      1. 需要用前台方法启动服务。

      2. 如果您处于节电模式,电池设置也很重要,因为系统检查您的服务与正常模式不同。

      3. 移动操作系统也有影响,一些中国移动操作系统停止正常应用程序的服务,但不停止市场上流行的应用程序的服务,如whatsapp等。

      【讨论】:

        【解决方案3】:

        所以我在 GitHub 上的 Nick Iliev 的一点帮助下设法解决了这个问题。

        基本上,当您从onStartCommand 返回START_STICKY 然后杀死您的应用程序时, 服务以null 意图重新启动。这就是崩溃的原因。

        您可能应该返回 START_REDELIVER_INTENT 以确保您不会收到 null 意图。但是,您的服务不会自动重启。

        要解决这个问题,您需要一个广播接收器来重新启动您从onDestroy 调用的服务。此外,为确保始终调用onDestroy 并且您的服务不会因内存不足或电池优化而被终止,您需要将您的服务设为前台服务。

        我写了一篇关于这个here的简短文章。

        还有here's a working example repo

        【讨论】:

          【解决方案4】:

          我看到你说

          if (device.sdkVersion < "26")
          

          在 Android 开发者文档中,它说 JobService 是在 API 级别 21 中添加的

          你为什么不把它写成if (device.sdkVersion &lt; "21")

          【讨论】:

            猜你喜欢
            • 2011-04-12
            • 1970-01-01
            • 2023-04-01
            • 1970-01-01
            • 2013-09-19
            • 2016-10-22
            • 1970-01-01
            • 2014-05-27
            相关资源
            最近更新 更多