diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index a2cf405..639c779 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -9,8 +9,8 @@
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 0c6dbbc..54940a1 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,3 +1,5 @@
+import java.util.Properties
+
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
@@ -18,6 +20,13 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ val properties = Properties()
+ val localPropertiesFile = rootProject.file("local.properties")
+ if (localPropertiesFile.exists()) {
+ properties.load(localPropertiesFile.inputStream())
+ }
+ val baseUrl = properties.getProperty("BASE_URL")// ?: "http://10.0.2.2:8080/"
+ buildConfigField("String", "BASE_URL", "\"$baseUrl\"")
}
buildTypes {
@@ -38,6 +47,7 @@ android {
}
buildFeatures {
compose = true
+ buildConfig = true
}
}
@@ -74,4 +84,10 @@ dependencies {
androidTestImplementation(libs.androidx.espresso.core)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest)
+
+ // Retrofit & OkHttp
+ implementation(libs.retrofit)
+ implementation(libs.retrofit.converter.gson)
+ implementation(libs.okhttp)
+ implementation(libs.okhttp.logging.interceptor)
}
diff --git a/app/src/main/java/com/example/kuit6_android_api/MainActivity.kt b/app/src/main/java/com/example/kuit6_android_api/MainActivity.kt
index 5129dff..bdb11e1 100644
--- a/app/src/main/java/com/example/kuit6_android_api/MainActivity.kt
+++ b/app/src/main/java/com/example/kuit6_android_api/MainActivity.kt
@@ -1,6 +1,7 @@
package com.example.kuit6_android_api
import android.Manifest
+import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
@@ -8,9 +9,14 @@ import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
+import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.core.content.ContextCompat
import androidx.navigation.compose.rememberNavController
@@ -32,6 +38,7 @@ class MainActivity : ComponentActivity() {
}
}
+ @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -40,15 +47,23 @@ class MainActivity : ComponentActivity() {
setContent {
KUIT6_Android_APITheme {
- Surface(
- modifier = Modifier.fillMaxSize(),
- color = MaterialTheme.colorScheme.background
+
+ val snackBarState = remember { SnackbarHostState() }
+
+ Scaffold(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(MaterialTheme.colorScheme.background),
+ snackbarHost = {
+ SnackbarHost(snackBarState)
+ }
) {
val navController = rememberNavController()
NavGraph(
navController = navController,
- startDestination = PostListRoute
+ startDestination = PostListRoute,
+ snackBarState = snackBarState
)
}
}
@@ -71,6 +86,7 @@ class MainActivity : ComponentActivity() {
) == PackageManager.PERMISSION_GRANTED -> {
// 이미 권한이 있음
}
+
shouldShowRequestPermissionRationale(permission) -> {
// 권한 거부 이력이 있음 - 설명 표시 후 재요청
Toast.makeText(
@@ -80,6 +96,7 @@ class MainActivity : ComponentActivity() {
).show()
requestPermissionLauncher.launch(permission)
}
+
else -> {
// 권한 요청
requestPermissionLauncher.launch(permission)
diff --git a/app/src/main/java/com/example/kuit6_android_api/data/api/ApiService.kt b/app/src/main/java/com/example/kuit6_android_api/data/api/ApiService.kt
new file mode 100644
index 0000000..ff80c60
--- /dev/null
+++ b/app/src/main/java/com/example/kuit6_android_api/data/api/ApiService.kt
@@ -0,0 +1,57 @@
+package com.example.kuit6_android_api.data.api
+
+
+import com.example.kuit6_android_api.data.model.request.PostCreateRequest
+import com.example.kuit6_android_api.data.model.response.BaseResponse
+import com.example.kuit6_android_api.data.model.response.PostResponse
+import okhttp3.MultipartBody
+import retrofit2.http.Body
+import retrofit2.http.DELETE
+import retrofit2.http.GET
+import retrofit2.http.Multipart
+import retrofit2.http.POST
+import retrofit2.http.PUT
+import retrofit2.http.Part
+import retrofit2.http.Path
+import retrofit2.http.Query
+
+interface ApiService {
+ // 게시글 목록 조회
+ // http://3.34.136.227:8080/api/posts
+ @GET(value = "/api/posts")
+ suspend fun getPosts(): BaseResponse> // suspend fun: 일시 중단 될 수도 있는 함수
+
+ // 게시글 생성
+ // http://3.34.136.227:8080/api/posts
+ @POST(value = "/api/posts")
+ suspend fun createPost(
+ @Query(value = "author") author: String = "anonymous",
+ @Body request: PostCreateRequest
+ ): BaseResponse
+
+ // 게시글 상세 조회
+ @GET(value = "/api/posts/{id}")
+ suspend fun getDetail(
+ @Path("id") id: Long
+ ): BaseResponse
+
+ // 게시글 수정 [스낵바 - 6주차 미션]
+ @PUT(value = "/api/posts/{id}")
+ suspend fun updatePost(
+ @Path(value = "id") id: Long,
+ @Body request: PostCreateRequest
+ ): BaseResponse
+
+ // 게시글 삭제 [스낵바 - 6주차 미션]
+ @DELETE(value = "/api/posts/{id}")
+ suspend fun deletePost(
+ @Path("id") id: Long
+ ): BaseResponse // 서버가 data 없으면 Unit/Any? 로 받기
+
+ // 이미지 업로드
+ @Multipart
+ @POST("/api/images/upload")
+ suspend fun uploadImage(
+ @Part file: MultipartBody.Part
+ ): BaseResponse