Network
JSON
JavaScript Object Notation — формат обмена данными, который легко читается людьми и обрабатывается компьютерами.
• Cтрого типизирован: данные должны соответствовать одному из типов.
• Ключи в объектах должны быть уникальными.
{
"user": {
"id": 123,
"name": "Alice",
"email": "alice@example.com",
"preferences": ["reading", "gaming", "traveling"],
"isPremium": true,
"subscription": null
}
}
Object
Набор пар ключ-значение, заключенных в фигурные скобки {}
.
• Ключи всегда строки.
• Значения могут быть любого типа из поддерживаемых JSON.
{
"name": "Alice",
"age": 25,
"isStudent": false
}
Array
Упорядоченный список значений, заключенный в квадратные скобки []
.
• Элементы массива могут быть разного типа.
• Порядок элементов имеет значение.
{
"users": [
{
"id": 1,
"name": "Alice"
},
{
"id": 2,
"name": "Bob"
},
{
"id": 3,
"name": "Charlie"
}
]
}
String
Текстовые данные, заключенные в двойные кавычки ""
.
• Поддерживаются экранированные символы (например, \n
, \t
).
• Строки используют стандарт кодировки Unicode.
{
"name": "Bob Miller",
"profilePicture": "https://example.com/profile.jpg"
}
Number
Целые или дробные числа.
• Допускаются отрицательные числа.
• Не поддерживаются специальные значения, такие как NaN
, Infinity
.
{
"age": 29,
"height": 167.5,
"accountBalance": -150.75
}
Boolean
Представляет истину или ложь.
• Возможные значения: true
или false
.
{
"isActive": true,
"hasPremiumAccount": false
}
Null
Указывает на отсутствие значения. Используется для обозначения пустого значения или неизвестного поля.
{
"email": null
}
WebSockets
Это коммуникационный протокол, обеспечивающий двустороннее, постоянное соединение между клиентом и сервером через один TCP-сокет. В отличие от HTTP, WebSockets позволяют обмениваться данными в реальном времени без необходимости повторного установления соединения, что снижает задержки и повышает эффективность обмена информацией.
class WebSocketClient {
private val client = OkHttpClient()
private lateinit var webSocket: WebSocket
private val request: Request = Request.Builder()
.url("wss://echo.websocket.org") // URL сервера WebSocket
.build()
fun start() {
webSocket = client.newWebSocket(request, object: WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
// Соединение установлено
webSocket.send("Hello, WebSocket!") // Отправка сообщения
}
override fun onMessage(webSocket: WebSocket, text: String) {
// Получено сообщение в текстовом формате
println("Received text: $text")
}
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
// Получено сообщение в байтовом формате
println("Received bytes: ${bytes.hex()}")
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
// Сервер закрывает соединение
webSocket.close(1000, null)
println("Closing WebSocket: $code / $reason")
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
// Произошла ошибка
t.printStackTrace()
}
})
}
fun stop() {
webSocket.close(1000, "Goodbye!")
}
}
SSL pinning
Техника безопасности, используемая для защиты приложений от атак «человек посередине» (MITM) при установлении защищенных соединений через HTTPS. Эта техника помогает убедиться, что приложение общается только с заранее известными и доверенными серверами, предотвращая возможность подключения к злоумышленным серверам, даже если их сертификаты подписаны доверенными центрами сертификации (CA). OkHttp поддерживает SSL pinning из коробки.
fun createOkHttpClient(): OkHttpClient {
val certificatePinner = CertificatePinner.Builder()
.add("example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") // Хэш сертификата
.build()
return OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
}
OkHttp
Библиотека для выполнения HTTP-запросов в Android и Java. Она упрощает создание, отправку и обработку HTTP-запросов и ответов, поддерживая такие важные функции, как кэширование, сжатие, повторные попытки запроса и управление соединениями. OkHttp разрабатывается компанией Square и широко используется в Android-приложениях для работы с REST API.
OkHttpClient
Основной класс в библиотеке OkHttp, который управляет выполнением HTTP-запросов и предоставляет API для их настройки. Через OkHttpClient
можно настроить таймауты, кэширование, перехватчики (interceptors), поведение подключения, обработку повторных попыток, настройку SSL и другие параметры работы с сетью.
val client = OkHttpClient()
Interceptor
Позволяет перехватывать и изменять HTTP-запросы и ответы до того, как они будут отправлены или получены. Interceptor
дает возможность добавлять общую логику для всех запросов и ответов в одном месте, что полезно для таких задач, как добавление заголовков, аутентификация, кэширование и логирование.
class AuthInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val requestWithAuth = originalRequest.newBuilder()
.header("Authorization", "Bearer <token>")
.build()
return chain.proceed(requestWithAuth) // Выполняем запрос с новым заголовком
}
}
// Подключаем кастомный Interceptor
val client = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor())
.build()
Application Interceptor
Перехватчик, который работает на уровне приложения и позволяет перехватывать и изменять HTTP-запросы и ответы до или после их отправки, но без непосредственного взаимодействия с сетью. Он используется для внесения изменений в запросы и ответы, добавления заголовков, логирования и другой обработки, которая не зависит от сети.
val client = OkHttpClient.Builder()
.addInterceptor { chain ->
val originalRequest = chain.request()
val modifiedRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer <token>")
.build()
chain.proceed(modifiedRequest) // Продолжаем с измененным запросом
}
.build()
Network Interceptor
Тип перехватчика, который работает на сетевом уровне и перехватывает запросы и ответы после обработки кэшем и перед отправкой в сеть. Network Interceptor предоставляет более низкоуровневый доступ к запросам и ответам, чем Application Interceptor, и позволяет управлять данными, которые фактически отправляются по сети и возвращаются с сервера.
val client = OkHttpClient.Builder()
.addNetworkInterceptor { chain ->
val request = chain.request()
println("Отправка запроса: ${request.url} с заголовками ${request.headers}")
val response = chain.proceed(request)
println("Получен ответ: ${response.code} с заголовками ${response.headers}")
response // Возвращаем ответ
}
.build()
Cache
Класс, который управляет кэшированием HTTP-ответов, помогая сократить количество сетевых запросов, ускорить время загрузки и снизить потребление трафика. Cache сохраняет HTTP-ответы в локальном хранилище и использует их для ответа на повторяющиеся запросы, если данные еще актуальны.
val cacheSize = 10 * 1024 * 1024 // 10 MB
val cache = Cache(File("cacheDirectory"), cacheSize)
val client = OkHttpClient.Builder()
.cache(cache)
.build()
cacheControl
Функция в Request.Builder
, которая позволяет задать поведение кэширования для конкретного HTTP-запроса. Он принимает объект CacheControl
, который определяет правила кэширования, такие как максимальный срок хранения данных, игнорирование кэша или принудительное использование данных из кэша.
• Настройка времени хранения в кэше
val request = Request.Builder()
.url("https://api.example.com/data")
.cacheControl(CacheControl.Builder()
.maxAge(10, TimeUnit.MINUTES) // Использовать кэш до 10 минут
.build())
.build()
• Принудительное использование кэша
val request = Request.Builder()
.url("https://api.example.com/data")
.cacheControl(CacheControl.FORCE_CACHE) // Использовать только кэш, даже если есть сеть
.build()
• Игнорирование кэша
val request = Request.Builder()
.url("https://api.example.com/data")
.cacheControl(CacheControl.FORCE_NETWORK) // Всегда обращаться к серверу, игнорируя кэш
.build()
REST
REST (Representational State Transfer) — это архитектурный стиль для веб-сервисов, использующий стандартные HTTP-протоколы для взаимодействия с ресурсами в различных форматах (например, JSON, XML) и обеспечивающий статeless-коммуникацию между клиентом и сервером.
Header
Метаданные, передаваемые с запросами и ответами. Они могут содержать информацию о клиенте, формате данных, авторизации, кэшировании и многом другом.
@GET("endpoint")
fun getData(
@Header("Authorization") authToken: String,
@Header("Custom-Header") customValue: String
): Call<DataResponse>
Authorization
Используется для передачи токена доступа.
@GET("user/profile")
fun getUserProfile(
@Header("Authorization") authToken: String
): Call<UserProfile>
val request = Request.Builder()
.url("https://api.example.com/user/profile")
.header("Authorization", "Bearer <token>")
.build()
Content-Type
Указывает формат данных, которые отправляются на сервер.
@POST("data")
@Headers("Content-Type: application/json")
fun sendData(
@Body data: DataRequest
): Call<ResponseBody>
val requestBody = RequestBody.create("application/json".toMediaType(), jsonData)
val request = Request.Builder()
.url("https://api.example.com/data")
.post(requestBody)
.build()
Accept
Указывает желаемый формат ответа от сервера.
@GET("data")
fun fetchData(
@Header("Accept") accept: String = "application/json"
): Call<DataResponse>
val request = Request.Builder()
.url("https://api.example.com/data")
.header("Accept", "application/json")
.build()
User-Agent
Передает информацию о приложении, которое отправляет запрос.
@GET("status")
fun checkStatus(
@Header("User-Agent") userAgent: String = "MyApp Android"
): Call<StatusResponse>
val request = Request.Builder()
.url("https://api.example.com/status")
.header("User-Agent", "MyApp Android")
.build()
Cache-Control
Управляет кэшированием данных.
@GET("content")
fun getContent(
@Header("Cache-Control") cacheControl: String = "no-cache"
): Call<ContentResponse>
val request = Request.Builder()
.url("https://api.example.com/content")
.header("Cache-Control", "no-cache")
.build()
Body
Используется для передачи объектов как тела запроса, обычно в формате JSON. Применяется в методах с POST
, PUT
, или PATCH
.
@POST("users")
fun createUser(@Body user: User): Call<Response>
Path
Используется для вставки переменных в URL-адрес, что позволяет динамически изменять конечную точку API. Переменные задаются в фигурных скобках.
@GET("users/{id}")
fun getUser(@Path("id") userId: String): Call<User>
Query
Используется для добавления параметров запроса к URL-адресу. Эти параметры добавляются после знака ?
в URL и разделяются символом &
.
// параметры page и size будут добавлены к URL-адресу, например, users?page=1&size=10.
@GET("users")
fun getUsers(
@Query("page") page: Int,
@Query("size") size: Int
): Call<List<User>>
GET
Запрашивает данные с сервера. Он не изменяет состояние ресурса.
@GET("users")
suspend fun getUsers(): List<User>
POST
Отправляет данные на сервер для создания нового ресурса.
@POST("users")
suspend fun createUser(@Body user: User): Response<User>
PUT
Обновляет существующий ресурс, отправляя его полные данные.
@PUT("users/{id}")
suspend fun updateUser(@Path("id") userId: String, @Body user: User): Response<User>
PATCH
Частично обновляет существующий ресурс. Он отправляет только измененные данные.
@PATCH("users/{id}")
suspend fun patchUser(@Path("id") userId: String, @Body user: User): Response<User>
DELETE
Удаляет ресурс на сервере.
@DELETE("users/{id}")
suspend fun deleteUser(@Path("id") userId: String): Response<Unit>
GraphQL
Это синтаксис который описывает как запрашивать данные и в основном используется клиентом для загрузки данных с сервера. GraphQL имеет три основные характеристики:
• Позволяет клиенту точно указать, какие данные ему нужны.
• Облегчает агрегацию данных из нескольких источников.
• Использует систему типов для описания данных.
GraphQL разработали в Facebook для замены REST. Из-за загрузки дополнительных данных приложение работает медленнее. Запросы разбиваются на множество endpoints. Они хранятся в разных БД. REST достигает своего предела. Вместо того чтобы иметь множество глупых endpoins лучше иметь один умный endpoint который будет способен работать со сложными запросами и придавать данным такую форму какую запрашивает клиент.
Cлой GraphQL находится между клиентом и одним или несколькими источниками данных. Он принимает запросы клиентов и возвращает необходимые данные в соответствии с переданными инструкциями.
REST-модель - это заказывать пиццу затем продукты затем химчистку. Три сервиса - три звонка. GraphQL - это передать все помощнику и запрашивать то что нужно.
gRPC
https://developer.android.com/guide/topics/connectivity/grpc |
Google Remote Procedure Call. Удаленный вызов процедур. Фреймворк для использования Protocol Buffers. Позволяет приложению и серверу взаимодействовать простым, прозрачным и эффективным способом.
Protocol Buffers
Protobufs. Метод сериализации структурированных данных. Поддерживает различные языки программирования.
Вопросы на собесе (19)
JSON (1)
- Что такое JSON и как его парсить в Android?
JSON (JavaScript Object Notation) — это легкий формат обмена данными, удобный для чтения и записи человеком, а также для парсинга и генерации машиной. В Android JSON можно парсить с помощью библиотек, таких как Gson или Kotlin Serialization.
- Что такое JSON и как его парсить в Android?
Websockets (3)
- Что такое сокеты?
Интерфейс для обмена данными между двумя устройствами по сети, обеспечивающий двустороннюю связь.
- Как работают сокеты?
Сокеты работают как точки соединения для обмена данными между устройствами через сеть, используя IP-адреса и порты для установления и поддержания связи.
- Как работать с сокетами в Android?
Использовать OkHttp WebSocket API.
- Что такое сокеты?
SSL (3)
- Что такое SSL pinning?
SSL pinning — это техника безопасности, которая заставляет приложение проверять, что сервер использует конкретный SSL-сертификат, предотвращая атаки типа «человек посередине» (MITM) и обеспечивая доверенное соединение.
- Как SSL pinning работает в Android?
SSL Pinning работает путём закрепления (пиннинга) конкретного сертификата или публичного ключа на стороне клиента, чтобы проверять его при каждом соединении с сервером. Это предотвращает атаки типа MITM, так как соединение будет установлено только если сертификат сервера совпадает с закреплённым на клиенте. В Android SSL Pinning можно реализовать с помощью OkHttp или Network Security Config.
- Что такое MITM?
MITM (Man-in-the-Middle) — это атака, при которой злоумышленник перехватывает и может изменять коммуникацию между двумя сторонами, ставя под угрозу конфиденциальность и целостность данных.
- Что такое SSL pinning?
OkHttp (3)
- Что такое OkHttp, и как его использовать для выполнения сетевых запросов?
Библиотека для работы с HTTP-запросами в Android, которая обеспечивает эффективное выполнение сетевых запросов и управление соединениями. OkHttp поддерживает асинхронные и синхронные запросы, кэширование, автоматическое управление соединениями и другие функции.
- Что под капотом использует OkHttp?
HttpURLConnection.
- Какие бывают виды интерсепторов?
• Application Interceptor — перехватывает запросы до их отправки или после получения ответа, может модифицировать запрос и ответ.
• Network Interceptor — работает на уровне сети, перехватывает запросы и ответы после сетевого слоя.
- Что такое OkHttp, и как его использовать для выполнения сетевых запросов?
REST (5)
- Что такое REST?
REST (Representational State Transfer) — это архитектурный стиль для проектирования сетевых приложений, использующий стандартные HTTP-методы (
GET
,POST
,PUT
,DELETE
) для работы с ресурсами по URL. Он обеспечивает простоту, масштабируемость и независимость клиента от сервера.
- Разница между GET и POST?
GET
запрашивает данные с сервера и передает параметры черезURL
, что делает их видимыми.POST
отправляет данные на сервер в теле запроса, что обеспечивает большую безопасность и позволяет передавать большие объемы информации.
- Могут ли GET-запросы содержать Body?
Нет, согласно спецификации HTTP. Рекомендуется использовать параметры URL для передачи данных.
- Почему нежелательно отправлять конфиденциальные данные через GET?
Параметры запроса видны в
URL
, что может привести к утечке информации через журналы сервера, кэш браузера или историю. Кроме того,GET
-запросы могут быть легко перехвачены и проанализированы, что увеличивает риск компрометации данных.
- Разница между path и query?
path
определяет ресурс,query
передает параметры.
- Что такое REST?
GraphQL (1)
- Что такое GraphQL?
GraphQL — это язык запросов для API, который позволяет клиентам запрашивать именно те данные, которые им нужны, и получать их в едином ответе. В отличие от REST, где структура ответа фиксирована, GraphQL позволяет более гибко определять структуру данных, что уменьшает количество запросов и объем передаваемых данных.
- Что такое GraphQL?
Другие (3)
- Какие есть способы сделать сетевой запрос на Android?
• HttpURLConnection — встроенный класс для выполнения HTTP-запросов. Подходит для простых операций, но требует больше кода для обработки потоков и ошибок.
• OkHttp — популярная библиотека от Square, которая упрощает работу с HTTP. Поддерживает асинхронные запросы, кеширование, и повторные попытки.
• Retrofit — библиотека для создания API-клиентов на основе HTTP. Работает на базе OkHttp и использует аннотации для простого создания запросов.
• Volley — библиотека от Google для выполнения сетевых запросов с поддержкой кеширования и обработки изображений.
• Ktor — библиотека от JetBrains, используемая для асинхронных HTTP-запросов в Kotlin.
- Как обеспечить безопасность сетевых запросов в Android приложении?
• Используйте HTTPS вместо HTTP для шифрования данных во время передачи.
• Реализуйте SSL pinning для проверки сертификатов сервера.
• Используйте аутентификацию (например, OAuth) для защиты API.
• Шифруйте конфиденциальные данные на устройстве и при передаче.
• Ограничьте доступ к сетевым ресурсам с помощью соответствующих разрешений.
• Используйте библиотеки для обработки сетевых запросов, которые обеспечивают защиту (например, Retrofit).
- В чем разница между HTTP и HTTPS?
HTTP передает данные в открытом виде, что делает их уязвимыми для перехвата и атак. А HTTPS использует SSL/TLS для шифрования данных, передаваемых между клиентом и сервером, что обеспечивает безопасность и конфиденциальность.
- Какие есть способы сделать сетевой запрос на Android?