Запрос HTTP в Котлине

Я совершенно не знаком с Котлином. Я хочу сделать проверку входа в систему с помощью метода POST и получить некоторую информацию с помощью метода GET. У меня есть URL, имя пользователя и пароль уже моего предыдущего проекта. Я не нашел подходящего примерного проекта, который использует эту вещь. Любой, пожалуйста, предложите мне любой рабочий пример, где я могу использовать метод GET и POST в запросе HTTP

Ответ 1

Для Android Volley - хорошее место для начала. Для всех платформ вы также можете проверить клиент Ktor.

Однако вы можете использовать стандартные библиотеки, которые вы используете в Java. Например, с HttpURLConnection вы можете сделать:

fun sendGet() {
    val url = URL("http://www.google.com/")

    with(url.openConnection() as HttpURLConnection) {
        requestMethod = "GET"  // optional default is GET

        println("\nSent 'GET' request to URL : $url; Response Code : $responseCode")

        inputStream.bufferedReader().use {
            it.lines().forEach { line ->
                println(line)
            }
        }
    }
}

Или проще:

URL("https://google.com").readText()

Ответ 2

Отправьте запрос HTTP POST/GET с параметрами, используя HttpURLConnection:

POST с параметрами:

fun sendPostRequest(userName:String, password:String) {

    var reqParam = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(userName, "UTF-8")
    reqParam += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8")
    val mURL = URL("<Your API Link>")

    with(mURL.openConnection() as HttpURLConnection) {
        // optional default is GET
        requestMethod = "POST"

        val wr = OutputStreamWriter(getOutputStream());
        wr.write(reqParam);
        wr.flush();

        println("URL : $url")
        println("Response Code : $responseCode")

        BufferedReader(InputStreamReader(inputStream)).use {
            val response = StringBuffer()

            var inputLine = it.readLine()
            while (inputLine != null) {
                response.append(inputLine)
                inputLine = it.readLine()
            }
            it.close()
            println("Response : $response")
        }
    }
}

GET с параметрами:

fun sendGetRequest(userName:String, password:String) {

        var reqParam = URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(userName, "UTF-8")
        reqParam += "&" + URLEncoder.encode("password", "UTF-8") + "=" + URLEncoder.encode(password, "UTF-8")

        val mURL = URL("<Yout API Link>?"+reqParam)

        with(mURL.openConnection() as HttpURLConnection) {
            // optional default is GET
            requestMethod = "GET"

            println("URL : $url")
            println("Response Code : $responseCode")

            BufferedReader(InputStreamReader(inputStream)).use {
                val response = StringBuffer()

                var inputLine = it.readLine()
                while (inputLine != null) {
                    response.append(inputLine)
                    inputLine = it.readLine()
                }
                it.close()
                println("Response : $response")
            }
        }
    }

Ответ 3

Возможно, самый простой GET

Для всех, придерживающихся NetworkOnMainThreadException для других решений: используйте AsyncTask или, даже короче, (все же экспериментально) Coroutines:

launch {

    val jsonStr = URL("url").readText()

}

Если вам нужно протестировать с помощью простого http, не забудьте добавить к вашему манифесту: android:usesCleartextTraffic="true"


Для экспериментальных Coroutines вам необходимо добавить build.gradle по состоянию на 10/10/2018:

kotlin {
    experimental {
        coroutines 'enable'
    }
}
dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.24.0"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.24.0"
    ...

Ответ 4

Вы можете использовать библиотеку kohttp. Это HTTP-клиент Kotlin DSL. Он поддерживает функции square.okhttp и предоставляет им понятный DSL. Асинхронные вызовы KoHttp приводятся в действие сопрограммами.

httpGet расширения httpGet

val response: Response = "https://google.com/search?q=iphone".httpGet()

Вы также можете использовать асинхронный вызов с сопрограммами

val response: Deferred<Response> = "https://google.com/search?q=iphone".asyncHttpGet()

или функция DSL для более сложных запросов

val response: Response = httpGet {
    host = "google.com"
    path = "/search"
    param {
       "q" to "iphone"
       "safe" to "off"
   }
}

Вы можете найти более подробную информацию в документации

Чтобы получить его с использованием Gradle

implementation 'io.github.rybalkinsd:kohttp:0.10.0'

Ответ 5

Без добавления дополнительных зависимостей это работает. Для этого вам не нужен Volley. Это работает с использованием текущей версии Kotlin по состоянию на декабрь 2018 года: Kotlin 1.3.10

Если вы используете Android Studio, вам нужно добавить это объявление в свой AndroidManifest.xml:

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

Здесь вы должны вручную объявить импорт. Авто-импорт инструмент вызвал у меня много конфликтов.:

import android.os.AsyncTask
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStream
import java.io.OutputStreamWriter
import java.net.URL
import java.net.URLEncoder
import javax.net.ssl.HttpsURLConnection

Вы не можете выполнять сетевые запросы в фоновом потоке. Вы должны подклассифицировать AsyncTask.

Чтобы вызвать метод:

NetworkTask().execute(requestURL, queryString)

Декларация:

