diff --git a/README.md b/README.md
index a7767508..54e4a0f5 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,8 @@
- 코드 복사
- API 받아오기
-1단계
+1단계 ✅
+
: 이전 단계와 기능은 비슷하나 카카오로컬 API를 사용한다.
- 검색어를 입력하면 검색 결과가 15개 이상 표시된다.
- 검색 결과 목록은 세로 스크롤이 된다.
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index ea1318a5..d5acde28 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -1,8 +1,18 @@
+import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
+import java.util.Properties
+
+fun getApiKey(key: String): String {
+ return gradleLocalProperties(rootDir, providers).getProperty(key) ?: ""
+}
+
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
}
+val properties = Properties()
+properties.load(project.rootProject.file("local.properties").inputStream())
+
android {
namespace = "campus.tech.kakao.map"
compileSdk = 34
@@ -15,6 +25,10 @@ android {
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+
+ buildConfigField("String", "API_KEY", "\"${getApiKey("API_KEY")}\"")
+ buildConfigField("String", "MAP_API_KEY", "\"${getApiKey("MAP_API_KEY")}\"")
+
}
buildTypes {
@@ -36,6 +50,7 @@ android {
buildFeatures {
viewBinding = true
+ buildConfig = true
}
}
@@ -51,6 +66,9 @@ dependencies {
implementation("com.google.code.gson:gson:2.9.0")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
+ implementation("com.kakao.maps.open:android:2.9.5")
+ implementation("com.kakao.sdk:v2-all:2.20.3")
+ implementation("androidx.activity:activity:1.9.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 576393e5..525ede22 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,10 @@
+
+
+
+
+
@@ -21,6 +29,10 @@
+
+
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/map/KakaoLocalApi.kt b/app/src/main/java/campus/tech/kakao/map/Model/KakaoLocalApi.kt
similarity index 90%
rename from app/src/main/java/campus/tech/kakao/map/KakaoLocalApi.kt
rename to app/src/main/java/campus/tech/kakao/map/Model/KakaoLocalApi.kt
index 6b8f6b28..e2c39c2a 100644
--- a/app/src/main/java/campus/tech/kakao/map/KakaoLocalApi.kt
+++ b/app/src/main/java/campus/tech/kakao/map/Model/KakaoLocalApi.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.Model
import retrofit2.Call
import retrofit2.http.GET
diff --git a/app/src/main/java/campus/tech/kakao/map/LocationData.kt b/app/src/main/java/campus/tech/kakao/map/Model/LocationData.kt
similarity index 73%
rename from app/src/main/java/campus/tech/kakao/map/LocationData.kt
rename to app/src/main/java/campus/tech/kakao/map/Model/LocationData.kt
index 0cdb9904..dc781959 100644
--- a/app/src/main/java/campus/tech/kakao/map/LocationData.kt
+++ b/app/src/main/java/campus/tech/kakao/map/Model/LocationData.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.Model
data class LocationData (
val name: String,
diff --git a/app/src/main/java/campus/tech/kakao/map/Model/MyApplication.kt b/app/src/main/java/campus/tech/kakao/map/Model/MyApplication.kt
new file mode 100644
index 00000000..2b65012a
--- /dev/null
+++ b/app/src/main/java/campus/tech/kakao/map/Model/MyApplication.kt
@@ -0,0 +1,20 @@
+package campus.tech.kakao.map.Model
+
+import android.app.Application
+import android.util.Log
+import campus.tech.kakao.map.BuildConfig
+import com.kakao.vectormap.KakaoMapSdk
+
+class MyApplication: Application() {
+ override fun onCreate() {
+ super.onCreate()
+
+ try {
+ KakaoMapSdk.init(this, BuildConfig.MAP_API_KEY)
+ Log.d("KakaoMapSDK", "SDK initialized successfully")
+ } catch (e: Exception) {
+ Log.e("KakaoMapSDK", "error", e)
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/map/RetrofitClient.kt b/app/src/main/java/campus/tech/kakao/map/Model/RetrofitClient.kt
similarity index 92%
rename from app/src/main/java/campus/tech/kakao/map/RetrofitClient.kt
rename to app/src/main/java/campus/tech/kakao/map/Model/RetrofitClient.kt
index 139467ce..95465ac3 100644
--- a/app/src/main/java/campus/tech/kakao/map/RetrofitClient.kt
+++ b/app/src/main/java/campus/tech/kakao/map/Model/RetrofitClient.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.Model
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
diff --git a/app/src/main/java/campus/tech/kakao/map/SearchCallback.kt b/app/src/main/java/campus/tech/kakao/map/Model/SearchCallback.kt
similarity index 75%
rename from app/src/main/java/campus/tech/kakao/map/SearchCallback.kt
rename to app/src/main/java/campus/tech/kakao/map/Model/SearchCallback.kt
index 03347cbb..3db3bcee 100644
--- a/app/src/main/java/campus/tech/kakao/map/SearchCallback.kt
+++ b/app/src/main/java/campus/tech/kakao/map/Model/SearchCallback.kt
@@ -1,11 +1,13 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.Model
import android.util.Log
+import campus.tech.kakao.map.view.MainActivity
+import campus.tech.kakao.map.viewmodel.MainViewModel
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
-class SearchCallback(private val activity: MainActivity) : Callback {
+class SearchCallback(private val activity: MainViewModel) : Callback {
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val result = response.body()
diff --git a/app/src/main/java/campus/tech/kakao/map/SearchResult.kt b/app/src/main/java/campus/tech/kakao/map/Model/SearchResult.kt
similarity index 82%
rename from app/src/main/java/campus/tech/kakao/map/SearchResult.kt
rename to app/src/main/java/campus/tech/kakao/map/Model/SearchResult.kt
index 2ddd35d9..426b5cc0 100644
--- a/app/src/main/java/campus/tech/kakao/map/SearchResult.kt
+++ b/app/src/main/java/campus/tech/kakao/map/Model/SearchResult.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.Model
data class SearchResult(
val documents: List
diff --git a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt
similarity index 83%
rename from app/src/main/java/campus/tech/kakao/map/MainActivity.kt
rename to app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt
index a51a9044..5e50669a 100644
--- a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt
+++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.view
import android.content.Context
import android.os.Bundle
@@ -9,16 +9,27 @@ import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
+import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import campus.tech.kakao.map.BuildConfig
+import campus.tech.kakao.map.viewmodel.DataDbHelper
+import campus.tech.kakao.map.viewmodel.LocationAdapter
+import campus.tech.kakao.map.Model.LocationData
+import campus.tech.kakao.map.Model.RetrofitClient
+import campus.tech.kakao.map.Model.Place
+import campus.tech.kakao.map.R
+import campus.tech.kakao.map.Model.SearchCallback
+import campus.tech.kakao.map.Model.SearchResult
+import campus.tech.kakao.map.viewmodel.MainViewModel
+import campus.tech.kakao.map.viewmodel.SearchViewAdapter
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import retrofit2.Call
-import campus.tech.kakao.map.SearchResult
class MainActivity : AppCompatActivity() {
- private val API_KEY = "KakaoAK 276613de22bf074fb398b9eed102f89b"
private lateinit var db: DataDbHelper
private lateinit var recyclerView: RecyclerView
@@ -31,16 +42,26 @@ class MainActivity : AppCompatActivity() {
private var locationList = ArrayList()
private var searchList = ArrayList()
+ private val mainViewModel: MainViewModel by viewModels()
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ mainViewModel.setUiStateChangedListener {uiState ->
+ locationList.clear()
+ locationList.addAll(uiState.locationList)
+ updateRecyclerView()
+ resultView.isVisible = uiState.isShowText
+ }
+
initialize()
loadSearchList()
setCancelBtn()
setSearchView()
setRecyclerView()
setSearchListener()
+
}
private fun initialize() {
@@ -113,7 +134,7 @@ class MainActivity : AppCompatActivity() {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
- searchLocations(s.toString())
+ mainViewModel.searchLocations(s.toString())
}
override fun afterTextChanged(s: Editable?) {}
@@ -139,33 +160,10 @@ class MainActivity : AppCompatActivity() {
Log.d("MainActivity", "Item clicked: ${locationData.name}")
}
- private fun searchLocations(key: String) {
- val apiService = RetrofitClient.instance
- val call: Call = apiService.searchPlaces(API_KEY, key)
- call.enqueue(campus.tech.kakao.map.SearchCallback(this))
- }
-
- fun updateSearchResults(results: List) {
- locationList.clear()
- for (result in results) {
- locationList.add(LocationData(result.place_name, result.address_name, result.category_group_name))
- }
- updateRecyclerView()
- isShowText()
- }
-
private fun updateRecyclerView() {
locationAdapter.notifyDataSetChanged()
}
- private fun isShowText() {
- if (locationList.isEmpty()) {
- resultView.visibility = View.VISIBLE
- } else {
- resultView.visibility = View.GONE
- }
- }
-
override fun onDestroy() {
super.onDestroy()
db.close()
diff --git a/app/src/main/java/campus/tech/kakao/map/view/MapActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MapActivity.kt
new file mode 100644
index 00000000..88637105
--- /dev/null
+++ b/app/src/main/java/campus/tech/kakao/map/view/MapActivity.kt
@@ -0,0 +1,67 @@
+package campus.tech.kakao.map.view
+
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import campus.tech.kakao.map.R
+import com.kakao.vectormap.KakaoMap
+import com.kakao.vectormap.KakaoMapReadyCallback
+import com.kakao.vectormap.LatLng
+import com.kakao.vectormap.MapLifeCycleCallback
+import com.kakao.vectormap.MapView
+import com.kakao.vectormap.camera.CameraUpdateFactory
+
+class MapActivity : AppCompatActivity() {
+
+ private lateinit var mapView: MapView
+ private lateinit var inputText: View
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_map)
+
+ mapView = findViewById(R.id.map_view)
+ inputText = findViewById(R.id.MapinputText)
+
+
+ mapView.start(
+ object : MapLifeCycleCallback() {
+ override fun onMapDestroy() {}
+ override fun onMapError(error: Exception) {
+ Log.e("MapError", "${error.message}", error)
+ }
+ },
+ object : KakaoMapReadyCallback() {
+ override fun onMapReady(kakaoMap: KakaoMap) {
+ // 맵 초기화 코드
+ val mapCenter = LatLng.from(37.566, 126.978) // 서울시청 좌표
+ kakaoMap.moveCamera(CameraUpdateFactory.newCenterPosition(mapCenter))
+ kakaoMap.moveCamera(CameraUpdateFactory.zoomTo(15))
+ }
+ }
+ )
+
+ inputText.setOnClickListener {
+ val intent = Intent(this@MapActivity, MainActivity::class.java)
+ startActivity(intent)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mapView.resume()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ mapView.pause()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ mapView.finish()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/map/DataDbHelper.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/DataDbHelper.kt
similarity index 95%
rename from app/src/main/java/campus/tech/kakao/map/DataDbHelper.kt
rename to app/src/main/java/campus/tech/kakao/map/viewmodel/DataDbHelper.kt
index d619dd24..abcd04df 100644
--- a/app/src/main/java/campus/tech/kakao/map/DataDbHelper.kt
+++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/DataDbHelper.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.viewmodel
import android.content.Context
import android.database.sqlite.SQLiteDatabase
diff --git a/app/src/main/java/campus/tech/kakao/map/LocationAdapter.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/LocationAdapter.kt
similarity index 92%
rename from app/src/main/java/campus/tech/kakao/map/LocationAdapter.kt
rename to app/src/main/java/campus/tech/kakao/map/viewmodel/LocationAdapter.kt
index 7c0b7826..a54154d3 100644
--- a/app/src/main/java/campus/tech/kakao/map/LocationAdapter.kt
+++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/LocationAdapter.kt
@@ -1,10 +1,12 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.viewmodel
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
+import campus.tech.kakao.map.Model.LocationData
+import campus.tech.kakao.map.R
class LocationAdapter(
private val locationList: List,
diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainViewModel.kt
new file mode 100644
index 00000000..b57a3340
--- /dev/null
+++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainViewModel.kt
@@ -0,0 +1,62 @@
+package campus.tech.kakao.map.viewmodel
+
+import retrofit2.Call
+import androidx.lifecycle.ViewModel
+import campus.tech.kakao.map.BuildConfig
+import campus.tech.kakao.map.Model.LocationData
+import campus.tech.kakao.map.Model.Place
+import campus.tech.kakao.map.Model.RetrofitClient
+import campus.tech.kakao.map.Model.SearchCallback
+import campus.tech.kakao.map.Model.SearchResult
+
+class MainViewModel: ViewModel() {
+
+ private var listener: (UiState) -> Unit = {}
+ private lateinit var call: Call
+
+ private var uiState: UiState = UiState(
+ locationList = emptyList(),
+ isShowText = false
+ )
+
+ fun setUiStateChangedListener(listener: (UiState) -> Unit) {
+ this.listener = listener
+ }
+
+ fun searchLocations(key: String) {
+ val apiService = RetrofitClient.instance
+ call = apiService.searchPlaces(BuildConfig.API_KEY, key)
+ call.enqueue(SearchCallback(this))
+ }
+
+ fun updateSearchResults(results: List) {
+ val locationList = mutableListOf()
+ for (result in results) {
+ locationList.add(
+ LocationData(
+ result.place_name,
+ result.address_name,
+ result.category_group_name
+ )
+ )
+ }
+ uiState = UiState(
+ locationList = locationList,
+ isShowText = locationList.isEmpty()
+ )
+
+ listener(uiState)
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ if (::call.isInitialized) {
+ call.cancel()
+ }
+ }
+
+ data class UiState(
+ val locationList: List,
+ val isShowText: Boolean
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/campus/tech/kakao/map/SearchViewAdapter.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/SearchViewAdapter.kt
similarity index 90%
rename from app/src/main/java/campus/tech/kakao/map/SearchViewAdapter.kt
rename to app/src/main/java/campus/tech/kakao/map/viewmodel/SearchViewAdapter.kt
index 2aa51ce5..9bccf0ea 100644
--- a/app/src/main/java/campus/tech/kakao/map/SearchViewAdapter.kt
+++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/SearchViewAdapter.kt
@@ -1,4 +1,4 @@
-package campus.tech.kakao.map
+package campus.tech.kakao.map.viewmodel
import android.view.LayoutInflater
import android.view.View
@@ -6,6 +6,8 @@ import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
+import campus.tech.kakao.map.Model.LocationData
+import campus.tech.kakao.map.R
class SearchViewAdapter(
private val searchList: ArrayList,
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index fc40717b..5c567b0f 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -6,7 +6,7 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".MainActivity">
+ tools:context=".view.MainActivity">
+
diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml
new file mode 100644
index 00000000..edfd3572
--- /dev/null
+++ b/app/src/main/res/layout/activity_map.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/search_item_view.xml b/app/src/main/res/layout/search_item_view.xml
index 44f96b98..08b3daea 100644
--- a/app/src/main/res/layout/search_item_view.xml
+++ b/app/src/main/res/layout/search_item_view.xml
@@ -1,7 +1,7 @@