1.表題
Javaで作成したAPIをAndroidアプリから呼び出して、APIの結果をAndroidアプリに表示させます。
2.動作環境
AndroidStudio、Kotlin
※APIは事前にEclipseでBootRun済とする。
3.使用するAPI
自作の料理IDに紐づくアレルギー情報API
http://localhost:8080/api/RecipeAllergyInfo?recipeId=1
{
"result": {
"success": true,
"info": [
{
"allergyId": 1
},
{
"allergyId": 4
},
{
"allergyId": 5
}
]
}
}
http://localhost:8080/api/RecipeAllergyInfo?recipeId=2
{
"result": {
"success": true,
"info": [
{
"allergyId": 2
},
{
"allergyId": 3
},
{
"allergyId": 6
}
]
}
}
4.仕様
2.レシピID=1で入力時
→ (3.使用するAPIの結果)で返ってきた結果がカンマ区切りで表示されている。
3.レシピID=2で入力時
→ (3.使用するAPIの結果)で返ってきた結果がカンマ区切りで表示されている
5.コーディング
(1) レイアウト(AndroidManifest.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="16dp">
<EditText
android:id="@+id/idInput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="アレルギーIDを入力"
android:inputType="number" />
<Button
android:id="@+id/searchButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="検索" />
<TextView
android:id="@+id/resultTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[アレルギー検索結果]"
android:textSize="18sp" />
</LinearLayout>
(2) API設定
戻りのクラス(AllergyResponse.kt)
package com.example.myfirstapp.api
data class AllergyResponse(
val result: Result
)
data class Result(
val success: Boolean,
val info: List<AllergyInfo>
)
data class AllergyInfo(
val allergyId: Int
)
APIのサービス設定(ApiService.kt)
package com.example.myfirstapp.api
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface ApiService {
@GET("api/RecipeAllergyInfo")
fun getAllergyInfo(@Query("recipeId") recipeId: Int): Call<AllergyResponse>
}
Retrofitライブラリを使用してAPI通信を行う際に、Retrofitのインスタンスを生成し、そのインスタンスを管理するためのクラスやオブジェクト(RetrofitInstance.kt)
package com.example.myfirstapp.api
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitInstance {
val api: ApiService by lazy {
Retrofit.Builder()
.baseUrl("http://10.0.2.2:8080/")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
(3) kotlin側
package com.example.myfirstapp
import android.os.Bundle
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import com.example.myfirstapp.api.RetrofitInstance
import com.example.myfirstapp.api.AllergyResponse
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
private lateinit var resultTextView: TextView
private lateinit var idInput: EditText
private lateinit var searchButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
resultTextView = findViewById(R.id.resultTextView)
idInput = findViewById(R.id.idInput)
searchButton = findViewById(R.id.searchButton)
searchButton.setOnClickListener {
val inputText = idInput.text.toString()
if (inputText.isNotEmpty()) {
val id = inputText.toInt()
fetchAllergyInfo(id)
} else {
Toast.makeText(this, "アレルギーIDを入力してください", Toast.LENGTH_SHORT).show()
}
}
}
private fun fetchAllergyInfo(id: Int) {
resultTextView.text = "読み込み中..."
RetrofitInstance.api.getAllergyInfo(id).enqueue(object : Callback<AllergyResponse> {
override fun onResponse(call: Call<AllergyResponse>, response: Response<AllergyResponse>) {
if (response.isSuccessful) {
val allergyIds = response.body()?.result?.info?.joinToString(", ") { it.allergyId.toString() }
resultTextView.text = "Allergy IDs: $allergyIds"
} else {
resultTextView.text = "エラー: ${response.code()}"
}
}
override fun onFailure(call: Call<AllergyResponse>, t: Throwable) {
resultTextView.text = "通信エラー: ${t.message}"
}
})
}
}
(4) 設定ファイル(gradle.ktsファイル)
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
}
android {
namespace = "com.example.myfirstapp"
compileSdk = 35
defaultConfig {
applicationId = "com.example.myfirstapp"
minSdk = 21
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
buildFeatures {
compose = true
}
}
dependencies {
// Retrofit & Gson
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
// Coroutine(API呼び出しを非同期で行うため)
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
6.終わりに
Andoroid StudioとAPIの連携の調査まで終わったので、今後作成予定の課題にそろそろ実装を着手していこうかなというところです。