Компьютеры с современный мир

WebView - создай свой браузер. Пишем полноценный браузер под Aндроид Дополнительная установка веб-обозревателя для перехода по внутренним ссылкам

Стандартные браузеры в устройствах на базе Android зачастую не отвечают повседневным запросам требовательных пользователей. На этой операционной системе существует масса качественных и функциональных интернет-обозревателей. Мы собрали лучшие браузеры для Android именно в этой статье.

Firefox по праву носит звание одного из лучших мобильных браузеров на Android. За годы присутствия на этой операционной системе разработка Mozilla обросла массой функций и получила облагороженный современный интерфейс. Firefox для Android - это баланс функционала, удобства и скорости использования. Мобильный браузер от Mozilla проигрывает по скорости тому же Google Chrome, но многие особенности Firefox сделаны куда более приятно и удобно.

Собственный движок Gecko, который использует Firefox, поддерживает практически все современные стандарты веба, а также для него имеются расширения с дополнительным функционалом, как и в десктопной версии браузера. Среди основных функций Fiefox: синхронизация всех данных между браузерами с помощью специального аккаунта, безопасный серфинг, удобная стартовая панель, масса расширений, режим чтения.



Самым популярным браузером не только на компьютерах, но и на мобильных устройствах является Google Chrome. Неудивительно, ведь он почти всегда предустанавливается на самую популярную мобильную ОС. Свою популярность Chrome завоевал вполне заслуженно - он быстрый, относительно функциональный, простой и удобный, а также он хорошо интегрирован с сервисами Google и десктопной версией браузера (есть полная сихронизация данных и вкладок). Интеграция с сервисами Google иногда может быть полезной, например - перевод текста на страницах с помощью Google Переводчика или голосовой поиск.

Также Chrome заботится о безопасности пользователя - в браузере встроен специальный фильтр сайтов, которые могут быть опасны для устройств с Android. Присутствует некое подобие технологии сжатия данных. Она не так совершенна, как у Opera, но все-таки неплохо экономит данные, передаваемые как по Wi-Fi, так и по мобильному интернету. Есть режим инкогнито для анонимного посещения сайтов. Пожалуй, единственный недостаток Chrome на данный момент - отсутствие поддержки расширений. Для тех, кто хочет пробовать все новые функции первым, есть Chrome Beta и Dev. Эти версии браузера обновляются быстрее и чаще - в них тестируются все нововведения.



Мобильные браузеры от норвежской компании Opera - тоже одни из самых популярных, функциональных и быстроразвивающихся на платформе Android. Эти ребята за многие годы своей работы определенно смогли вывести формулу почти идеального интернет-обозревателя для смартфонов и планшетов. В Opera есть практически все, что надо обычному пользователю: быстрый серфинг, удобная классическая экспресс-панель, синхронизация данных с десктопной версией, анонимный режим, удобный поиск с подсказками из панели адреса, а также одна из главных особенностей - сжатие трафика.

Ребята из Opera собаку съели на технологиях экономии трафика. Мобильная Opera с активированным режимом Turbo может сократить расходы мобильного интернета в два, а то и в три раза. Для тех, кому особенно важен расход трафика, существует Opera Mini - в ней экономия включена по умолчанию, но от этого порой страдает внешний вид сайтов. Также мини-версия куда легче и быстрее обычной Opera. Еще одна сильная сторона одноименного браузера - красивый и приятный внешний вид. Opera всегда славилась одним из самых стильных интерфейсов в браузерах. Если вы хотите сжимать весь трафик на своем устройстве, то обратите внимание на приложение .



Dolphin - это альтернативный браузер на Android с массой дополнительных возможностей и функций «из-коробки». Среди таких стоит отметить поддержку Adobe Flash, от которого практически все отказались, но он еще много где используется, применение различных тем для изменения интерфейса, поддержку уникальных дополнений и управление удобными и простыми жестами. Все это доступно сразу - никаких дополнительных настроек. А еще Dolphin быстрый, безопасный, бесплатный и всегда современный - разработчики выпускают обновления браузера практически каждую неделю.


Puffin - мобильный веб-браузер, который по своей концепции напоминает Dolphin. Здесь тоже в наличии красивый и удобный интерфейс, есть много возможностей, а еще Puffin такой же быстрый, как и «дельфин». В основном браузер Puffin подходит для слабых устройств, так как в нем предусмотрена специальная технология «облегченного» веб-серфинга - страницы сначала загружаются на облачный сервис Puffin, там оптимизируются и уже в легком виде приходят на экран устройства. При этом качество и внешний вид страниц практически не страдают от сломанной верстки или уменьшения качества.

