KotlinでAPI接続の設定〜お天気情報編〜

ListViewでタップされた都市のお天気情報を表示するだけです。
Livedoorさんのお天気情報を使用します。

# 表示xmlの作成
stringは適宜いい感じに

```xml:activity_main.xml
  <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

<!--        上-->
        <ListView
            android:id="@+id/lvCityList"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.5" />

<!--        下-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.5"
            android:orientation="vertical">

<!--            タイトル-->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:text="@string/tv_winfo_title"
                android:gravity="center"
                android:textSize="25dp" />
<!--            中身-->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

<!--                都市名-->
                <TextView
                    android:id="@+id/tvCityName"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="25dp" />
<!--                天気テロップ-->
                <TextView
                    android:id="@+id/tvWetherTelop"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:textSize="20sp" />


            </LinearLayout>

            <ScrollView
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

<!--                天気情報-->
                <TextView
                    android:id="@+id/tvWetherDesc"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textSize="15sp" />

            </ScrollView>

        </LinearLayout>

    </LinearLayout>
```
# MainActivity.ktの編集
解説しながらやっていきたい

```kotlin:MainActivity.kt
package com.websarva.wings.android.asyncsample

import android.os.AsyncTask
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ListView
import android.widget.SimpleAdapter
import android.widget.TextView
import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //❶SimpleAdapterを作成して、クリック処理の呼び出しまで
        val lvCityList = findViewById<ListView>(R.id.lvCityList)
        val cityList: MutableList<MutableMap<String,String>> = mutableListOf()
        var city = mutableMapOf("name" to "大阪" , "id" to "270000") //このIDはAPI用
        cityList.add(city)
        city = mutableMapOf("name" to "神戸" , "id" to "280010") //このIDはAPI用
        cityList.add(city)
        val from = arrayOf("name")
        val to = intArrayOf(android.R.id.text1)
        val adapter = SimpleAdapter(applicationContext,cityList,android.R.layout.simple_expandable_list_item_1,from,to)
        lvCityList.adapter = adapter
        //タップしたときの処理
        lvCityList.onItemClickListener = ListItemClickListener()
    }

    //＊クリックでクリックした都市を表示
    private inner class ListItemClickListener: AdapterView.OnItemClickListener{
        override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
            //タップされた都市名と都市IDを取得
            val item = parent?.getItemAtPosition(position) as Map<String,String>
            val cityName = item["name"]
            val cityId = item["id"]
//            取得した都市をtvで表示するように登録
            val tvCityName = findViewById<TextView>(R.id.tvCityName)
            tvCityName.setText(cityName + "天気：")
            //❷タップされたときにお天気情報取得の処理を呼び出す
            val receiver = WeatherInfoReceiver()
            //実行（★IDを渡す）
            receiver.execute(cityId)
        }
    }
    //＊AsyncTaskを継承するメンバクラスを作成
    private inner class WeatherInfoReceiver(): AsyncTask<String,String,String>() {
        //バックグラウンド処理
        override fun doInBackground(vararg params: String?): String {
            val id = params[0]
            val urlStr = "http://weather.livedoor.com/forecast/webservice/json/v1?city=${id}"

            //❸接続処理
            val url = URL(urlStr)
            val con = url.openConnection() as HttpURLConnection
            con.requestMethod = "GET"
            con.connect()
            val stream = con.inputStream
            val result = is2String(stream)

            con.disconnect()
            stream.close()
            //onPostExecuteへ渡す
            return result
        }
        //❹解析
        override fun onPostExecute(result: String?) {
            //文字解析
            val rootJSON = JSONObject(result)
            //項目1つ抜き出す
            val descriptionJSON = rootJSON.getJSONObject("description")
            val desc = descriptionJSON.getString("text")
            //配列ごと抜き出す
            val forecasts = rootJSON.getJSONArray("forecasts")
            //配列の一つ目のJSONオブジェクト
            val forecastsNow = forecasts.getJSONObject(0)
            val telop = forecastsNow.getString("telop")

            //天気情報用文字列をセット
            val tvWeatherTelop = findViewById<TextView>(R.id.tvWetherTelop)
            val tvWeatherDesc = findViewById<TextView>(R.id.tvWetherDesc)
            tvWeatherTelop.text = telop
            tvWeatherDesc.text = desc
        }
//        文字型変換　どこでもソース落ちてます！
        private fun is2String(stream: InputStream): String {
            val sb = StringBuilder()
            val reader = BufferedReader(InputStreamReader(stream, "UTF-8"))
            var line = reader.readLine()
            while(line != null) {
                sb.append(line)
                line = reader.readLine()
            }
            reader.close()
            return sb.toString()
        }


    }
}

```