RetrofitでRestAPIからデータを取得します

Kotlin

build.gradle

dependencies {
    implementation("com.squareup.retrofit2:retrofit:2.9.0")
    implementation("com.squareup.retrofit2:converter-gson:2.9.0")
}

retrofit(非同期通信するためのライブラリ)をimplementします

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    <uses-permission android:name="android.permission.INTERNET" />

インターネットに接続するのでパーミッションを追加します

com.exmple.myapp/network/ApiService.kt

package com.example.myapp.network

import retrofit2.Call
import retrofit2.http.GET
import com.example.myapp.model.Destination

interface ApiService {
    @GET("wp-json/custom/v1/get-destination")
    fun getDestination(): Call<List<Destination>>
}

API インターフェースの概要を定義します

今回は @GET(“REST APIのパス”) つまりREST APIからデータをGETします。

サーバーからはCustomData.ktで定義したDestinationオブジェクトのListがCall(呼び出し)されます。

そして関数getDestinationを使うことで、このListが得られるようにしておきます。

com.example.myapp/model/Destination.kt

package com.example.application0210.model

data class DestinationResponse(
    val success: Boolean,
    val data: List<Destination>
)

data class Destination(
    val id: String,
    val latitude: String,  // APIのデータが文字列なので String にする
    val longitude: String,
    val created_at: String,
    val closest_driver: String,
    val min_distance: String,
    val customer_name: String,
    val customer_sex: String,
    val customer_phone: String,
    val customer_birth: String
)

データクラスを作成します。中身はカラム名に合わせます

HomeActivity.kt

package com.example.application0210

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.TextView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.application0210.model.Destination
import com.example.application0210.model.DestinationResponse
import com.google.gson.Gson
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.IOException

class HomeActivity : AppCompatActivity() {

    private lateinit var tvLabelInfo: TextView
    private val handler = Handler(Looper.getMainLooper())
    private val updateInterval: Long = 60000 // 1分ごとに更新
    private lateinit var prefsManager: PrefsManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_home)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.home)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        prefsManager = PrefsManager(this)
        tvLabelInfo = findViewById(R.id.tvLabelInfo)

        startPolling()
    }

    private fun startPolling() {
        handler.post(object: Runnable {
            override fun run() {
                fetchDestinationData()
                handler.postDelayed(this, updateInterval)
            }
        })
    }

    private fun fetchDestinationData() {
        val url = "https://azurlane.work/wp-json/custom/v1/get-destination"
        val client = OkHttpClient()
        val request = Request.Builder().url(url).build()

        client.newCall(request).enqueue(object : okhttp3.Callback {
            override fun onFailure(call: okhttp3.Call, e: IOException) {
                Log.e("API", "Error: ${e.message}")
            }
            override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
                response.use { res ->
                    val responseBody = res.body?.string()
                    Log.d("API Response", "Response: $responseBody") // ログで確認

                    if (responseBody != null) {
                        try {
                            // DestinationResponse に変換
                            val responseObj: DestinationResponse = Gson().fromJson(responseBody, DestinationResponse::class.java)

                            // APIの `data` を取り出してリストにする
                            val destinations = responseObj.data

                            // UIを更新
                            runOnUiThread {
                                updateUI(destinations)
                            }

                        } catch (e: Exception) {
                            Log.e("API", "JSON parsing error: ${e.message}")
                        }
                    }
                }
            }
        })
    }

    private fun updateUI(destinations: List<Destination>) {
        val sb = StringBuilder()
        for (dest in destinations) {
            sb.append(
                "Lat: ${dest.latitude.toDouble()}, " +
                        "Lon: ${dest.longitude.toDouble()}, " +
                        "Driver: ${dest.closest_driver}, " +
                        "Distance: ${dest.min_distance.toDouble()}, " +
                        "CustomerName: ${dest.customer_name}, " +
                        "CustomerSex: ${dest.customer_sex}, " +
                        "CustomerPhone: ${dest.customer_phone}, " +
                        "CustomerBirth: ${dest.customer_birth}\n"
            )
        }
        tvLabelInfo.text = sb.toString()
    }

    override fun onDestroy() {
        super.onDestroy()
        handler.removeCallbacksAndMessages(null)
    }
}

※1 … Retrofit.instance.getData()でhttps://xxx.com/wp-json/xxx にアクセスしてデータを取得します。

enqueueは非同期のHTTP通信を行うという意味です。executeとすると同期通信になります。

得られるデータはList<CustomData>という形になります。

※2 … 成功したらonResponse 、失敗したらonFailure 関数を実行します

※3 … レスポンスが成功(200等)かどうかを判別します

※4 … response.body() はAPIから返ってきたJSONデータをList<CustomData>というKotlinオブジェクトに変換したものです。これがnull出ない場合?.let {}内の処理を行います。

BACK