2013-01-09 53 views
6

我有一个Android应用程序,它使用嵌入式PhoneGap WebView。我已经在我的活动中成功实施了CordovaInterface,并且该应用程序启动并执行应有的功能。在嵌入式PhoneGap应用程序中保存和恢复WebView

当我暂停应用程序(切换到其他应用程序或Tab键首页),我保存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")); 
    } 
} 

我方法(在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 [email protected] 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 [email protected] that was originally registered here. Are you missing a call to unregisterReceiver()? 
... 

错误再次启动应用程序时(解决 - 见更新1):

这将导致一个错误,因为的WebView尝试加载的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) 

UPDATE 1:

这两个错误解决了,但换成了新的。

第一个错误是因为未被调用。

第二个错误是由于未设置的CordovaWebView中的字段baseUrl造成的。我目前正试图通过保存最近访问过的网址为SharedPreferences来解决,当onPause()/onSaveInstanceState()发生:

 String url = webView.peekAtUrlStack(); 
     out.putString("url", url); 
     webView.handlePause(true); 

onResume(),我加载URL中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中删除它。

回答

10

与恢复嵌入式CordovaWebView的问题是因为在onPause()onResume()onCreate()onDestroy()CordovaWebView的相互作用没有正确地发生。当开始修复时,restoreState()发生了两次,这导致了进一步的问题。

的onCreate:

下一步恢复状态,电子需要设置CordovaWebView基本URL使用方法loadUrlIntoView()

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()我们需要调用CordovaWebViewhandleResume()

webView.handleResume(true, false); 

结论:

嵌入一个CordovaWebView并且保存和恢复其状态是可能的,但是因为您必须知道很多来自DroidGap & CordovaWebView的内部结构,所以不建议这样做。

我希望我的回答能帮助别人。

+0

可以使用['onPause'](http://docs.phonegap.com/en/1.1.0/phonegap_events_events.md.html#pause)&['onResume'](http:// docs .phonegap.com/en/1.1.0/phonegap_events_events.md.html#resume)方法来自Phone gap。 – GoodSp33d

+0

onCreate和Destroy代码为我工作!谢谢。 peekAtUrlStack方法似乎不在我的cordova库中...我有v2.9.1 –