На сегодняшний день если не все, то большинство Android-устройств имеют доступ к сети интернет. А большое количество мобильных приложений так или иначе взаимодействуют с средой интернет: загружают файлы, авторизуются и получают информацию с внешних веб-сервисов и т.д. Рассмотрим, как мы можем использовать в своем приложении доступ к сети интернет.
Среди стандартных элементов нам доступен виджет WebView, который может загружать контент с определенного url-адреса. Но этим возможности работы с сетью в Android не ограничиваются. Для получения данных с определенного интернет-ресурса мы можем использовать классы HttpUrlConnection (для протокола HTTP) и HttpsUrlConnection (для протокола HTTPS) из стандартной библиотеки Java.
Итак, создадим новый проект с пустой MainActivity. Первым делом для работы с сетью нам надо установить в файле манифеста AndroidManifest.xml соответствующее разрешение:
<uses-permission android:name="android.permission.INTERNET"/>
В файле activity_main.xml, который представляет разметку для MainActivity, определим следующий код:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/downloadBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Загрузка"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<WebView
android:id="@+id/webView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/downloadBtn"
app:layout_constraintBottom_toTopOf="@id/scrollView" />
<ScrollView
android:id="@+id/scrollView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/webView"
app:layout_constraintBottom_toBottomOf="parent">
<TextView android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Здесь определена кнопка для загрузки данных, а сами данные для примера загружаются одновременно в виде строки в текстовое поле и в элемент WebView. Так как данных может быть очень много, то текстовое поле помещено в элемент ScrollView.
Поскольку загрузка данных может занять некоторое время, то обращение к интернет-ресурсу определим в отдельном потоке и для этого изменим код MainActivity следующим образом:
package com.example.httpapp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView contentView = findViewById(R.id.content);
WebView webView = findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
Button btnFetch = findViewById(R.id.downloadBtn);
btnFetch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
contentView.setText("Загрузка...");
new Thread(new Runnable() {
public void run() {
try{
String content = getContent("https://stackoverflow.com/");
webView.post(new Runnable() {
public void run() {
webView.loadDataWithBaseURL("https://stackoverflow.com/",content, "text/html", "UTF-8", "https://stackoverflow.com/");
Toast.makeText(getApplicationContext(), "Данные загружены", Toast.LENGTH_SHORT).show();
}
});
contentView.post(new Runnable() {
public void run() {
contentView.setText(content);
}
});
}
catch (IOException ex){
contentView.post(new Runnable() {
public void run() {
contentView.setText("Ошибка: " + ex.getMessage());
Toast.makeText(getApplicationContext(), "Ошибка", Toast.LENGTH_SHORT).show();
}
});
}
}
}).start();
}
});
}
private String getContent(String path) throws IOException {
BufferedReader reader=null;
InputStream stream = null;
HttpsURLConnection connection = null;
try {
URL url=new URL(path);
connection =(HttpsURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(10000);
connection.connect();
stream = connection.getInputStream();
reader= new BufferedReader(new InputStreamReader(stream));
StringBuilder buf=new StringBuilder();
String line;
while ((line=reader.readLine()) != null) {
buf.append(line).append("\n");
}
return(buf.toString());
}
finally {
if (reader != null) {
reader.close();
}
if (stream != null) {
stream.close();
}
if (connection != null) {
connection.disconnect();
}
}
}
}
Непосредственно для самой загрузки определен метод getContent(), который будет загружать веб-страницу с помощью класса
HttpsURLConnection и возвращать код загруженной страницы в виде строки.
Вначале создается элемент HttpsURLConnection:
URL url=new URL(path);
connection =(HttpsURLConnection)url.openConnection();
connection.setRequestMethod("GET"); // установка метода получения данных -GET
connection.setReadTimeout(10000); // установка таймаута перед выполнением - 10 000 миллисекунд
connection.connect(); // подключаемся к ресурсу
После подключение происходит считывание со входного потока:
stream = connection.getInputStream(); reader= new BufferedReader(new InputStreamReader(stream));
Используя входной поток, мы можем считать его в строку.
Этот метод getContent() затем будет вызываться в обработчике нажатия кнопки:
Button btnFetch = (Button)findViewById(R.id.downloadBtn);
btnFetch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
contentView.setText("Загрузка...");
new Thread(new Runnable() {
public void run() {
try{
String content = getContent("https://stackoverflow.com/");
Поскольку загрузка может занять долгое время, то метод getContent() в отдельном потоке с помощью объектов Thread и Runnable. Для примера в данном
случае обращение идет к ресурсу "https://stackoverflow.com/".
Запустим приложение и нажмем на кнопку. И при наличии интернета приложение загрузит гравную страницу с "https://stackoverflow.com/" и отобразит ее в WebView и TextView:
Конечно, данный способ вряд ли подходит для просмотра интернет-страниц, однако таким образом, мы можем получать какие-либо данные (не интернет-страницы) от различных веб-сервисов, например, в формате xml или json (например, различные курсы валют, показатели погоды), используя специальные api, и затем после обработки показывать их пользователю.