Подробно о webview в android: что, как и почему
Чаще всего для работы с простыми html-страницами используется виджет TextView. В этом случае мы можем реализовать статический метод fromHtml(), который принадлежит утилитному HTML классу для парсинга строк с html кодом и дальнейшим его отображением в TextView.
Виджет TextView обеспечивает простое форматирование для стилей (жирный, курсив), шрифтов, различным цветов, гиперссылок и т.д.
Что такое webview?
WebView
, как мы уже говорили, это WebView
– представление, которое отображает веб-страницы.
Оно представлено классом WebView. Этот класс гораздо мощнее, чем вы можете подумать. При этом он очень прост и понятен в использовании и предоставляет вам абстракции, на которые вы можете опираться.
Именно этот класс является основой, на которой вы можете создать свой собственный веб-браузер или просто отобразить онлайн-контент в рамках вашей Активности. WebView использует механизм рендеринга WebKit для отображения веб-страниц и включает методы, позволяющие:
- перемещаться вперед и назад по истории
- увеличивать и уменьшать масштаб.
- выполнять текстовый поиск и многое другое.
WebView является очень мощным средством, поскольку он предоставляет вам возможность писать приложения на таких языках, как Javascript и разметка HTML. Существует множество фреймворков, которые используют эту возможность, позволяя вам писать приложения на технологиях HTML5. Вы даже можете превратить свой сайт, например, сайт wordpress, в приложение для android.
Почему webview?
WebView – это, вероятно, один из самых практичных, простых в использовании, но недостаточно используемых классов в android. Это потому, что он позволяет создавать приложения для android с помощью HTML, CSS и Javascript. Я бы понял, если бы его не использовали так часто, если бы он не мог выполнять Javascript или рендерить CSS. Однако он делает все это.
Это дает мощные возможности, поскольку HTML, CSS и Javascript – простые в использовании, популярные технологии, используемые в пользовательских интерфейсах почти каждого веб-приложения или веб-сайта, который вы когда-либо посещали. Более того, существуют сотни фреймворков/библиотек для этих технологий, которые предоставляют мощные виджеты и абстракции. К ним относятся jQuery, Vue.js, Angular, React.js, Bootstrap, materializecss, UIKit и др.
Вы можете легко создать простое веб-приложение на стороне клиента, которое может взаимодействовать с технологиями на стороне сервера, такими как Node.js и PHP, и поместить его в папку assets. Затем используйте WebView для его загрузки.
Однако вы должны убедиться, что Javascript включен. Я понимаю, что это не так мощно, как иметь полноценное Java-приложение, написанное на Java, Kotlin или C#, однако для начинающих вы быстро создадите свое первое приложение, которое сможете показать друзьям, продолжая свое образование.
"authorization required" in webview
I am trying to access a webpage after successfuly loging in, where i get the username and password (from the EditTexts in my app “user = (EditText) findViewById(R.id.user);” and “pass = (EditText) findViewById(R.id.pass);” ) and POST it to server.
The problem is that the webview shows the text “Authorization Required…. ” (after loging in successfuly) only on the phones/tablets that have android 4.2.2 but on 4.4.2, 4.4.4 and 5.0.1 works fine (shows the page intended).
I am running out of ideas and need help. Chould you guys help me? Thank you in advance.
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("user", user.getText().toString()));
nameValuePairs.add(new BasicNameValuePair("password", pass.getText().toString()));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "utf-8"));
httppost.addHeader("Authorization", "Basic BLA123BLA23BLA32343LSJ");
// Execute HTTP Post Request
response = httpclient.execute();
//WebView
webview_asd = new WebView(MainScreen.this);
webview_asd = (WebView) findViewById(R.id.webview_asd);
webview_asd.getSettings().setLoadsImagesAutomatically(true);
webview_asd.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
webview_asd.setWebViewClient( new WebViewClient() );
webview_asd.getSettings().setJavaScriptEnabled(true);
CookieSyncManager.createInstance (webview_asd.getContext());
CookieSyncManager.getInstance().sync();
cookies = ((AbstractHttpClient) httpclient).getCookieStore().getCookies();
if(cookies != null)
{
for(Cookie cookie : cookies)
{
cookieString = cookie.getName() "=" cookie.getValue() "; domain=" cookie.getDomain();
CookieManager.getInstance().setCookie(cookie.getDomain(), cookieString);
}
}
CookieSyncManager.getInstance().sync();
webview_asd.loadURL(URL);
webview_asd.setVisibility(View.VISIBLE);
The webview page shows’s “Authorization Required. This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials(e.g., bad password), or your browser doesn’t understand how to supply the credentials required.”
Later edit:
Just figured out that 4.2.2 doesn’t support HTML5 and that’s why i got this problem.
Android WebView – загрузка из URL, строк и папки активов
Android WebView
– загрузка из URL, строк и папки активов.
WebView – это один из тех классов, которые существуют в android с самого начала.
Добавлен в API уровня 1, находится в пакете android.webkit. Он используется для отображения веб-контента прямо внутри активности. Это делает его очень мощным и может быть использовано для создания даже базового работающего браузера. Это все еще представление, поэтому мы можем просто перетащить его из палитры в наш макет.
- URL online.
- Локальная папка
Assets
. String
в java-коде.
Часто используемые параметры `WebView
Вот некоторые часто используемые настройки WebView. Давайте инкапсулируем их в простой статический метод, который затем можно легко использовать повторно.
// Commonly used WebViewSetting
public static void initWebSetting(WebView webView) {
WebSettings setting = webView.getSettings();
setting.setJavaScriptEnabled(true);
setting.setAllowFileAccess(true);
setting.setAllowFileAccessFromFileURLs(true);
setting.setAllowUniversalAccessFromFileURLs(true);
setting.setAppCacheEnabled(true);
setting.setDatabaseEnabled(true);
setting.setDomStorageEnabled(true);
setting.setCacheMode(WebSettings.LOAD_DEFAULT);
setting.setAppCachePath(webView.getContext().getCacheDir().getAbsolutePath());
setting.setUseWideViewPort(true);
setting.setLoadWithOverviewMode(true);
setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
setting.setAllowFileAccessFromFileURLs(true);
}
}
Этот метод принимает объект WebView. Сначала мы получаем настройки webview с помощью метода getSettings класса WebView. Затем мы включаем javascript с помощью метода setJavaScriptEnabled(). Большинство этих методов настроек принимают булево значение для включения или отключения различных настроек.
Как создать пользовательский WebView
Мы хотим создать пользовательский веб-вид, который можно использовать в NestedScrollView.
import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.webkit.WebView;
public class MyWebView extends WebView {
public MyWebView(Context context) {
super(context);
}
public MyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//Check pointer index to avoid -1 (error)
if (MotionEventCompat.findPointerIndex(event, 0) == -1) {
return super.onTouchEvent(event);
}
if (event.getPointerCount() >= 1) {
requestDisallowInterceptTouchEvent(true);
} else {
requestDisallowInterceptTouchEvent(false);
}
return super.onTouchEvent(event);
}
@Override
protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
requestDisallowInterceptTouchEvent(true);
}
}
Activitymain.xml
- Шаблон макета.
- Содержит наш
ContentMain.xml
. - Также определяет
appbarlayout
,toolbar
, а такжеfloatingaction buttton
.
Androidmanifest.xml
- Файл
Android Manifest
. - Добавьте разрешение на интернет, так как мы будем получать веб-страницу также по url.
Build.gradle
- Обычно в проектах android есть два файла
build.gradle
. Один из них – этоbuild.gradle
уровня приложения, а другой –build.gradle
уровня проекта. Уровень app принадлежит папке app, и именно там мы обычно добавляем наши зависимости и указываем компилируемые и целевые sdks. - Также добавляем зависимости для библиотек AppCompat и Design support.
- Наша
MainActivity
будет происходить от AppCompatActivity, а также мы будем использовать плавающую кнопку действия из библиотек поддержки дизайна.
dependencies {
implementation 'com.android.support:appcompat-v7:26. '
implementation 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
implementation 'com.android.support:design:26. '
testImplementation 'junit:junit:4.12'
}
Contentmain.xml
- Макет контента.
- Определяет представления и виджеты, которые будут отображаться внутри
MainActivity
. - В данном случае это простое веб-представление.
Mainactivity.java
- Launcher
activity
. - ActivityMain.xml раздувается как contentview для этой
активности
. - Мы инициализируем представления и виджеты внутри этой
активности
. - Мы переключаемся между пунктами меню на нашей панели инструментов, выбирая загрузку из url, активов или
строки
.
Menu_main.xml
- Мы будем переключаться между пунктами меню на нашей панели инструментов.
- Давайте определим это в
menu_main.xml
внутри каталога меню.
Webview определение api
WebView – это конкретный класс, находящийся в пакете android.webkit. Он происходит от класса android.widget.AbsoluteLayout и реализует несколько интерфейсов, как показано ниже:
public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener
Вот иерархия наследования:
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AbsoluteLayout
↳ android.webkit.WebView
Быстрые примеры webview и howto’s
Давайте рассмотрим быстрые примеры для нашего класса webview. Позже мы рассмотрим, как написать полноценное приложение.
Загрузка контента в webview: источники и способы
Кроме перехода по ссылкам в WebView есть еще несколько способов загрузить контент, который предоставляется по средствам вызова метода loadUrl():
Также есть метод loadData(), который принимает в параметры строку с html-кодом, например:
Использованные инструменты
Этот пример был написан с использованием следующих инструментов:
- Windows 8
- IDE
AndroidStudio
- Genymotion Emulator
- Язык: Java
В этом проекте не использовались сторонние библиотеки.
Перейдем непосредственно к исходному коду.
Как обрабатывать базовую аутентификацию в webview
Я знаю, что это старый, но добавление здесь другого подхода, поскольку приведенные выше (с использованием onReceivedHttpAuthRequest) не сработали для меня. В частности, некоторые веб-страницы не запрашивают у пользователя простую аутентификацию, они просто перенаправляют на экран входа в систему. В моем тестировании Grafana по умолчанию имеет такое поведение.
Поэтому вместо этого я добавил заголовок HTTP Basic auth, используя следующий код:
HashMap<String, String> headers = new HashMap<>();
String basicAuthHeader = android.util.Base64.encodeToString((username ":" password).getBytes(), android.util.Base64.NO_WRAP);
headers.put("Authorization", "Basic " basicAuthHeader);
webView.loadUrl(url, headers);
Это должно обойти приглашение аутентификации и просто установить учетные данные автоматически. Надеюсь, это поможет кому-то найти другое решение.
Кроме того, для тех, кто надеется использовать шаблон URL-адреса «https: // username: password @ url» – это устарело, и я думаю, что большинство браузеров проигнорируют его и выбросят учетные данные.
редактировать
Я пришел к выводу, что мое вышеупомянутое решение работает только для первого запроса и никаких последующих запросов после загрузки страницы (т.е. для любых дополнительных загруженных ресурсов).
Чтобы все последующие запросы работали, мне пришлось переопределить следующую функцию для веб-клиента:
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request){
if (username != null && password != null && username.length() > 0 && password.length() > 0) {
try {
OkHttpClient client = new OkHttpClient();
Request.Builder newRequestBuilder = new Request.Builder()
.url(request.getUrl().toString());
// add headers
Map<String, String> currentHeaders = request.getRequestHeaders();
for (String header : currentHeaders.keySet()){
newRequestBuilder.addHeader(header, currentHeaders.get(header));
}
String basicAuthHeader = android.util.Base64.encodeToString((username ":" password).getBytes(), android.util.Base64.NO_WRAP);
newRequestBuilder.addHeader("Authorization", "Basic " basicAuthHeader);
//make request
Request newRequest = newRequestBuilder.build();
Response response = client.newCall(newRequest).execute();
// respond with content
return new WebResourceResponse(response.header("content-type"), response.header("content-encoding", "utf-8"), response.body().byteStream());
} catch (Exception e) {
// if an exception occurs, just make a default request
return null;
}
} else {
// if no username and password, then make a default request
return null;
}
}
К сожалению, этот код не будет перехватывать запросы POST, а только запросы GET, что ограничивает ваши возможности с ним.
Кроме того, в приведенный выше код должна быть добавлена некоторая логика для проверки того, что домен первоначального запроса совпадает с доменом перехваченных запросов перед присоединением заголовков авторизации. В противном случае заголовок авторизации будет отправлен со всеми запросами, которые могут непреднамеренно отправить его в другой домен (например, загрузка ресурсов из CDN).
Навигация внутри android webview: нажатие кнопок вперед и назад
Если в разрабатываемом нами приложении нажать кнопку назад, то мы увидим, что приложение возвращается в главный экран, даже если мы осуществлять навигацию через несколько страниц внутри самого WebView. Чтобы использовать историю просмотра ссылок внутри WebView при нажатии кнопки назад, мы должны изменить переопределить функцию этой кнопки:
Мы переопределили метод onKeyDown() и теперь он сначала проверяет, что WebView может вернуться на предыдущую ссылку, потому что WebView поддерживает историю просмотра как обычный браузер. Если в истории ссылок нет, то нажатие на кнопку назад будет работать по умолчанию, то есть выходить из приложения.
Ниже весь код MainActivity с указанными выше функциями:
Теперь запустите ваше приложение и переходите по ссылкам внутри сайта. Вы увидите, что все переходы происходят внутри приложения:
А все нажатия на ссылки, которые ведут на другие сайты спрашивают каким приложением открыть ссылку:
Общие вопросы по этому примеру.
- Что такое
WebView
? - Как загрузить сайт из url в webview.
- Как загрузить html из
assets
frolder в webview. - Как загрузить html
строку
в webview. - Как использовать webview в android
activity
.
Руководство по работе с webview
Ниже представлен пример работы с макетом, установкой виджета в коде и обзор наиболее полезных методов при работе с WebView в Android.
1. Установка WebView в макете
Компонент WebView вставляется в тот файл XML-макета, где мы хотим видеть виджет WebView. Давайте создадим простой Hello World проект на Android и посмотрим его работу в макете activity_main.xml:
2. Инициализируем Android WebView в коде
Компонент WebView инициализируется в классе MainActivity , с помощью идентификатора, ранее определенного в activity_main.xml:
3. Используем метод loadUrl()
Установка webviewclient
Установка WebViewClient нужна для того, чтобы пользователь нажимал на ссылку внутри веб-страницы нашего приложения и эта ссылка открывалась в нашем приложении, а не браузером по умолчанию.
Чтобы сохранить навигацию по ссылкам в нашем приложении с WebView, мы должны создать подкласс WebViewClient и переопределить метод shouldOverrideUrlLoading (WebView webView, String url). Давайте рассмотрим простой пример подкласса WebViewClient:
Здесь мы видим, что метод shouldOverrideUrlLoading() возвращает false. Это означает, что по нажатию на ссылку откроется вкладка внутри нашего приложения, а не стандартного браузера.
Шаг 1: импорт base64
Добавьте следующий импорт:
import android.util.Base64
Шаг 2: создайте функцию для инъекции css
Эта функция будет внедрять css через Javascript:
Шаг 3: переопределите onpagefinished.
Следующим шагом будет переопределение события onpage finished, которое вызывается, когда webview завершает загрузку содержимого.
override fun onPageFinished(view: WebView?, url: String?) {
injectCSS()
}
Вот и все.
Заключение.
Мы рассмотрели простой пример android webview. Как загружать веб-страницы из сети по url, из папки assets и из данных string.
Вы можете захотеть манипулировать чужой страницей с помощью CSS. Например, загрузится веб-страница, а затем вы примените свой собственный стиль в CSS.
Это возможно в android webview. Вот шаги: