系统终止/重新启动应用程序时,Android服务崩溃

时间:2019-08-06 04:38:19

标签: android typescript nativescript

我正在尝试在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

4 个答案:

答案 0 :(得分:0)

希望我的回答会有所帮助。

在android版本8及更高版本中,服务已更改很多。

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

  2. 如果您处于省电模式,则电池设置也很重要,它们会系统检查您的服务是否不同于正常模式。

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

答案 1 :(得分:0)

我不确定您使用的是哪个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 :(得分:0)

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

基本上,当您从START_STICKY返回onStartCommand并终止您的应用时, 服务将以null的意图重新启动。那就是飞机坠毁的原因。

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

要解决此问题,您需要一个广播接收器,以重新启动您从onDestroy调用的服务。此外,要确保始终调用onDestroy,并且不会由于内存不足或电池优化而导致服务不被杀死,则需要使服务成为前台服务。

我写了一篇有关此here的简短文章。

here's a working example repo

答案 3 :(得分:0)

我看到你说

if (device.sdkVersion < "26")

在Android Developer文档中,它说JobService是在API级别21中添加的。

为什么没有if (device.sdkVersion < "21")

相关问题