2017-01-06 7 views
3

У меня есть приложение, которое позволяет пользователям играть в игры онлайн или кэшировать их локально. Когда они конвертируют свою игру в кеш, я не хочу, чтобы они теряли прогресс.Синхронизированный локальный ресурс для веб-виджета Android с онлайн-и автономным контентом

Перед установкой KitKat вы можете установить локальный каталог, но мне нужны более новые телефоны для поддержки этой функции.

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

Невозможно найти замену. В результате, вот два каталога:

[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: 1- Блокировка задачи ввода-вывода на главной нити 2 - Скорее всего, вам придется объединить два файла, а не заменять старый файл более новым. – copolii

ответ

1

Это чувствует себя немного грязный, но он работает (на KitKat и выше)!

LocalStorageCopier класс ниже использует магазин SharedPreferences для отслеживания предметов (не стесняйтесь использовать все, что захотите). Перед загрузке URL (локальный или удаленный) создать экземпляр LocalStorageCopier и добавить его в качестве JavascriptInterface к вашему Webview:

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

Примечание: важно, что Javascript интерфейс добавляется перед загрузкой страница. Я почесывал голову о том, почему «резервное копирование не определено», пока я не переместил этот бит до загрузки URL-адреса (я добавлял его непосредственно перед выполнением резервного копирования).

Теперь вам нужно всего лишь связать резервную копию и восстановить действия.

Резервное копирование: Как вы упомянули выше, метод является хорошим местом для восстановления этой информации. В соответствующем месте в вашем добавить код ниже:

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

где BACKUP_JAVASCRIPT является "(function() { console.log('backing up'); backup.clear(); for (var key in localStorage) { backup.set(key, localStorage.getItem(key)); }})()"

Так что теперь каждый раз, когда ваша деятельность приостановлена, ваша localStorage резервное копирование.

Восстановление выполнено очень похоже. Вам необходимо инициировать действие восстановления после загрузки страницы. Здесь вводится класс WebClient (код ниже). После того, как страница будет загружена, вам необходимо захватить все предметы в вашем экземпляре LocalStorageCopier и поместить их в localStorage.Javascript для RESTORE_JAVASCRIPT является: "(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));}})()"

LocalStorageCopier

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); 
    } 
} 
0

Возможно, используя символические ссылки, обе версии WebView будут использовать один и тот же файл:

Creating SymLinks in Android

 Смежные вопросы

  • Нет связанных вопросов^_^