我有一个Android应用,它使用嵌入式PhoneGap WebView
。我已经在我的活动上成功实施了CordovaInterface
,应用程序启动并运行应该如何运行。
当我暂停应用程序(切换到其他应用程序或标签主页)时,我使用WebView
方法保存saveState
的状态,应用程序再次启动时应恢复此状态(此方法适用于没有PhoneGap
)的应用。
然而,当应用程序再次启动时,我尝试恢复状态(使用restoreState
方法)而不首先加载URL(因为我想使用最后一个状态)。这会导致错误,因为PhoneGap期望加载一个url(至少这是我从异常中收集的内容)。
我的问题是:如何在嵌入式PhoneGap WebView中正确保存和恢复WebView的状态?
我的onCreate
方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (CordovaWebView) findViewById(R.id.webView);
if (savedInstanceState == null) {
savedInstanceState = restoreFromPreferences();
}
if (savedInstanceState == null) {
webView.loadUrl("file:///android_asset/www/index.html");
} else {
webView.restoreState(savedInstanceState);
webView.loadUrlIntoView(savedInstanceState.getString("url"));
}
}
我的onPause
方法(onSaveInstanceState
中的类似逻辑):
@Override
protected void onPause() {
super.onPause();
Bundle out = new Bundle();
webView.saveState(out);
saveToPreferences(out);
}
关闭/暂停应用时出错(已解决 - 请参阅更新1):
当我关闭应用时,我收到了错误消息。这可能是相关的,但我不知道如何:
01-09 11:44:50.181: E/ActivityThread(2068): Activity my.package.MainActivity has leaked IntentReceiver org.apache.cordova.NetworkManager$1@a6bc4020 that was originally registered here. Are you missing a call to unregisterReceiver()?
01-09 11:44:50.181: E/ActivityThread(2068): android.app.IntentReceiverLeaked: Activity my.package.MainActivity has leaked IntentReceiver org.apache.cordova.NetworkManager$1@a6bc4020 that was originally registered here. Are you missing a call to unregisterReceiver()?
...
再次启动应用时出错(已解决 - 请参阅更新1):
这会导致错误,因为WebView会尝试加载一个null的URL:
01-09 11:38:22.813: E/AndroidRuntime(1979): FATAL EXCEPTION: main
01-09 11:38:22.813: E/AndroidRuntime(1979): java.lang.NullPointerException
01-09 11:38:22.813: E/AndroidRuntime(1979): at java.lang.String.indexOf(String.java:994)
01-09 11:38:22.813: E/AndroidRuntime(1979): at org.apache.cordova.CordovaWebView.loadUrlNow(CordovaWebView.java:499)
01-09 11:38:22.813: E/AndroidRuntime(1979): at org.apache.cordova.CordovaWebView.loadUrl(CordovaWebView.java:384)
01-09 11:38:22.813: E/AndroidRuntime(1979): at org.apache.cordova.CordovaWebViewClient.onPageFinished(CordovaWebViewClient.java:298)
01-09 11:38:22.813: E/AndroidRuntime(1979): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:327)
01-09 11:38:22.813: E/AndroidRuntime(1979): at android.os.Handler.dispatchMessage(Handler.java:99)
01-09 11:38:22.813: E/AndroidRuntime(1979): at android.os.Looper.loop(Looper.java:137)
01-09 11:38:22.813: E/AndroidRuntime(1979): at android.app.ActivityThread.main(ActivityThread.java:4745)
01-09 11:38:22.813: E/AndroidRuntime(1979): at java.lang.reflect.Method.invokeNative(Native Method)
01-09 11:38:22.813: E/AndroidRuntime(1979): at java.lang.reflect.Method.invoke(Method.java:511)
01-09 11:38:22.813: E/AndroidRuntime(1979): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-09 11:38:22.813: E/AndroidRuntime(1979): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-09 11:38:22.813: E/AndroidRuntime(1979): at dalvik.system.NativeStart.main(Native Method)
更新1:
两个错误都已解决,但已被新错误取代。
第一个错误是因为webView.handleDestroy()
中的onDestroy()
未被调用。
第二个错误是由baseUrl
中未设置的CordovaWebView
字段引起的。目前,我正在尝试通过在SharedPreferences
发生时将上次访问的网址保存到onPause() / onSaveInstanceState()
来解决此问题:
String url = webView.peekAtUrlStack();
out.putString("url", url);
webView.handlePause(true);
在onResume()
中,我在SharedPreferences
中加载了网址:
if (savedInstanceState != null) {
webView.restoreState(savedInstanceState);
webView.loadUrlIntoView(savedInstanceState.getString("url"));
}
现在我得到了另一个(讨厌的)错误。奇怪的是,应用程序立即崩溃(没有通知)。经过几次尝试后,无论如何都会启动。这是错误:
01-09 15:11:19.869: A/libc(3392): Fatal signal 11 (SIGSEGV) at 0x00000008 (code=1), thread 3404 (WebViewCoreThre)
01-09 15:11:19.925: I/ActivityManager(281): Displayed my.package/.MainActivity: +197ms
01-09 15:11:19.973: I/DEBUG(86): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
01-09 15:11:19.973: I/DEBUG(86): Build fingerprint: 'generic/vbox86tp/vbox86tp:4.1.1/JRO03L/eng.dan.20121106.232935:userdebug/test-keys'
01-09 15:11:19.973: I/DEBUG(86): pid: 3392, tid: 3404, name: WebViewCoreThre >>> my.package <<<
01-09 15:11:19.973: I/DEBUG(86): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000008
01-09 15:11:20.249: I/DEBUG(86): eax 00000000 ebx b6b61c98 ecx 00000000 edx 00000001
...
更新2:
恢复WebView状态两次,这导致了问题。因此将其从onResume
删除。
答案 0 :(得分:10)
恢复嵌入式CordovaWebView
的问题是因为与CordovaWebView
,onPause()
,onResume()
和onCreate()
中onDestroy()
的互动确实存在没有正确发生。当开始修复时,restoreState()发生了两次,这引起了进一步的问题。
<强>的onCreate:强>
在恢复状态之后,需要使用方法loadUrlIntoView()
设置CordovaWebView基本网址:
webView.restoreState(savedInstanceState);
webView.loadUrlIntoView(savedInstanceState.getString("url"));
<强>的onDestroy:强>
我们需要执行handleDestroy()
来清理所有与PhoneGap相关的东西,比如PluginManager,广播接收器......:
@Override
public void onDestroy() {
super.onDestroy();
webView.handleDestroy();
}
<强>的onPause:强>
在onPause()
中,我们存储CordovaWebView
的状态。我们查找最后一个已注册的网址,然后将其存储在SharedPreferences
中。此外,还需要调用handlePause()
。
@Override
protected void onPause() {
super.onPause();
String url = webView.peekAtUrlStack();
webView.handlePause(true);
Bundle out = new Bundle();
webView.saveState(out);
out.putString("url", url);
saveToPreferences(out);
}
<强>的onResume:强>
在onResume()
我们需要致电CordovaWebView
的{{1}}:
handleResume()
<强>结论:强>
嵌入webView.handleResume(true, false);
并保存并恢复其状态是可能的,但是因为你必须知道来自CordovaWebView
&amp;的许多内部成员。 DroidGap
,建议不要这样做。
我希望我的回答会对某人有所帮助。