2017-01-06 4 views
3

私は、ユーザーがオンラインでゲームをプレイしたり、ローカルにキャッシュするアプリを持っています。彼らがゲームをキャッシュに変換するとき、私は彼らが進歩を失うことを望んでいません。オンラインとオフラインのコンテンツを含むAndroid WebViewsの同期ローカルストア

KitKatに入る前に、localstorageディレクトリを設定することができましたが、この機能をサポートするには新しい電話が必要です。

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { 
    playingField.getSettings().setDatabasePath("/data/data/" + playingField.getContext().getPackageName() + "/databases/"); 
} 

置き換えの方法が見つかりません。結果として、ここに2つのディレクトリがあります:

[email protected]:/data/data/com.myapp.android/app_webview/Local Storage # 
ls -la 
total 80 
drwx------ 2 u0_a165 u0_a165 4096 2017-01-06 11:51 . 
drwxrwx--x 4 u0_a165 u0_a165 4096 2017-01-06 11:41 .. 
-rw------- 1 u0_a165 u0_a165 4096 2017-01-06 11:51 file__0.localstorage 
-rw------- 1 u0_a165 u0_a165 0 2017-01-06 11:51 file__0.localstorage-journal 
-rw------- 1 u0_a165 u0_a165 4096 2017-01-06 12:02 http_cdn.myapp.com_0.localstorage 
-rw------- 1 u0_a165 u0_a165 0 2017-01-06 12:02 http_cdn.myapp.com_0.localstorage-journal 

誰でもこの問題を解決しましたか?

アクティビティのonPause()の間にファイルを同期しようとするかもしれませんが、より洗練されたソリューション(統合ストレージなど)があるかどうかを知りたいと思います。おそらく、シンボリックリンクを使用して

+0

onPause同期に問題がいくつかあります:メインスレッド2にIOのタスクをブロック1- - 古いファイルを新しいファイルに置き換えるのではなく、2つのファイルをマージする必要があります。 – copolii

答えて

1

これは少し汚いを感じているが、それは(KitKat以降に)動作します!

下記のクラスはSharedPreferencesストアを使用してアイテムを追跡します(代わりに他のものを自由に使用してください)。あなたがLocalStorageCopierのインスタンスを作成し、あなたのWebViewにJavascriptInterfaceとして追加(ローカルまたはリモート)のURLをロード前

webView.setWebViewClient(new WebClient()); 
storageBackup = new LocalStorageCopier(someContext, someId); 
webView.addJavascriptInterface(storageBackup, "backup"); 
webView.loadUrl (someUrl); 

注: javascriptのインタフェースをロードする前に追加されていることが重要ですページ。私はこのビットをURLをロードする前に移動するまで(私はバックアップを実行する直前に追加していた)、なぜ "バックアップが未定義である"のかについて頭を悩ましていました。

バックアップバックアップの復元アクションを結びつけるだけで済みます。

バックアップ:上記のとおり、メソッドは、このようなものをバックアップするのに適しています。あなたの内の適切な場所に以下のコードを追加します。BACKUP_JAVASCRIPT"(function() { console.log('backing up'); backup.clear(); for (var key in localStorage) { backup.set(key, localStorage.getItem(key)); }})()"

ある場合、すべての時間があなたの活動が一時停止されている

webView.evaluateJavascript(BACKUP_JAVASCRIPT, new ValueCallback<String>() { 
     @Override public void onReceiveValue(String s) { 
      LOG.d("Backed up."); 
     } 
    }); 

をだから今、あなたのlocalStorageがバックアップされます。

復元は非常によく似た方法で行われます。ページがロードされた後にリストア・アクションを開始する必要があります。これは、WebClientクラス(下のコード)が入る場所です。ページの読み込みが完了したら、LocalStorageCopierインスタンス内のすべてのアイテムを取得してlocalStorageに配置する必要があります。RESTORE_JAVASCRIPTのためのjavascriptは次のとおりです。LocalStorageCopier "(function(){console.log('Restoring'); backup.dump(); var len = backup.size(); for (i = 0; i < len; i++) { var key = backup.key(i); console.log(key); localStorage.setItem(key, backup.get(key));}})()"

public static class LocalStorageCopier { 
    private final SharedPreferences store; 
    private String[] keys = null; 
    private String[] values = null; 

    private boolean dumped = false; 

    LocalStorageCopier(final Context context, final String id) { 
     store = context.getSharedPreferences(id, Context.MODE_PRIVATE); 
    } 

    @JavascriptInterface 
    public synchronized void dump() { 
     if (dumped) throw new IllegalStateException("already dumped"); 
     final Map<String, ?> map = store.getAll(); 
     final int size = map.size(); 
     keys = new String[size]; 
     values = new String[size]; 

     int cur = 0; 

     for (final String key : map.keySet()) { 
      keys[cur] = key; 
      values[cur] = (String) map.get(key); 
      ++cur; 
     } 

     dumped = true; 
    } 

    @JavascriptInterface 
    public synchronized int size() { 
     if (!dumped) throw new IllegalStateException("dump() first"); 
     return keys.length; 
    } 

    @JavascriptInterface 
    public synchronized String key(final int i) { 
     if (!dumped) throw new IllegalStateException("dump() first"); 
     return keys[i]; 
    } 

    @JavascriptInterface 
    public synchronized String value(final int i) { 
     if (!dumped) throw new IllegalStateException("dump() first"); 
     return values[i]; 
    } 

    @JavascriptInterface 
    public synchronized String get(final String key) { 
     return store.getString(key, null); 
    } 

    @JavascriptInterface 
    public synchronized void set(final String key, final String value) { 
     if (dumped) throw new IllegalStateException("already dumped"); 
     store.edit().putString(key, value).apply(); 
    } 

    @JavascriptInterface 
    public synchronized void clear() { 
     store.edit().clear().apply(); 
     keys = null; 
     values = null; 
     dumped = false; 
    } 

    @Override public synchronized String toString() { 
     return store.getAll().toString(); 
    } 
} 

のWebClient

class WebClient extends WebViewClient { 
    @Override public void onPageFinished(WebView view, String url) { 
     LOG.d("Page finished. Restoring storage."); 

     view.evaluateJavascript(RESTORE_JAVASCRIPT, new ValueCallback<String>() { 
      @Override public void onReceiveValue(String s) { 
       LOG.d("Restored."); 
      } 
     }); 

     super.onPageFinished(view, url); 
    } 
} 
関連する問題