Урок по созданию простого браузера в Android Studio

В этом уроке исправим распространенную ошибку, которая случается при выполнении Урока 32 по основам разработки приложений в Android Studio

Дело в том, что там при открытии ссылки андроид использует системный браузер вместо создаваемого в уроке. В этом уроке мы создадим простой браузер, который будет работать правильно. Кроме того, вы увидите, как можно выполнить домашнее задание из урока 32.

Создаем проект в Android Studio

Детально процесс создания показан в видео.

Вводим название приложения. Выбор минимальной версии оставляем по умолчанию. В окне выбора шаблона выбираем Empty Activity. Остальные настройки оставляем по умолчанию.

Скачайте такие иконки с сайта https://material.io/icons/ и добавьте в ресурсы проекта.

ic_arrow_back_black_24dp.png https://material.io/icons/#ic_arrow_back
ic_arrow_forward_black_24dp.png https://material.io/icons/#ic_arrow_forward
ic_refresh_black_24dp.png https://material.io/icons/#ic_refresh
ic_send_black_24dp.png https://material.io/icons/#ic_send

Изменяем макет главного экрана

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.android.myapplicationbrowser.MainActivity"
    tools:layout_editor_absoluteY="81dp">


    <ImageButton
        android:id="@+id/sendButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_send_black_24dp" />

    <AutoCompleteTextView
        android:id="@+id/autoCompleteTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toStartOf="@+id/sendButton"
        app:layout_constraintStart_toEndOf="@+id/refreshButton"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@+id/refreshButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="8dp"
        app:layout_constraintStart_toEndOf="@+id/forwardButton"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_refresh_black_24dp" />

    <ImageButton
        android:id="@+id/forwardButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:layout_marginTop="8dp"
        app:layout_constraintStart_toEndOf="@+id/backButton"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_arrow_forward_black_24dp" />

    <ImageButton
        android:id="@+id/backButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_arrow_back_black_24dp" />

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/refreshButton" />

    <WebView
        android:id="@+id/webView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressBar">

    </WebView>

</android.support.constraint.ConstraintLayout>

На главном экране будет поле для ввода адреса, несколько кнопок управления, прогрессбар и WebView, в котором будет отображаться сайт. Набор кнопок – почти как в стандартном браузере – Назад, Вперед, Обновить и Отправить запрос. Полный код макета – на нашем сайте fandroid.info в текстовой версии этого урока, ссылка под видео.

В файле манифеста добавьте разрешение на доступ к интернету

<uses-permission android:name="android.permission.INTERNET" />

В файле styles.xml установим главному экрану тему без экшнбара

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

Теперь создадим класс для веб-клиента.

import android.webkit.WebView;
import android.webkit.WebViewClient;


public class myWebClient extends WebViewClient {


    @SuppressWarnings("deprecation")
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
}

Класс myWebClient унаследован от WebViewClient. Мы определяем собственный веб-клиент для того, чтобы ссылки открывались в нем, а не в системном WebView.
Здесь переопределяем метод shouldOverrideUrlLoading, в котором вызываем метод загрузки loadUrl(url).

Теперь рассмотрим код MainActivity.

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {

    ProgressBar progressBar;
    EditText inputUrl;
    WebView webView;
    ImageButton sendButton, forwardButton, backButton, refreshButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        inputUrl = (EditText) findViewById(R.id.autoCompleteTextView);
        webView = (WebView) findViewById(R.id.webView);
        sendButton = (ImageButton) findViewById(R.id.sendButton);
        forwardButton = (ImageButton) findViewById(R.id.forwardButton);
        backButton = (ImageButton) findViewById(R.id.backButton);
        refreshButton = (ImageButton) findViewById(R.id.refreshButton);

        webView.setWebViewClient(new myWebClient());

        webView.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                progressBar.setProgress(newProgress);
                if(newProgress==100)
                    progressBar.setVisibility(View.GONE);
                else
                    progressBar.setVisibility(View.VISIBLE);
            }
        });

        WebSettings webset = webView.getSettings();
        webset.setJavaScriptEnabled(true);

        webView.loadUrl("http://www.google.com");

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String url = inputUrl.getText().toString();

                if (!url.startsWith("http://")) {
                    url = "http://" + url;
                }
                webView.loadUrl(url);

                InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                inputMethodManager.hideSoftInputFromWindow(webView.getWindowToken(), 0);
            }
        });
        
        forwardButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (webView.canGoForward())
                    webView.goForward();
            }
        });

        backButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (webView.canGoBack())
                    webView.goBack();
            }
        });

        refreshButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                webView.reload();
            }
        });

    }
}

