2013-01-09 5 views
6

Ho un'app per Android che utilizza uno PhoneGap WebView incorporato. Ho implementato con successo CordovaInterface sulla mia attività e l'app si avvia e funziona come dovrebbe.Salvataggio e ripristino di WebView in un'app PhoneGap incorporata

Quando metto in pausa l'applicazione (il passaggio a un altra applicazione o la tabulazione Home), risparmio stato s la WebView' con il metodo saveState, che dovrebbe essere ripristinata quando l'applicazione si avvia di nuovo (questo approccio funziona in un app senza PhoneGap).

Tuttavia, quando l'app si riavvia, provo a ripristinare lo stato (con il metodo restoreState) senza caricare prima un url (poiché desidero utilizzare l'ultimo stato). Ciò causa un errore perché PhoneGap si aspetta che venga caricato un URL (almeno questo è quello che raccolgo dall'eccezione).

La mia domanda è: come posso salvare e ripristinare correttamente lo stato di WebView in un WebGap incorporato di WebGap?

mio onCreate metodo:

@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")); 
    } 
} 

mio metodo (logica simile a onSaveInstanceState):

@Override 
protected void onPause() { 
    super.onPause(); 

    Bundle out = new Bundle(); 
    webView.saveState(out); 

    saveToPreferences(out); 
} 

errore durante la chiusura/app pausa (risolto - vedi aggiornare 1):

Viene visualizzato un errore quando chiudo l'app. Questo è probabilmente legato, ma io non vedo come:

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()? 
... 

errore quando si inizia di nuovo app (risolto - vedere Update 1):

Questo causa un errore, perché il WebView tenta di caricare un uRL che è nullo:

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:

Entrambi gli errori sono risolto ma sostituito da uno nuovo.

Il primo errore era perché webView.handleDestroy() in onDestroy() non è stato chiamato.

Il secondo errore era dovuto al campo baseUrl in CordovaWebView che non è impostato. Attualmente sto cercando di risolvere che salvando l'ultimo URL visitato in SharedPreferences quando onPause()/onSaveInstanceState() si verificano:

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

In onResume(), ho caricare l'URL in SharedPreferences:

if (savedInstanceState != null) { 
     webView.restoreState(savedInstanceState);   
     webView.loadUrlIntoView(savedInstanceState.getString("url")); 
    } 

Ora ho un'altra (brutta) errore. La cosa strana è che l'app si blocca immediatamente (senza notifica). Dopo alcuni tentativi, inizia comunque.Ecco l'errore:

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 
... 

UPDATE 2:

Ripristinare lo stato WebView si è verificato due volte, causando dei problemi. Quindi rimosso da onResume.

risposta

10

I problemi con il ripristino di un incorporato CordovaWebView erano perché le interazioni con il CordovaWebView in onPause(), onResume(), onCreate() e onDestroy() non si è verificato in modo corretto. Quando si inizia a correggere, restoreState() si è verificato due volte che ha causato ulteriori problemi.

onCreate:

Accanto a ripristinare lo stato, e necessario impostare l'URL di base CordovaWebView utilizzando il metodo loadUrlIntoView():

webView.restoreState(savedInstanceState); 
webView.loadUrlIntoView(savedInstanceState.getString("url")); 

OnDestroy:

Dobbiamo eseguire handleDestroy() per pulire tutte le cose relative a PhoneGap, come il PluginManager, i ricevitori broadcast, ...:

@Override 
public void onDestroy() { 
    super.onDestroy(); 

    webView.handleDestroy(); 
} 

onPause:

In onPause(), abbiamo memorizzare lo stato s' il CordovaWebView. Cerchiamo l'ultimo URL registrato e lo memorizziamo in SharedPreferences. Inoltre, è necessario chiamare 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:

In onResume() abbiamo bisogno di chiamare CordovaWebView s' handleResume():

webView.handleResume(true, false); 

Conclusione:

Incorporare un CordovaWebView e salvare e ripristinare il suo stato è possibile, ma poiché è necessario conoscere molti interni da DroidGap , NON è consigliabile farlo.

Spero che la mia risposta aiuti qualcuno.

+0

È possibile utilizzare ['onPause'] (http://docs.phonegap.com/en/1.1.0/phonegap_events_events.md.html#pause) e [' onResume'] (http: // docs .phonegap.com/it/1.1.0/phonegap_events_events.md.html # resume) metodi da Phone gap. – GoodSp33d

+0

il codice onCreate e on Destroy ha funzionato per me! Grazie. il metodo peekAtUrlStack non sembra essere nella mia libreria cordova ... ho la v2.9.1 –