Также в Puffin стоит отметить ряд дополнительных возможностей:

  • полная поддержка Adobe Flash для игр (виртуальный джойстик на экране);
  • шифрование трафика через облачный сервис;
  • эмуляция мыши;
  • возможность загрузить файлы сначала в «облако», а потом на устройство;
  • установка расширений;
  • темы интерфейса.
Браузер Puffin является отличным выбором для слабых устройств, но при этом функционала в этом интернет-обозревателе не занимать.



Российская компания «Яндекс» преуспела в создании собственного браузера для мобильных устройств с Android. Яндекс.Браузер для этой платформы - это отличное решение для пользователей из СНГ. Этот интернет-обозреватель прямо таки пропитан интеграцией с сервисами самого «Яндекса» и других местных социальных сетей / порталов. Например, строка поиска в браузере подсказывает нужные сайты и понимает запросы с полуслова, а еще внутри приложения можно посмотреть информацию о погоде и пробках.

Дорогой, я студентка bca. Я должен сделать один проект за последний семестр. Поэтому я решил создать веб- , который работает на ОС Android, но я полностью для этого приложения. Так, может ли кто-нибудь помочь мне в этом. Я уже установил все необходимые инструменты, такие как jdk, android sdk 3.0, eclipse. Но теперь я понятия не имею, откуда я должен начать разработку браузера. Поэтому, пожалуйста, помогите мне … у меня есть только 2 месяца для этого проекта. Так это возможно через 2 месяца или нет?

Это зависит от того, что вы подразумеваете при разработке браузера …

Разработка механизма браузера + рендеринга с нуля – это много работы, но вы можете легко создать браузер на основе Androids WebView с помощью WebViewClient и создать новый пользовательский интерфейс, изменив способ взаимодействия пользователя с браузером.

В Webview есть всевозможные перехватчики для перехвата взаимодействия с браузером, поэтому вы можете легко расширить его. Например, вы можете позволить пользователю перелистывать страницы (например, google fastflip), экспериментировать с 3D, сопоставляя отображаемую веб-страницу в пространстве OpenGL (например, в браузере сферы) и т. Д.

В качестве отправной точки взгляните на блог Александра Кметека и его проект «Мосамбро», который расширяет браузер Android, добавив поддержку микроформата.

Звучит как действительно большой проект, и поэтому вы не можете просто начать с нуля и записать его. Вы должны составить план о том, как вы хотите реализовать все части, записать диаграммы классов и т. Д. Если вы изучаете информатику, вы должны были услышать об этом в предыдущих семестрах.

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

Я действительно предлагаю вам понять масштабы этой задачи, вот исходный код браузера Androids, дающий вам представление о его сложности.

Создание базового браузера можно было сделать через день или два для тех, кто имеет опыт разработки Android, так же, как другие заявили, что WebView обеспечивает практически все, что вам нужно для отображения веб-страницы. Есть несколько настроек для JavaScript и других функций для проверки, а затем после маркировки основного текстового поля для URL-адреса и кнопки go, которая в значительной степени является основным веб-браузером.

Реальная работа приходит во всех расширенных настройках. Создание браузера, который конкурирует с большими парнями, может быть, немного сложно для одного человека через пару месяцев, но сделать что-то свое, что работает, очень возможно. Попробуй!

Для создания полного веб-браузера в Android вы используете WebView .

Простая привязка кода:

WebView wv = (WebView)findViewById(R.id.webview1); wv = (WebView) findViewById(R.id.webView1); wv.loadUrl("http://www.apsmind.com");

Давайте создадим новое приложение - браузер для android устройств, своими руками, это будет интересно, и кода будет не очень много.

Приложение-браузер для android

Запустим android studio и создадим новый проект, application name My Site, company domain по своему усмотрению, я вписал домен сайта сайт. жмем Next, на следующей вкладке оставляем все без изменения, жмем next, далее уже выбрана Empty Activity , ее и оставим, затем в последней вкладке изменим Layout Name с activity_main на main, и нажмем финиш.

Android Studio подготовит файлы проекта, это займет некоторое время. В главном окне будет открыты два файла, main.xml и MainActivity.java , начнем работать в последнем. Изменим extended AppCompactActivity на Activity, сохранимся.

Добавление разрешений в манифест

Затем откроем файл AndroidManifest.xml и добавим после первой секции пользовательское разрешение user-permission ,

что бы наше приложение имело доступ в интернет. Сохраним и закроем AndroidManifest.xml.

