HttpHelper.kt 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import android.graphics.Bitmap
  2. import android.graphics.BitmapFactory
  3. import org.json.JSONObject
  4. import java.io.*
  5. import java.net.HttpURLConnection
  6. import java.net.URL
  7. import java.net.URLEncoder
  8. import javax.net.ssl.HttpsURLConnection
  9. /*
  10. Перед использованием не забудьте добавить в манифест
  11. разрешение
  12. <uses-permission android:name="android.permission.INTERNET" />
  13. И атрибут в тег application
  14. android:usesCleartextTraffic="true"
  15. Использование:
  16. HTTP.requestGET(
  17. "http://s4a.kolei.ru/Product",
  18. mapOf(
  19. "token" to token
  20. ),
  21. "UTF-8"
  22. ){result, error ->
  23. runOnUiThread{
  24. if(result!=null){
  25. resultTextView.text = result
  26. }
  27. else
  28. AlertDialog.Builder(this)
  29. .setTitle("Ошибка http-запроса")
  30. .setMessage(error)
  31. .setPositiveButton("OK", null)
  32. .create()
  33. .show()
  34. }
  35. }
  36. HTTP.requestPOST(
  37. "http://s4a.kolei.ru/login",
  38. JSONObject().put("username", username).put("password", password),
  39. mapOf(
  40. "Content-Type" to "application/json"
  41. ),
  42. "UTF-8"
  43. ){result, error ->
  44. runOnUiThread{
  45. if(result!=null){
  46. }
  47. else
  48. AlertDialog.Builder(this)
  49. .setTitle("Ошибка http-запроса")
  50. .setMessage(error)
  51. .setPositiveButton("OK", null)
  52. .create()
  53. .show()
  54. }
  55. }
  56. HTTP.getImage("https://openweathermap.org/img/w/${icoName}.png") { bitmap, error ->
  57. runOnUiThread {
  58. if (bitmap != null) {
  59. var imageView = findViewById<ImageView>(R.id.ico)
  60. imageView.setImageBitmap(bitmap)
  61. }
  62. }
  63. }
  64. */
  65. object HTTP
  66. {
  67. private const val GET : String = "GET"
  68. private const val POST : String = "POST"
  69. private fun getCharSet(url: String): String{
  70. val obj = URL(url)
  71. var con: HttpURLConnection = if(url.startsWith("https:", true))
  72. obj.openConnection() as HttpsURLConnection
  73. else
  74. obj.openConnection() as HttpURLConnection
  75. con.requestMethod = "HEAD"
  76. val contentType = con.contentType
  77. return if(contentType.contains("Windows-1251", true))
  78. "Windows-1251"
  79. else
  80. "UTF-8"
  81. }
  82. /**
  83. * Метод для отправки POST-запросов
  84. *
  85. * Запросы отправляются в отдельном потоке
  86. * Автоматически поддерживает http/httpS
  87. * Можно задать заголовки запроса
  88. * По-умолчанию отправляет данные в формате application/x-www-form-urlencoded
  89. * при задании заголовка Content-type: application/json автоматически переключается на это тип
  90. *
  91. * @param url Полный URL сайта (протокол + домен + путь)
  92. * @param postData Даные для отправки
  93. * @param headers Ассоциативный массив заголовков запроса
  94. * @param callback Лямбда-функция обратного вызова
  95. */
  96. fun requestPOST(
  97. url: String,
  98. postData: JSONObject? = null,
  99. headers: Map<String, String>?,
  100. callback: (result: String?, error: String)->Unit
  101. ) {
  102. Thread( Runnable {
  103. var error = ""
  104. var result: String? = null
  105. try {
  106. val charset = getCharSet(url)
  107. val urlURL = URL(url)
  108. val conn: HttpURLConnection = if (url.startsWith("https:", true))
  109. urlURL.openConnection() as HttpsURLConnection
  110. else
  111. urlURL.openConnection() as HttpURLConnection
  112. // если задан тип контента application/json, то на выход пишу как есть
  113. var contentTypeJson = false
  114. if(headers!=null){
  115. for((key, value) in headers){
  116. if(key.lowercase()=="content-type" && value.startsWith("application/json"))
  117. contentTypeJson = true
  118. conn.setRequestProperty(key, value)
  119. }
  120. }
  121. conn.readTimeout = 10000
  122. conn.connectTimeout = 10000
  123. conn.requestMethod = POST
  124. conn.doInput = true
  125. conn.doOutput = true
  126. val os: OutputStream = conn.outputStream
  127. if (postData != null) {
  128. val writer = BufferedWriter(OutputStreamWriter(os, "UTF-8"))
  129. var content = ""
  130. content = if(contentTypeJson)
  131. postData.toString()
  132. else
  133. encodeParams(postData)?:""
  134. writer.write(content)
  135. writer.flush()
  136. writer.close()
  137. }
  138. os.close()
  139. val responseCode: Int = conn.responseCode // To Check for 200
  140. if (responseCode == HttpsURLConnection.HTTP_OK) {
  141. val `in` = BufferedReader(InputStreamReader(conn.inputStream, charset))
  142. val sb = StringBuffer("")
  143. var line: String? = ""
  144. while (`in`.readLine().also { line = it } != null) {
  145. sb.append(line)
  146. break
  147. }
  148. `in`.close()
  149. result = sb.toString()
  150. }
  151. else {
  152. error = "Response code ${responseCode}"
  153. }
  154. }
  155. catch (e: Exception) {
  156. error = e.message.toString()
  157. }
  158. callback.invoke(result, error)
  159. }).start()
  160. }
  161. fun getImage(url: String, callback: (result: Bitmap?, error: String)->Unit){
  162. Thread( Runnable {
  163. var image: Bitmap? = null
  164. var error = ""
  165. try {
  166. val `in` = URL(url).openStream()
  167. image = BitmapFactory.decodeStream(`in`)
  168. }
  169. catch (e: Exception) {
  170. error = e.message.toString()
  171. }
  172. callback.invoke(image, error)
  173. }).start()
  174. }
  175. fun requestGET(
  176. r_url: String,
  177. headers: Map<String, String>?,
  178. callback: (result: String?, error: String)->Unit
  179. ) {
  180. Thread( Runnable {
  181. var error = ""
  182. var result: String? = null
  183. try {
  184. val charset = getCharSet(r_url)
  185. val obj = URL(r_url)
  186. val con: HttpURLConnection = if(r_url.startsWith("https:", true))
  187. obj.openConnection() as HttpsURLConnection
  188. else
  189. obj.openConnection() as HttpURLConnection
  190. if(headers!=null){
  191. for((key, value) in headers){
  192. con.setRequestProperty(key, value)
  193. }
  194. }
  195. con.requestMethod = GET
  196. val responseCode = con.responseCode
  197. result = if (responseCode == HttpURLConnection.HTTP_OK) { // connection ok
  198. val `in` =
  199. BufferedReader(InputStreamReader(con.inputStream, charset))
  200. var inputLine: String?
  201. val response = StringBuffer()
  202. while (`in`.readLine().also { inputLine = it } != null) {
  203. response.append(inputLine)
  204. }
  205. `in`.close()
  206. response.toString()
  207. } else {
  208. null
  209. }
  210. }
  211. catch (e: Exception){
  212. error = e.message.toString()
  213. }
  214. callback.invoke(result, error)
  215. }).start()
  216. }
  217. @Throws(IOException::class)
  218. private fun encodeParams(params: JSONObject): String? {
  219. val result = StringBuilder()
  220. var first = true
  221. val itr = params.keys()
  222. while (itr.hasNext()) {
  223. val key = itr.next()
  224. val value = params[key]
  225. if (first) first = false else result.append("&")
  226. result.append(URLEncoder.encode(key, "UTF-8"))
  227. result.append("=")
  228. result.append(URLEncoder.encode(value.toString(), "UTF-8"))
  229. }
  230. return result.toString()
  231. }
  232. }