2013-01-09 78 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 –