Перейдем в файл Main.xml , он находится по пути res/layout/main.xml, удалим строку android:text="Hello Word!" полностью, изменим TextView на WebView, из свойств основного слоя RelativeLayout уберем ненужные отступы (paddingBottom, paddingLeft, paddingRight,paddingTop).

Для WebView добавим свойство android:id="@+id/webView",изменим android:layout_width="wrap_content" и android:layout_height="wrap_content" на android:layout_width="match_parent" и android:layout_height="match_parent", для того, что бы наш элемент WebView был на весь экран.

Кодим логику на Java

С файлом main.xml мы закончили, перейдем к MainActivity.java . Добавим переменную wv типа WebView , присвоим ей элемент, найдя его с помощью функции findViewById(), опишем настройки wv, в частности разрешим в WebView выполнять java скрипты, укажем адрес загрузки сайта в наш браузер, я для примера запущу Яндекс, применив функцию loadUrl("http://ya.ru").

public class MainActivity extends Activity { WebView wv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); wv = (WebView)findViewById(R.id.webView); WebSettings settings = wv.getSettings(); settings.setJavaScriptEnabled(true); wv..setWebViewClient(new WebViewClient()); }

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

@Override public void onBackPressed(){ if(wv.canGoBack()){ wv.goBack(); }else{ super.onBackPressed(); } }

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

Нажмем кнопку Start, это зеленый треугольник на панели инструментов AndroidStudio , запустится наш эмулятор, и если все сделано правильно, через некоторое время в браузере запустится поиск Яндекс, можно понажимать на виртуальную клавиатуру и что-то поискать, все работает хорошо.

Закроем программу, не закрывая сам эмулятор, нажав на красный прямоугольник, это Stop вместо Start, изменим адрес на произвольный, я «пропиарю» свой сайт "https://сайт",

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

Полный текст AndroidManifest.xml

Полный текст main.xml

Полный текст MainActivity.java

package ru.maxfad.mysite; import android.app.Activity; import android.os.Bundle; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; public class MainActivity extends Activity { WebView wv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); wv = (WebView)findViewById(R.id.webView); WebSettings settings = wv.getSettings(); settings.setJavaScriptEnabled(true); wv..setWebViewClient(new WebViewClient()); } @Override public void onBackPressed(){ if(wv.canGoBack()){ wv.goBack(); }else{ super.onBackPressed(); } } }

В этом видео подробно показано как создать приложение-браузер для android устройств:

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

Создадим новый проект MyBrowser и сразу заменим код в файле разметки res/layout/activity_main.xml :

Теперь откроем файл активности MainActivity.java и объявим компонент , а также инициализируем его - включим поддержку JavaScript и укажем страницу для загрузки.

Private WebView webView; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); webView = findViewById(R.id.webView); // включаем поддержку JavaScript webView.getSettings().setJavaScriptEnabled(true); // указываем страницу загрузки webView.loadUrl("http://сайт/android"); }

Так как приложение будет использовать интернет, необходимо установить разрешение на доступ к интернету в файле-манифесте.

Там же в манифесте модифицируем строчку для экрана, удалив заголовок из нашего приложения (выделено жирным):

android:theme="@style/Theme.AppCompat.NoActionBar" >

Запустим приложение. В нашем распоряжении появился простейший вьювер веб-страниц, но с одним недостатком. Если вы щёлкнете на любой ссылке, то у вас автоматически запустится браузер по умолчанию и новая страница отобразится уже там. Точнее так было раньше. На новых устройствах при запуске приложения сразу открывается браузер.

Чтобы решить данную проблему и открывать ссылки в своей программе, нужно переопределить класс WebViewClient и позволить нашему приложению обрабатывать ссылки. Добавим в коде вложенный класс:

