Phonegap:关闭DroidGap活动后javascript计时器仍在运行

时间:2013-04-09 11:09:55

标签: java javascript android cordova exit

我正在使用Phonegap在Android WebApp中工作。要退出应用程序,我将从JavaScript代码中调用navigator.app.exitApp

我试图找到此方法的文档页面,但它不存在。然后我下载了适用于Android的Phonegap源代码,但是我没有找到该库从本机代码退出应用程序的位置和方式。我没有时间这样做,所以我决定自己测试一下。

我的应用程序有一个DroidGap活动(使用singleInstance标志启动),还有一个服务和一个广播接收器。用户必须能够关闭GUI,但我想保持服务和其他一切运行。所以我想做的只是完成活动,而不是调用System.exit

现在这里有奇怪的部分。我已经在模拟器中对此进行了测试,并且DroidGap活动似乎以我想要的方式关闭(onDestroy被触发)并且服务保持运行。但是,尽管活动已关闭,并且任务管理器中不再显示应用程序图标,但JavaScript计时器仍在运行。我已经三次检查了这个。我想相信活动是在后台,但它不能是:它是作为singleInstance启动的,当我再次打开应用程序时它会显示初始页面(它在不同的页面中关闭)。

为什么会这样?我应该编写插件来直接调用finish活动吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

我一直在调查这几个小时,所以我会在这里发布我的发现。

在每个Android WebApp中,不仅是Phonegap应用程序,每当您拥有WebView时,都会产生两个线程:WebViewCoreThreadWebViewWorkerThread。它们显示在DDMS中。我一直在阅读Android源代码,我已将此线程的创建跟踪到WebViewCore.java文件。显然,每个应用程序进程只启动两个线程,并且它们由应用程序中的每个WebView共享。

恕我直言,在屏幕上使用View意味着产生线程是非常糟糕的设计。如果此字段需要执行像启动线程那样复杂的事情,那么它应该更好地设计为WebViewActivity或WebWiewFragment。在任何情况下,创建线程的类也应该负责在不再需要它时完成它。不幸的是,情况并非如此。

当包含WebView的活动关闭但应用程序进程仍在运行时(可能因为您有其他组件,如服务,或者操作系统尚未杀死它),这些线程将继续运行。核心线程将继续执行您在应用中设置的计时器。再次创建活动时,将重用线程。

作为附注,请注意如何在后台运行javascript代码而不必显示活动。

我尝试了在此问题中公开的常规WevView的一些变通方法:WebView threads never stop (WebViewCoreThread, CookieSyncManager, http[0-3])

但由于某些未知原因,它不适用于Phonegap。我尝试覆盖我的DroidGap子类:

@Override
public void onDestroy(){
    System.out.println("Activity destroyed");

    if(appView != null){ //This is a protected reference to the `CordovaWebView`, extending `WebView`
        //First attempt
        try {
            Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(appView, (Object[]) null);
        } catch (Exception e) {             
            e.printStackTrace();
        } 

        //Second attempt
        appView.pauseTimers();          
    }

    super.onDestroy();
}

所以我最终做的是确保在退出应用程序之前从JavaScript代码中取消所有计时器。但是,人们会期望这在Android操作系统代码中得到修复,或者在Phonegap中修补,因为即使在最好的情况下,这些线程也浪费了在没有显示网页时真正不需要的资源。在最糟糕的情况下,一些与DOM相关的JavaScript代码可能会崩溃。

答案 1 :(得分:0)

你需要在调用navigator.app.exitApp()之前明确地终止计时器。此问题也在here进行了讨论。

希望这有助于......:)