Сначала определяем переменные для прогрессбара, поля ввода, вебвью и кнопок.
Затем в методе onCreate инициализируем все эти объекты.
Методом setWebViewClient устанавливаем наш веб-клиент для вебвью.
Затем в методе setWebChromeClient устанавливаем прогрессбар, который будет отображать процесс загрузки страницы.
Затем включаем поддержку JavaScript и загружаем url по умолчанию – это будет страница Google.

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

При нажатии кнопки Отправки запроса будем считывать значение текстового поля, преобразовывать его в строку и присваивать переменной url. Затем проверяем переменную url на наличие префикса http:// и добавляем его, если он отсутствует. Передаем url браузеру WebView.

После создаем экземпляр класса InputMethodManager и вызываем его метод hideSoftInputFromWindow для скрытия клавиатуры после нажатия кнопки отправки адреса.

Следующая кнопка – Вперед, которая загружает страницу, покинутую в результе возврата по кнопке Назад (имеется в виду кнопка Назад нашего приложения, а не системная). Здесь через проверку возможности перехода вперед по истории методом WebView canGoForward() вызываем метод WebView goForward() для перехода.

Далее обрабатываем кнопку Назад, где по нажатию проверяем методом WebView canGoBack() возможность возврата по истории просмотров назад и вызываем метод WebView goBack().

Кнопка Обновить по нажатию вызывает метод WebView reload() для обновления страницы.

Запускаем приложение на устройстве.

После старта должна отобразиться страница Google. В поле ввода пишем адрес любого сайта и нажимаем кнопку отправить. Открывается страница сайта. Также можно вернуться назад в истории просмотров, перейти вперед по истории, обновить загруженную страницу. Таким образом мы создали простой браузер для загрузки страниц.

Можно убрать кнопки в приложении, и вместо сайта гугла прописать любой сайт на ваше усмотрение. Получится простое приложение для сайта на основе WebView.

А чтобы создать полноценное приложение для сайтп, предлагаем пройти наш Продвинутый курс по созданию приложения для сайта на WordPress.

В этом курсе вы научитесь создавать и размещать на хостинге сайт с популярной CMS WordPress, а также разработаете приложение для удобного доступа к созданному сайту. Подробнее о курсе смотрите на странице подписки.

На этом мы заканчиваем урок. Исходный код по ссылке https://drive.google.com/open?id=1q-2T82ZbQ1FSV-IR9fhsCwuYi1PKXBvS
Вопросы задавайте в комментариях. До встречи на следующем уроке, всем добра)

Коментарі: 3
  1. ti1
    ti1

    ОК, разобрался.
    Поскольку код я не копировал, а набирал сам, еще и поздним вечером, то ошибся с именем переменной – она называлась InputMethodManager, а не inputMethodManager…

  2. ti1
    ti1

    При запуске проекта Андроид Студио выдает ошибку для метода hideSoftInputFromWindow() в строке:

    InputMethodManager.hideSoftInputFromWindow(webView.getWindowToken(), 0);

    Текст ошибки:

    Error:(65, 35) error: non-static method hideSoftInputFromWindow(IBinder,int) cannot be referenced from a static context

    Если закомментировать эту строку, все ОК, работает, только клавиатура не убирается))).

    Что нужно сделать с этим методом? Ввести локальную переменную?

    1. Виталий Непочатов
      admin (автор)
Додати коментар