Private class MyWebViewClient extends WebViewClient { @TargetApi(Build.VERSION_CODES.N) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { view.loadUrl(request.getUrl().toString()); return true; } // Для старых устройств @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } }

Затем в методе onCreate() определим экземпляр MyWebViewClient . Он может находиться в любом месте после инициализации объекта :

WebView.setWebViewClient(new MyWebViewClient());

Теперь в нашем приложении создан WebViewClient , который позволяет загружать любой указанный URL, выбранный в , в сам контейнер , а не запускать браузер. За данную функциональность отвечает метод , в котором мы указываем текущий и нужный URL. Возвращаемое значение true говорит о том, что мы не нуждаемся в запуске стороннего браузера, а самостоятельно загрузим контент по ссылке. В версии API 24 добавили перегруженную версию метода, учитывайте это обстоятельство.

Повторно запустите программу и убедитесь, что ссылки загружаются теперь в самом приложении. Но теперь возникла ещё одна проблема. Мы не можем вернуться к предыдущей странице. Если мы нажмём на кнопку BACK (Назад) на своем устройстве, то просто закроем свое приложение. Для решения новой проблемы нам необходимо обрабатывать нажатие кнопки BACK. Добавляем новый метод:

@Override public void onBackPressed() { if(webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } }

Мы должны проверить, что поддерживает навигацию на предыдущую страницу. Если условие верно, тогда вызывается метод goBack() , который возвращает нас на предыдущую страницу на один шаг назад. Если таких страниц набралось несколько, то мы можем последовательно вернуться к самой первой странице. При этом метод всегда будет возвращать значение true . Когда мы вернёмся на самую первую страницу, с которой начали путешествие по интернету, то вернётся значение false и обработкой нажатия кнопки BACK займётся уже сама система, которая закроет экран приложения.

Запустите приложение ещё раз. У вас появился свой собственный веб-браузер, позволяющий ходить по ссылкам и возвращаться на предыдущую страницу. Изучив документацию, вы можете оснастить приложение и другим вкусными плюшками для своего браузера.

Если вам нужно часть ссылок, ведущих на ваш сайт открывать в браузере, а локальные ссылки открывать в приложении, то применяйте условие с разными возвращаемыми значениями.

Public class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(Uri.parse(url).getHost()..ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } }

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

Public class MyAppWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if(Uri.parse(url).getHost().length() == 0) { return false; } Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); view.getContext().startActivity(intent); return true; } }

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

Чтобы было понятнее, переделаем пример следующим образом. Создайте две активности. На первой активности разместите кнопку для перехода на вторую активность, а на второй активности разместите компонент .

В манифесте прописываем у второй активности фильтр.

Код для кнопки для перехода на вторую активность.

Public void onClick(View view) { Intent intent = new Intent("ru.alexanderklimov.Browser"); intent.setData(Uri.parse("http://сайт/android/")); startActivity(intent); }

Мы создали собственное намерение с указанием фильтра и предоставили данные - адрес сайта.

Вторая активность должна принять данные:

Package ru.alexanderklimov.testapplication; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.webkit.WebView; import android.webkit.WebViewClient; public class SecondActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_second); Uri url = getIntent().getData(); WebView webView = findViewById(R.id.webView); webView.setWebViewClient(new Callback()); webView.loadUrl(url.toString()); } private class Callback extends WebViewClient { @Override public boolean shouldOverrideUrlLoading (WebView view, String url) { return(false); } } }

В фильтре для второй активность мы указали два действия.

Это означает, что любые активности (читай, приложения) могут вызвать вашу активность с мини-браузером по такому же принципу. Запустите в студии в отдельном окне любой старый проект или создайте новый и добавьте в него кнопку и пропишите тот же код, который мы использовали для щелчка кнопки.

Запустите второе приложение (первое приложение можно закрыть) и нажмите на кнопку. У вас запустится не первое приложение с начальным экраном, а сразу вторая активность с мини-браузером. Таким образом, любое приложение может запустить браузер, не зная имени класса вашей активности, а используя только строку "ru.alexanderklimov.Browser" , передаваемую в Intent . При этом ваша активность с браузером должна иметь категорию по умолчанию и данные. Напомню:

Вы можете представить свою строку в виде строковой константы и сообщить всем потенциальным пользователям вашего браузера, как они могут запустить его у себя. Но в Android уже есть такая готовая константа ACTION_VIEW , которая по справке документации представляет собой следующее:

Public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW";

Перепишем код для кнопки у второго приложения

Intent(android.content.Intent.ACTION_VIEW, Uri.parse("http://сайт/android/")); startActivity(intent);

Что произойдёт на этот раз? Мы помним, что у нас прописано два действия, включая и android.intent.action.VIEW . А значит наше первое приложение с браузером тоже должно распознавать эту команду, когда какое-то приложение у пользователя использует этот код. На эмуляторе как минимум есть одна такая программа "Browser", и теперь к ней добавилась наша вторая активность из первого приложения. На экране появится выбор из двух приложений.

А если удалить все альтернативные браузеры и оставить только вашу программу, то и выбора не будет. Ваш браузер станет основным. И если какое-то приложение захочет запустить веб-страницу указанным способом, то откроется ваша программа.

Небольшое замечание. Если заменить последнюю строчку на такую:

StartActivity(Intent.createChooser(intent, "Мяу..."));

То в окне выбора программы вместо верхней строки "Open with" или её локального перевода появится ваша строка. Но не это главное. Если по каким-то причинам на устройстве не окажется ни одного браузера, то данный вариант кода не вызовет краха приложения, в отличие от первоначального варианта. Поэтому используйте предложенный вариант ради надёжности.

