Android webview cookie возвращает null

Я пытаюсь просто установить и получить cookie внутри webview в android. Я попробовал множество скриптов администратора cookie, чтобы попытаться заставить это работать. У меня включен JavaScript.

При запуске приложения на Samsung S3 и Samsung Galaxy Tab 10.1 файлы cookie не отображаются вообще (android 4.1). Тем не менее, при запуске программного обеспечения на Samsung Galaxy Ace, HTC Desire Z и в эмуляторах Android, файлы cookie устанавливаются и читаются отлично.

При работе веб-просмотр возвращает строку, как ожидалось, когда она не работает, вывод просто «null»; Cookie не имеет значения / не установлен.

В моем конкретном случае также используется скользящий класс навигации, который является расширением Actionbar Sherlock.

Я бы очень признателен за любую помощь, я боролся с этим уже несколько недель. Спасибо.

HTML:

<html> <head> <title> </title> <script> function createCookie(name, value) { var day = (1 * 24 * 60 * 60 * 1000); var date = new Date(); date.setTime(date.getTime() + (20 * 365 * day)); var expires = "; expires=" + date.toGMTString(); document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; document.cookie = name + "=" + value + expires + "; path=/"; } function readCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); } return null; } </script> </head> <body> <h1 class=""> <script type="text/javascript"> createCookie("test", "If this is working, it returns this string. If this is not working, it returns null."); document.write("test: " + readCookie("test")); </script> </body> </html> 

Код Java:

Открытый класс MainActivity расширяет возможности SherlockActivity ISIDNavigationCallback {

 public static final String EXTRA_TITLE = "com.devspark.sidenavigation.sample.extra.MTGOBJECT"; public static final String EXTRA_RESOURCE_ID = "com.devspark.sidenavigation.sample.extra.RESOURCE_ID"; public static final String EXTRA_MODE = "com.devspark.sidenavigation.sample.extra.MODE"; public static String WebLoaded = "0"; public static String page = "signup.php"; private ImageView icon; private SideNavigationView sideNavigationView; private WebView engine; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); icon = (ImageView) findViewById(android.R.id.icon); sideNavigationView = (SideNavigationView) findViewById(R.id.side_navigation_view); sideNavigationView.setMenuItems(R.menu.side_navigation_menu); sideNavigationView.setMenuClickCallback(this); if (getIntent().hasExtra(EXTRA_TITLE)) { String title = getIntent().getStringExtra(EXTRA_TITLE); int resId = getIntent().getIntExtra(EXTRA_RESOURCE_ID, 0); setTitle(title); icon.setImageResource(resId); sideNavigationView.setMode(getIntent().getIntExtra(EXTRA_MODE, 0) == 0 ? Mode.LEFT : Mode.RIGHT); } //test getSupportActionBar().setDisplayHomeAsUpEnabled(true); String domain = "localhost"; CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(true); cookieManager.setCookie(domain, "name=value"); cookieManager.setCookie(domain, "path=/"); cookieManager.setCookie(domain, "HttpOnly"); //enable cookies CookieManager.getInstance().setAcceptCookie(true); //navigates web engine, including on nav click engine = (WebView) findViewById(R.id.web_engine); engine.loadUrl("file:///android_asset/" + page); //enable JavaScript support - disabled by default for some weird reason engine.getSettings().setJavaScriptEnabled(true); engine.setWebViewClient(new WebViewClient()); //disables text selection engine.setOnLongClickListener(new View.OnLongClickListener() { public boolean onLongClick(View v) { return true; } }); } @Override public void onPause() { super.onPause(); engine.getSettings().setJavaScriptEnabled(false); } @Override public void onResume() { super.onResume(); engine.getSettings().setJavaScriptEnabled(true); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: sideNavigationView.toggleMenu(); break; case R.id.mode_left: item.setChecked(true); sideNavigationView.setMode(Mode.LEFT); break; case R.id.mode_right: item.setChecked(true); sideNavigationView.setMode(Mode.RIGHT); break; default: return super.onOptionsItemSelected(item); } return true; } @Override public void onSideNavigationItemClick(int itemId) { switch (itemId) { case R.id.side_navigation_menu_item1: invokeActivity(getString(R.string.title1), R.drawable.ic_android1); page = "index.html"; break; case R.id.side_navigation_menu_item2: invokeActivity(getString(R.string.title2), R.drawable.ic_android2); page = "test.html"; break; case R.id.side_navigation_menu_item3: invokeActivity(getString(R.string.title3), R.drawable.ic_android3); break; case R.id.side_navigation_menu_item4: invokeActivity(getString(R.string.title4), R.drawable.ic_android4); break; case R.id.side_navigation_menu_item5: invokeActivity(getString(R.string.title5), R.drawable.ic_android5); break; default: return; } finish(); } 

Solutions Collecting From Web of "Android webview cookie возвращает null"

После более чем месяца исследования я пришел к выводу, что установка файла cookie в версиях Android больше 2,3 не представляется возможным в веб-просмотре, где файл находится на локальном хосте (читается непосредственно из папки с ресурсами).

Я воспользовался многими альтернативами использованию хранилища файлов cookie, включая использование локального хранилища HTML. Весь вопрос здесь, я убежден, – это безопасность. Если бы я должен был создать файл cookie или localstorage на локальном хосте, другие приложения могли бы получить доступ к этому хранилищу, что является серьезной угрозой безопасности.

Моя конечная проблема заключалась в попытке свести веб-просмотр с двусторонней связью с java, а также иметь место для хранения данных во время процесса. Мое решение состояло в том, чтобы использовать JavascriptInterface

Идея такова:

  • Анализ данных для работы в javascript
  • Javascript вызывает специальную функцию javascript, например «setData (myDataName, myData)»
  • Java имеет функцию, которая слушает это и принимает аргументы, заданные javscript, а также может возвращать значения в javascript.
  • После того как данные анализируются на Java, java хранит это в серии файлов в активах.
  • Когда вызывается функция javascript «getData (myDataName)», данные возвращаются одним и тем же методом Java.

Я нашел это очень полезным: Android JavascriptInterface Documentation , обработка JavascriptInterface в Android 2.3

Единственное крупное «зависание» – это то, что я нашел, было довольно серьезной ошибкой в Android 2.3 (исправлено в версии 3.0), которая эффективно нарушила JavascriptInterface. Вторая ссылка выше описывает наилучшее обходное решение, которое я нашел.

Вот пример того, как работать с двусторонней связью (это очень грязно, но работает):

Пользовательский класс webinterface:

 public class webViewInterface { //@JavascriptInterface //for SDK 12+ public String showToast(String myText) { Toast.makeText(context, myText, Toast.LENGTH_LONG).show(); return myText; } } 

Основной класс: protected void onCreate (Bundle savedInstanceState) {super.onCreate (savedInstanceState);

 setContentView(R.layout.activity_main); engine = (WebView) findViewById(R.id.web_engine); context = this; WebSettings webSettings = engine.getSettings(); webSettings.setJavaScriptEnabled(true); engine.setWebViewClient(new WebViewClient()); engine.loadUrl("file:///android_asset/" + page); boolean javascriptInterfaceBroken = false; try { if (Build.VERSION.RELEASE.startsWith("2.3")) { javascriptInterfaceBroken = true; } } catch (Exception e) { // Ignore, and assume user javascript interface is working correctly. } // Add javascript interface only if it's not broken // @TODO: write the workaround for < 2.3 devices if (!javascriptInterfaceBroken) { engine.addJavascriptInterface(new webViewInterface(), "MainActivityInterface"); } //disables text selection engine.setOnLongClickListener(new View.OnLongClickListener() { public boolean onLongClick(View v) { return true; } }); } 

HTML:

 <html> <head> </head> <body> <input type="button" value="Say hello" onClick="showAndroidToast();" /> <script type="text/javascript"> function showAndroidToast() { document.write(MainActivityInterface.showToast("eureka!")); } </script> </body> </html> 

Я столкнулся с теми же ограничениями. Я загружаю локальные html-файлы из fodler. На эмуляторе 2.2 файлы cookie хранятся и могут быть получены с помощью JavaScript. Тем не менее, тестирование на моем устройстве 4.1, файлы cookie, установленные на локальной странице, не будут сохраняться.

Основываясь на предложениях @ kirgy и @ user3220983, я сделал это, используя интерфейс Javascript.

 webview.addJavascriptInterface(new JavaScriptInterface(this), "Android"); public class JavaScriptInterface { ... @JavascriptInterface public void setCookie(String name, String value) { Editor editor = activity.settings.edit(); editor.putString(name, value); editor.commit(); } @JavascriptInterface public String getCookie(String name) { return activity.settings.getString(name, ""); } @JavascriptInterface public void deleteCookie(String name) { Editor editor = activity.settings.edit(); editor.remove(name); editor.commit(); } 

Примечание: эти функции не обеспечивают полную функциональность печенья (expiration, path), я публикую это как идею хорошей отправной точки.

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

Что-то вроде этого:

 document.setCookie = function(sName,sValue) { var oDate = new Date(); oDate.setYear(oDate.getFullYear()+1); var sCookie = sName.escape() + '=' + escape(sValue) + ';expires=' + oDate.toGMTString() + ';path=/'; document.cookie= sCookie; } 

Удачи, надеюсь, что это сработает!

Я столкнулся с той же проблемой, что и кирги. Я пытался использовать файлы cookie (с javascript) в веб-обзоре Droid, который отображал местный контент. Он не сохранит данные. Тот же код работал отлично, если он запускался с удаленного URL-адреса в том же веб-браузере. Включение файлов cookie в java (с Android CookieManger) не повлияло.

К счастью, я использовал пользовательские функции javascript для инкапсуляции всех моих потребностей в cookie в локальное веб-приложение. Используя интерфейс javascript webview, при работе на дроиде я просто управлял своими файлами в виртуальном режиме, обрабатывая его в java.

Для моих нужд мне требуется только хранение сеанса, поэтому просто поместите данные cookie в java-файл HashMap. Я не беспокоился о сроках годности или долгосрочном хранении. Если вам нужны ваши «виртуальные куки» для реализации этих деталей, не следует слишком сложно разобраться, как только данные будут отправлены, и из java через интерфейс js.