Skip to content

Commit

Permalink
부산대 Android_김정희_6주차 과제_0단계 (kakao-tech-campus-2nd-step2#13)
Browse files Browse the repository at this point in the history
* Initial commit

* Initial commit

* Docs: README 작성

* Add: 검색어 삭제 버튼 사진 추가

* Design: 검색어 입력 및 검색 결과 표시 기본 레이아웃 구현

* Add: strings.xml 추가

* Feat: 데이터베이스 스키마 정의

* Feat: SQliteOpenHelper 상속

* Feat: ViewModel 생성

* Feat: 데이터 삽입 기능 구현

* Add: strings.xml 한글 리소스 추가

* Docs: step2 README 작성

* Comment: SearchView 주석 삭제

* Design: 검색어 저장 목록 아이템 디자인

* Design: 검색 결과 목록 아이템 디자인

* Add: 마커 아이콘 추가

* Feat: 데이터 존재 체킹 및 데이터 검색, 반환 기능 추가

* Feat: 검색어 저장 목록 관리 및 표시

* Feat: 검색 결과 목록 관리 및 표시

* Feat: DB에서 검색어와 일치하는 장소 검색 기능

* Feat: 검색 및 검색 결과-검색어 저장 목록 관리, 표시

* Initial commit

* Docs: README 기능 작성

* Chore: 카카오 API 키 저장

* Design: 장소명 글씨 크기 변경

* Remove: insertData 기능 삭제

* Feat: Retrofit 인터페이스 생성

* Feat: Retrofit 클라이언트 설정

* Feat: 카카오 API 호출

* Feat: DTO 파일 생성

* Design: 검색 결과 목록 아이템 크기 수정

* Fix: Document-category_group_name 으로 변경

* Fix: Document-category_group_name 으로 변경

* Design: 지도 화면 구성

* Docs: 3주차 과제 2단계 기능 명세

* Chore: MapActivity 인텐트 필터 추가 및 application 이름 설정

* Feat: KakaoMapSdk.init 호출

* Design: 검색 결과 항목 디자인 수정

* Feat: 뒤로가기 버튼 클릭시 화면 이동 기능 추가

* Feat: 지도 시작 및 검색창 클릭시 화면 이동 기능 추가

* Add: 돋보기 이미지 추가

* Add: strings 리소스 추가

* Chore: 카카오지도 SDK 의존성 추가 및 에뮬레이터 설정

* Feat: MapView resume, pause 호출

* Chore: HTTP 트래픽 차단 해결 (네트워크 보안 구성 변경)

* Fix: private 변수로 변경

* Fix: 네트워크 에러 메세지 표시

* Comment: 키 해시 주석 제거

* Docs: README 기능 작성

* Feat: 저장된 검색어 선택시 해당 검색어 검색 결과 표시(검색창 자동 입력)

* 부산대 Android_김정희_4주차 과제_0단계 (kakao-tech-campus-2nd-step2#25)

* Initial commit

* Docs: README 작성

* Add: 검색어 삭제 버튼 사진 추가

* Design: 검색어 입력 및 검색 결과 표시 기본 레이아웃 구현

* Add: strings.xml 추가

* Feat: 데이터베이스 스키마 정의

* Feat: SQliteOpenHelper 상속

* Feat: ViewModel 생성

* Feat: 데이터 삽입 기능 구현

* Add: strings.xml 한글 리소스 추가

* Docs: step2 README 작성

* Comment: SearchView 주석 삭제

* Design: 검색어 저장 목록 아이템 디자인

* Design: 검색 결과 목록 아이템 디자인

* Add: 마커 아이콘 추가

* Feat: 데이터 존재 체킹 및 데이터 검색, 반환 기능 추가

* Feat: 검색어 저장 목록 관리 및 표시

* Feat: 검색 결과 목록 관리 및 표시

* Feat: DB에서 검색어와 일치하는 장소 검색 기능

* Feat: 검색 및 검색 결과-검색어 저장 목록 관리, 표시

* Initial commit

* Docs: README 기능 작성

* Chore: 카카오 API 키 저장

* Design: 장소명 글씨 크기 변경

* Remove: insertData 기능 삭제

* Feat: Retrofit 인터페이스 생성

* Feat: Retrofit 클라이언트 설정

* Feat: 카카오 API 호출

* Feat: DTO 파일 생성

* Design: 검색 결과 목록 아이템 크기 수정

* Fix: Document-category_group_name 으로 변경

* Fix: Document-category_group_name 으로 변경

* Design: 지도 화면 구성

* Docs: 3주차 과제 2단계 기능 명세

* Chore: MapActivity 인텐트 필터 추가 및 application 이름 설정

* Feat: KakaoMapSdk.init 호출

* Design: 검색 결과 항목 디자인 수정

* Feat: 뒤로가기 버튼 클릭시 화면 이동 기능 추가

* Feat: 지도 시작 및 검색창 클릭시 화면 이동 기능 추가

* Add: 돋보기 이미지 추가

* Add: strings 리소스 추가

* Chore: 카카오지도 SDK 의존성 추가 및 에뮬레이터 설정

* Feat: MapView resume, pause 호출

* Chore: HTTP 트래픽 차단 해결 (네트워크 보안 구성 변경)

* Fix: private 변수로 변경

* Fix: 네트워크 에러 메세지 표시

* Comment: 키 해시 주석 제거

---------

Co-authored-by: MyStoryG <[email protected]>

* Add: 마커 아이콘 이미지 추가

* Comment: 빌드 오류 막기 위해 주석 처리

* Feat: 데이터 넘겨주는 기능 추가

* Feat: 선택 항목 지도 표시 및 마지막 위치 저장 기능

* Refactor: 코드 리팩토링

* Feat: 위도, 경도 데이터 추가

* Design: BottomSheet 래이아웃 디자인

* Feat: BottomSheet 띄우는 기능 추가

* Add: 한글 리소스 추가

* Design: 에러 메세지 화면 디자인

* Add: 로딩 이미지 추가

* Design: errorLayout 추가

* Feat: 카카오지도 onMapError() 호출 시 에러 화면 띄우는 기능 추가

* Initial commit

* Docs: Step2 기능 작성

* Test: MainActivity UI 테스트 실행

* Test: MapActivity UI 테스트 실행

* Style: 테스트를 위해 public으로 변수 변경

* Test: MainActivity 단위 테스트 실행

* Style: 테스트를 위해 public으로 변수 변경

* Test: MapActivity 단위 테스트 실행

* 부산대 Android_김정희_4주차 과제_1단계 (kakao-tech-campus-2nd-step2#49)

* Initial commit

* Docs: README 작성

* Add: 검색어 삭제 버튼 사진 추가

* Design: 검색어 입력 및 검색 결과 표시 기본 레이아웃 구현

* Add: strings.xml 추가

* Feat: 데이터베이스 스키마 정의

* Feat: SQliteOpenHelper 상속

* Feat: ViewModel 생성

* Feat: 데이터 삽입 기능 구현

* Add: strings.xml 한글 리소스 추가

* Docs: step2 README 작성

* Comment: SearchView 주석 삭제

* Design: 검색어 저장 목록 아이템 디자인

* Design: 검색 결과 목록 아이템 디자인

* Add: 마커 아이콘 추가

* Feat: 데이터 존재 체킹 및 데이터 검색, 반환 기능 추가

* Feat: 검색어 저장 목록 관리 및 표시

* Feat: 검색 결과 목록 관리 및 표시

* Feat: DB에서 검색어와 일치하는 장소 검색 기능

* Feat: 검색 및 검색 결과-검색어 저장 목록 관리, 표시

* Initial commit

* Docs: README 기능 작성

* Chore: 카카오 API 키 저장

* Design: 장소명 글씨 크기 변경

* Remove: insertData 기능 삭제

* Feat: Retrofit 인터페이스 생성

* Feat: Retrofit 클라이언트 설정

* Feat: 카카오 API 호출

* Feat: DTO 파일 생성

* Design: 검색 결과 목록 아이템 크기 수정

* Fix: Document-category_group_name 으로 변경

* Fix: Document-category_group_name 으로 변경

* Design: 지도 화면 구성

* Docs: 3주차 과제 2단계 기능 명세

* Chore: MapActivity 인텐트 필터 추가 및 application 이름 설정

* Feat: KakaoMapSdk.init 호출

* Design: 검색 결과 항목 디자인 수정

* Feat: 뒤로가기 버튼 클릭시 화면 이동 기능 추가

* Feat: 지도 시작 및 검색창 클릭시 화면 이동 기능 추가

* Add: 돋보기 이미지 추가

* Add: strings 리소스 추가

* Chore: 카카오지도 SDK 의존성 추가 및 에뮬레이터 설정

* Feat: MapView resume, pause 호출

* Chore: HTTP 트래픽 차단 해결 (네트워크 보안 구성 변경)

* Fix: private 변수로 변경

* Fix: 네트워크 에러 메세지 표시

* Comment: 키 해시 주석 제거

* Docs: README 기능 작성

* Feat: 저장된 검색어 선택시 해당 검색어 검색 결과 표시(검색창 자동 입력)

* Add: 마커 아이콘 이미지 추가

* Comment: 빌드 오류 막기 위해 주석 처리

* Feat: 데이터 넘겨주는 기능 추가

* Feat: 선택 항목 지도 표시 및 마지막 위치 저장 기능

* Refactor: 코드 리팩토링

* Feat: 위도, 경도 데이터 추가

* Design: BottomSheet 래이아웃 디자인

* Feat: BottomSheet 띄우는 기능 추가

* Add: 한글 리소스 추가

* Design: 에러 메세지 화면 디자인

* Add: 로딩 이미지 추가

* Design: errorLayout 추가

* Feat: 카카오지도 onMapError() 호출 시 에러 화면 띄우는 기능 추가

---------

Co-authored-by: MyStoryG <[email protected]>

* Refactor: 패키지 분리

* Docs: Step1 기능 명세

* Feat: Room 데이터베이스 정의

* Feat: 데이터베이스 작업 정의

* Feat: 데이터 소스 관리 Repository 정의

* Feat: 데이터 로직 처리

* Feat: Room 데이터 불러와서 UI 업데이트하는 기능 추가

* Feat: Room 데이터베이스 엔티티 정의

* Feat: Hilt 초기화

* Feat: 의존성 주입 모듈 추가

* Feat: Hilt 사용하여 ViewModel 주입 설정

* Feat: Hilt 의존성 주입 적용

* Feat: Hilt 사용하여 DAO 주입

* Feat: Hilt 사용하여 Application, Repository 주입 설정

* Fix: step1 피드백 반영

* Docs: Step2 기능 명세

* Feat: 검색창 클릭시 데이터 초기화 기능 추가

* Feat: 커스텀 어댑터 추가

* Refactor: MainActivity MVVM 패턴 적용

* Refactor: MapActivity MVVM 패턴 적용

* Refactor: MapActivity(error_layout.xml) MVVM 패턴 적용

* Remove: 커스텀 어댑터 삭제

* Refactor: MainActivity MVVM 패턴 적용 수정

* Refactor: 코루틴을 사용하여 MapViewModel 비동기 처리 개선

* Refactor: MainActivity MVVM 패턴 적용 수정

* Fix: 검색창 클릭시 DB 초기화 기능 삭제

* Refactor: MapActivity MVVM 패턴 적용 수정(bottom_sheet)

* Feat: 불필요한 부분 수정

* Fix: 4주차 2단계 피드백 반영

---------

Co-authored-by: MyStoryG <[email protected]>
Co-authored-by: 이오형 leo <[email protected]>
  • Loading branch information
3 people authored Jul 29, 2024
1 parent 2967c62 commit 4494e4e
Show file tree
Hide file tree
Showing 39 changed files with 1,626 additions and 36 deletions.
43 changes: 42 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import java.io.FileInputStream
import java.util.Properties

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jlleitschuh.gradle.ktlint")
id("kotlin-parcelize")
id("kotlin-kapt")
id("com.google.dagger.hilt.android")
id("com.google.gms.google-services")
//id("com.google.gms.google-services")
}

android {
Expand All @@ -20,6 +24,17 @@ android {
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

resValue("string", "kakao_api_key", getApiKey("KAKAO_API_KEY"))
buildConfigField("String", "KAKAO_REST_API_KEY", "\"" + getApiKey("KAKAO_REST_API_KEY") + "\"")

ndk {
abiFilters.add("arm64-v8a")
abiFilters.add("armeabi-v7a")
abiFilters.add("x86")
abiFilters.add("x86_64")
}

}

buildTypes {
Expand All @@ -40,13 +55,35 @@ android {
}

buildFeatures {
viewBinding = true
dataBinding = true
buildConfig = true
}
}

fun getApiKey(key: String): String {
val properties = Properties()
val localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
properties.load(FileInputStream(localPropertiesFile))
}
return properties.getProperty(key) ?: throw IllegalArgumentException("API key not found for: " + key)
}

dependencies {

implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.11.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.datastore:datastore-preferences:1.0.0")
implementation("com.kakao.sdk:v2-all:2.20.3")
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("androidx.activity:activity:1.8.0")
implementation("androidx.test:core-ktx:1.5.0")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.appcompat:appcompat:1.7.0")
implementation("com.google.android.material:material:1.12.0")
Expand Down Expand Up @@ -74,6 +111,10 @@ dependencies {
testImplementation("io.mockk:mockk-agent:1.13.11")
testImplementation("androidx.arch.core:core-testing:2.2.0")
testImplementation("org.robolectric:robolectric:4.11.1")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
androidTestImplementation("androidx.test:rules:1.5.0")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.5.1")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package campus.tech.kakao.map.uiTest

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import campus.tech.kakao.map.R
import campus.tech.kakao.map.ui.MainActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MainActivityTest {

@get:Rule
val activityRule = ActivityScenarioRule(MainActivity::class.java)

// 검색어를 입력하면 올바른 결과가 뜨나요?
@Test
fun testEnteringKeywordCorrectResult() {
onView(withId(R.id.etKeywords)).perform(typeText("london"))

Thread.sleep(2000)

onView(withId(R.id.rvSearchResult))
.check(matches(hasDescendant(withText("london1118"))))
}

// 결과를 클릭하면 지도 화면으로 올바르게 이동하나요?
@Test
fun testClickingResultsTakeMapScreenCorrectly() {
onView(withId(R.id.etKeywords)).perform(typeText("london"))

Thread.sleep(2000)

onView(withText("london1118")).perform(click())

Thread.sleep(500)

onView(withId(R.id.mapView)).check(matches(isDisplayed()))
}

// 검색어 입력 후 삭제 버튼을 누르면 검색어가 잘 삭제되나요?
@Test
fun testKeywordDeletedByPressingDeleteButton() {
onView(withId(R.id.etKeywords)).perform(typeText("london"))

onView(withId(R.id.ivClear)).perform(click())

onView(withId(R.id.etKeywords)).check(matches(withText("")))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package campus.tech.kakao.map.uiTest

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import campus.tech.kakao.map.R
import campus.tech.kakao.map.ui.MapActivity
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MapActivitiyTest {

@get:Rule
val activityRule = ActivityScenarioRule(MapActivity::class.java)

// 지도 화면이 잘 보이나요?
@Test
fun testMapScreenVisible() {
onView(withId(R.id.mapView)).check(matches(isDisplayed()))
}

// 검색창을 클릭하면 검색 화면으로 잘 넘어가나요?
@Test
fun testClickingSearchBarMovesToSearchScreen() {
onView(withId(R.id.etMapSearch)).perform(click())

onView(withId(R.id.etKeywords)).check(matches(isDisplayed()))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package campus.tech.kakao.map.unitTest

import android.view.View
import android.widget.EditText
import android.widget.TextView
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import campus.tech.kakao.map.R
import campus.tech.kakao.map.ui.MainActivity
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertTrue
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MainActivityUnitTest {

private lateinit var scenario: ActivityScenario<MainActivity>

@Before
fun setUp() {
scenario = ActivityScenario.launch(MainActivity::class.java)
}

@After
fun tearDown() {
scenario.close()
}

// MainActivity가 잘 보이나요?
@Test
fun testMainActivityVisible() {
scenario.onActivity { activity ->
val mainView = activity.findViewById<View>(R.id.main)
assertNotNull(mainView)
}
}

// 검색 기능이 잘 동작하나요?
// @Test
// fun testVerifySearchFunction() {
// scenario.onActivity { activity ->
// val keyword = "london"
// val editText = activity.findViewById<EditText>(R.id.etKeywords)
// editText.setText(keyword)
//
// activity.mapViewModel.searchPlaces(keyword)
//
// activity.mapViewModel.searchResults.observe(activity, Observer { results ->
// assertTrue(results.isNotEmpty())
// })
// }
// }
//
// // 검색 결과에 따라 RecyclerView가 잘 바뀌나요?
// @Test
// fun testRecyclerViewVisibility() {
// scenario.onActivity { activity ->
// val recyclerView = activity.findViewById<RecyclerView>(R.id.rvSearchResult)
// val noResultTextView = activity.findViewById<TextView>(R.id.tvNoResults)
//
// activity.mapViewModel.searchResults.observe(activity, Observer { results ->
// if (results.isEmpty()) {
// assertEquals(View.VISIBLE, noResultTextView.visibility)
// assertEquals(View.GONE, recyclerView.visibility)
// } else {
// assertEquals(View.GONE, noResultTextView.visibility)
// assertEquals(View.VISIBLE, recyclerView.visibility)
// }
// })
// }
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package campus.tech.kakao.map.unitTest

import android.content.Context
import android.view.View
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import campus.tech.kakao.map.R
import campus.tech.kakao.map.ui.MapActivity
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertNotNull
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MapActivityUnitTest {

private lateinit var scenario: ActivityScenario<MapActivity>

@Before
fun setup() {
scenario = ActivityScenario.launch(MapActivity::class.java)
}

@After
fun tearDown() {
scenario.close()
}

// MapActivity가 잘 보이나요?
@Test
fun testMapActivityVisible() {
scenario.onActivity { activity ->
val mainView = activity.findViewById<View>(R.id.main)
assertNotNull(mainView)
}
}

// 저장된 위치를 잘 로드하나요?
@Test
fun testSavedLocationLoad() {
scenario.onActivity { activity ->
val preferences = activity.getSharedPreferences("location_prefs", Context.MODE_PRIVATE)
val editor = preferences.edit()
val savedLatitude = 37.3957122
val savedLongitude = 127.1105181
editor.putString("latitude", savedLatitude.toString())
editor.putString("longitude", savedLongitude.toString())
editor.apply()

activity.loadSavedLocation()

assertEquals(savedLatitude, activity.savedLatitude)
assertEquals(savedLongitude, activity.savedLongitude)
}
}

// 현재 위치를 잘 저장하나요?
@Test
fun testSaveCurrentLocation() {
scenario.onActivity { activity ->
val latitude = 37.0
val longitude = 127.0

activity.savedLatitude = latitude
activity.savedLongitude = longitude

activity.saveCurrentLocation()

val preferences = activity.getSharedPreferences("location_prefs", Context.MODE_PRIVATE)
val savedLatitude = preferences.getString("latitude", null)?.toDouble()
val savedLongitude = preferences.getString("longitude", null)?.toDouble()

assertEquals(latitude, savedLatitude)
assertEquals(longitude, savedLongitude)
}
}

}
19 changes: 13 additions & 6 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,23 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Map"
tools:targetApi="31">
tools:targetApi="31"
android:name=".application.AppClass"
android:networkSecurityConfig="@xml/network_security_config">

<activity
android:name=".MainActivity"
android:exported="true">
android:name=".ui.MapActivity"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

<activity
android:name=".ui.MainActivity"
android:exported="false" />

</application>

</manifest>
11 changes: 0 additions & 11 deletions app/src/main/java/campus/tech/kakao/map/MainActivity.kt

This file was deleted.

Loading

0 comments on commit 4494e4e

Please sign in to comment.