private class NetworkTask : AsyncTask<String, Int, Long>() {
    override fun doInBackground(vararg parts: String): Long? {
        val requestURL = parts.first()
        val queryString = parts.last()

        // Set up request
        val connection: HttpsURLConnection = URL(requestURL).openConnection() as HttpsURLConnection
        // Default is GET so you must override this for post
        connection.requestMethod = "POST"
        // To send a post body, output must be true
        connection.doOutput = true
        // Create the stream
        val outputStream: OutputStream = connection.outputStream
        // Create a writer container to pass the output over the stream
        val outputWriter = OutputStreamWriter(outputStream)
        // Add the string to the writer container
        outputWriter.write(queryString)
        // Send the data
        outputWriter.flush()

        // Create an input stream to read the response
        val inputStream = BufferedReader(InputStreamReader(connection.inputStream)).use {
            // Container for input stream data
            val response = StringBuffer()
            var inputLine = it.readLine()
            // Add each line to the response container
            while (inputLine != null) {
                response.append(inputLine)
                inputLine = it.readLine()
            }
            it.close()
            // TODO: Add main thread callback to parse response
            println(">>>> Response: $response")
        }
        connection.disconnect()

        return 0
    }

    protected fun onProgressUpdate(vararg progress: Int) {
    }

    override fun onPostExecute(result: Long?) {
    }
}

Ответ 6

import java.io.IOException
import java.net.URL

fun main(vararg args: String) {
    val response = try {
        URL("http://seznam.cz")
                .openStream()
                .bufferedReader()
                .use { it.readText() }
    } catch (e: IOException) {
        "Error with ${e.message}."
    }
    println(response)
}

Ответ 7

Если вы используете Kotlin, вы можете сделать свой код максимально лаконичным. Метод run превращает получатель в this и возвращает значение блока. this as HttpURLConnection создает умный бросок. bufferedReader().readText() избегает связки стандартного кода.

return URL(url).run {
        openConnection().run {
            this as HttpURLConnection
            inputStream.bufferedReader().readText()
        }
}

Вы также можете обернуть это в функцию расширения.

fun URL.getText(): String {
    return openConnection().run {
                this as HttpURLConnection
                inputStream.bufferedReader().readText()
            }
}

И называть это так

return URL(url).getText()

Наконец, если вы супер ленивый, вы можете расширить класс String.

fun String.getUrlText(): String {
    return URL(this).run {
            openConnection().run {
                this as HttpURLConnection
                inputStream.bufferedReader().readText()
            }
    }
}

И называть это так

return "http://somewhere.com".getUrlText()

Ответ 8

Я думаю, что использование okhttp - самое простое решение. Здесь вы можете увидеть пример для метода POST, отправки json и с auth.

val url = "https://example.com/endpoint"

val client = OkHttpClient()

val JSON = MediaType.get("application/json; charset=utf-8")
val body = RequestBody.create(JSON, "{\"data\":\"$data\"}")
val request = Request.Builder()
        .addHeader("Authorization", "Bearer $token")
        .url(url)
        .post(body)
        .build()

val  response = client . newCall (request).execute()

println(response.request())
println(response.body()!!.string())

Не забудьте добавить эту зависимость в ваш проект https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp

ОБНОВЛЕНИЕ: 7 июля 2019 г. Я приведу два примера с использованием последних версий Kotlin (1.3.41), OkHttp (4.0.0) и Jackson (2.9.9).

Получить метод

fun get() {
    val client = OkHttpClient()
    val url = URL("https://reqres.in/api/users?page=2")

    val request = Request.Builder()
            .url(url)
            .get()
            .build()

    val response = client.newCall(request).execute()

    val responseBody = response.body!!.string()

    //Response
    println("Response Body: " + responseBody)

    //we could use jackson if we got a JSON
    val mapperAll = ObjectMapper()
    val objData = mapperAll.readTree(responseBody)

    objData.get("data").forEachIndexed { index, jsonNode ->
        println("$index $jsonNode")
    }
}

Метод POST

fun post() {
    val client = OkHttpClient()
    val url = URL("https://reqres.in/api/users")

    //just a string
    var jsonString = "{\"name\": \"Rolando\", \"job\": \"Fakeador\"}"

    //or using jackson
    val mapperAll = ObjectMapper()
    val jacksonObj = mapperAll.createObjectNode()
    jacksonObj.put("name", "Rolando")
    jacksonObj.put("job", "Fakeador")
    val jacksonString = jacksonObj.toString()

    val mediaType = "application/json; charset=utf-8".toMediaType()
    val body = jacksonString.toRequestBody(mediaType)

    val request = Request.Builder()
            .url(url)
            .post(body)
            .build()

    val response = client.newCall(request).execute()

    val responseBody = response.body!!.string()

    //Response
    println("Response Body: " + responseBody)

    //we could use jackson if we got a JSON
    val objData = mapperAll.readTree(responseBody)

    println("My name is " + objData.get("name").textValue() + ", and I'm a " + objData.get("job").textValue() + ".")
}

Ответ 9

Посмотрите библиотеку Fuel, пример запроса GET

"https://httpbin.org/get"
  .httpGet()
  .responseString { request, response, result ->
    when (result) {
      is Result.Failure -> {
        val ex = result.getException()
      }
      is Result.Success -> {
        val data = result.get()
      }
    }
  }

// You can also use Fuel.get("https://httpbin.org/get").responseString { ... }
// You can also use FuelManager.instance.get("...").responseString { ... }

Образец запроса POST

Fuel.post("https://httpbin.org/post")
    .jsonBody("{ \"foo\" : \"bar\" }")
    .also { println(it) }
    .response { result -> }

Их документацию можно найти здесь