Мы уже начали полноценно обеспечивать себя личным софтом, вспомните наши чудесные калькулятор и конвертер. И в этом уроке мы научимся создавать простой браузер, с помощью которого будет бороздить просторы интернета. Согласитесь, серфить сеть на своем собственном браузере - это в разы приятнее чем делать это на Opera или Chrome (вряд ли удобнее, но приятнее:)). Создаем новый проект, названия традиционно выбирайте сами. Лично я вообще не создаю каждый раз все с нуля, а просто открываю, что есть, и зачищаю весь код до исходного состояния Blank Activity. Делайте, как вам удобней.

Итак, кратко очертим объем и специфику последующей работы. Нам нужно создать элемент , в котором будет все происходить, написать код, создающий наш личный Веб-обозреватель, обустроить его базовыми функциями, прописать разрешение на использование Internet нашим приложением в файле манифеста, и написать обработчик нажатия аппаратной кнопки "Назад" на устройстве (то есть, что будет происходить в нашем браузере при нажатии на эту кнопку).

Начнем. Открываем файл activity_main.xml . Создаем там один единственный элемент , которого нам вполне достаточно для реализации веб-обозревателя:

< WebView xmlns: android= "http://schemas.android.com/apk/res/android" android: layout_height= "match_parent" android: layout_width= "match_parent" android: id= "@+id/web" />

Окно разметки будет выглядеть так:

После этого давайте сразу разберемся с файлом AndroidManifest.xml . Открываем его и добавляем туда две строчки, одна - это разрешение для приложения использовать Интернет, другая - изменение стиля приложения, а точнее сокрытие панели "Title" приложения (панели с заголовком приложения) с той целью, чтобы предоставить окну браузера больше пространства для отображения страниц.

Пишем строку разрешения использовать интернет до открытия тега ...:

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

Теперь добавим к строке настройки нашего Activity команду для скрытия заголовка (нижняя строка, выделенная жирным, это также находиться в AndroidManifest.xml ):

< activity android: name= ".MainActivity" android: label= android: theme= "@android:style/Theme.NoTitleBar" >

Теперь переходим к самой важной и ответственной части работы - написанию java кода. Открываем файл MainActivity.java и пишем так следующее (объяснения даны в коде после знаков //, кто не заметил):

package home.myapplication ; import android.app.Activity ; import android.app.AlertDialog ; import android.content.ContentValues ; import android.content.Intent ; import android.database.Cursor ; import android.database.sqlite.SQLiteDatabase ; import android.database.sqlite.SQLiteOpenHelper ; import android.support.v7.app.ActionBarActivity ; import android.os.Bundle ; import android.util.Log ; import android.view.KeyEvent ; import android.view.Menu ; import android.view.MenuItem ; import android.view.View ; import android.webkit.WebView ; import android.webkit.WebViewClient ; import android.widget.Button ; import android.widget.EditText ; import android.widget.RadioButton ; import android.widget.TextView ; public class MainActivity extends Activity { // Объявляем переменную типа WebView private WebView mWeb; // Создаем класс типа Веб-обозреватель (WebViewClient), которому настраиваем // по умолчанию разрешение обрабатывать все ссылки внутри этого класса, // не обращаясь к сторонним программам: private class WebViewer extends WebViewClient { (WebView view , String url ) { view. loadUrl(url); return true ; } } public void onCreate (Bundle savedInstanceState ) { super. onCreate(savedInstanceState); setContentView(R . layout. activity_main); // Привязываем объявленную переменную типа WebView к созданному нами // элементу WebView в файле activity_main.xml: mWeb= (WebView )findViewById(R . id. web); // Подключаем для этого элемента поддержку Java скриптов: mWeb. getSettings(). setJavaScriptEnabled(true ); // Настраиваем страницу, которая будет загружать при запуске, можете ввести любую: mWeb. loadUrl("http://developeroleg.ucoz.ru/" ); // Настраиваем обозреватель для нашего элемента WebView, подключаем созданный нами выше // Веб-клиент, с помощью которого будет проходить просмотр страниц: mWeb. setWebViewClient(new WebViewer ()); } // Пишем код обработки нажатия кнопки назад на устройстве, что позволит нам при нажатии // на кнопку "Назад" перейти к предыдущей странице, а не просто закрывать приложения. // Оно будет закрываться кнопкой "Назад" лишь в том случае, если мы находимся на стартовой // странице, которую указали выше: @Override public void onBackPressed () { if (mWeb. canGoBack()) { mWeb. goBack();} else { super. onBackPressed(); } } }

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

Похожие публикации