diff --git a/.gitignore b/.gitignore index 902bf34f..aa25f17c 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,4 @@ google-services.json /app/release # Mac OS -.DS_Store +.DS_Store \ No newline at end of file diff --git a/app/schemas/campus.tech.kakao.map.data.db.AppDatabase/1.json b/app/schemas/campus.tech.kakao.map.data.db.AppDatabase/1.json index e6d4556f..731659a4 100644 --- a/app/schemas/campus.tech.kakao.map.data.db.AppDatabase/1.json +++ b/app/schemas/campus.tech.kakao.map.data.db.AppDatabase/1.json @@ -2,11 +2,11 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "e1dff925b4d05fac65f959d46ab6a9a7", + "identityHash": "de42a776ec13b03bff04a36fe6dc2ddb", "entities": [ { "tableName": "research", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `img` INTEGER NOT NULL, `name` TEXT NOT NULL, `location` TEXT NOT NULL, `category` TEXT NOT NULL, `x` TEXT NOT NULL, `y` TEXT NOT NULL)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `location` TEXT NOT NULL, `category` TEXT NOT NULL, `x` TEXT NOT NULL, `y` TEXT NOT NULL)", "fields": [ { "fieldPath": "id", @@ -14,12 +14,6 @@ "affinity": "INTEGER", "notNull": false }, - { - "fieldPath": "img", - "columnName": "img", - "affinity": "INTEGER", - "notNull": true - }, { "fieldPath": "name", "columnName": "name", @@ -64,7 +58,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'e1dff925b4d05fac65f959d46ab6a9a7')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'de42a776ec13b03bff04a36fe6dc2ddb')" ] } } \ No newline at end of file diff --git a/app/src/androidTest/java/campus/tech/kakao/map/MainViewUiTest.kt b/app/src/androidTest/java/campus/tech/kakao/map/MainViewUiTest.kt index 51514e6a..64410f4e 100644 --- a/app/src/androidTest/java/campus/tech/kakao/map/MainViewUiTest.kt +++ b/app/src/androidTest/java/campus/tech/kakao/map/MainViewUiTest.kt @@ -8,7 +8,7 @@ import androidx.test.espresso.matcher.ViewMatchers.* import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.espresso.assertion.ViewAssertions.matches -import campus.tech.kakao.map.view.MainActivity +import campus.tech.kakao.map.presentation.view.MainActivity import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e12dddb5..a38af5aa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,9 @@ + + + + + + + + + + + - \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/db/AppDatabase.kt b/app/src/main/java/campus/tech/kakao/map/data/db/AppDatabase.kt index 014d1cca..4df5aca5 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/db/AppDatabase.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/db/AppDatabase.kt @@ -1,28 +1,10 @@ package campus.tech.kakao.map.data.db -import android.content.Context import androidx.room.Database -import androidx.room.Room import androidx.room.RoomDatabase import campus.tech.kakao.map.data.db.entity.Place @Database(entities = [Place::class], version = 1) abstract class AppDatabase: RoomDatabase() { abstract fun placeDao(): PlaceDao - - companion object { - @Volatile private var instance: AppDatabase? = null - - fun getDatabase(context: Context): AppDatabase = - instance ?: synchronized(this) { - instance ?: buildDatabase(context).also { instance = it } - } - - private fun buildDatabase(context: Context) = - Room.databaseBuilder( - context.applicationContext, - AppDatabase::class.java, - "MyPlace.db").build() - - } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/db/PlaceDao.kt b/app/src/main/java/campus/tech/kakao/map/data/db/PlaceDao.kt index 04765a6c..1e8c9275 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/db/PlaceDao.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/db/PlaceDao.kt @@ -10,14 +10,14 @@ import campus.tech.kakao.map.data.db.entity.Place @Dao interface PlaceDao { @Insert(onConflict = OnConflictStrategy.IGNORE) - fun insertLog(place: Place) + suspend fun insertLog(place: Place) @Delete - fun deleteLog(place: Place) + suspend fun deleteLog(place: Place) @Query("SELECT * FROM research") - fun getAllLogs(): List + suspend fun getAllLogs(): List @Query("SELECT COUNT(*) FROM research") - fun getPlaceCount(): Int + suspend fun getPlaceCount(): Int } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/db/entity/Place.kt b/app/src/main/java/campus/tech/kakao/map/data/db/entity/Place.kt index 118fcc07..d745bd03 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/db/entity/Place.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/db/entity/Place.kt @@ -1,16 +1,14 @@ package campus.tech.kakao.map.data.db.entity -import androidx.annotation.DrawableRes import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = "research") data class Place ( @PrimaryKey(autoGenerate = true) val id: Int? = null, - @DrawableRes val img: Int, val name: String, val location: String, val category: String, val x: String, val y: String -) +) \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/di/DatabaseModule.kt b/app/src/main/java/campus/tech/kakao/map/data/di/DatabaseModule.kt index 023f03ed..6a50d452 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/di/DatabaseModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/di/DatabaseModule.kt @@ -1,6 +1,7 @@ package campus.tech.kakao.map.data.di import android.content.Context +import androidx.room.Room import campus.tech.kakao.map.data.db.AppDatabase import campus.tech.kakao.map.data.db.PlaceDao import dagger.Module @@ -13,10 +14,15 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object DatabaseModule { + private const val DATABASE_NAME = "MyPlace.db" @Provides @Singleton fun provideDatabase(@ApplicationContext context: Context): AppDatabase { - return AppDatabase.getDatabase(context) + return Room.databaseBuilder( + context, + AppDatabase::class.java, + DATABASE_NAME + ).build() } @Provides diff --git a/app/src/main/java/campus/tech/kakao/map/data/di/PreferencesModule.kt b/app/src/main/java/campus/tech/kakao/map/data/di/PreferencesModule.kt index e9ed1fc6..d42f850e 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/di/PreferencesModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/di/PreferencesModule.kt @@ -12,7 +12,6 @@ import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object PreferencesModule { - @Provides @Singleton fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences { diff --git a/app/src/main/java/campus/tech/kakao/map/data/di/RemoteConfigModule.kt b/app/src/main/java/campus/tech/kakao/map/data/di/RemoteConfigModule.kt index 1654a369..525711e6 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/di/RemoteConfigModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/di/RemoteConfigModule.kt @@ -1,6 +1,6 @@ package campus.tech.kakao.map.data.di -import campus.tech.kakao.map.repository.RemoteConfigManager +import campus.tech.kakao.map.data.remote.config.RemoteConfigManager import dagger.Module import dagger.Provides import dagger.hilt.InstallIn diff --git a/app/src/main/java/campus/tech/kakao/map/data/di/RepositoryModule.kt b/app/src/main/java/campus/tech/kakao/map/data/di/RepositoryModule.kt index f3e52593..ffd1cdf9 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/di/RepositoryModule.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/di/RepositoryModule.kt @@ -1,18 +1,15 @@ package campus.tech.kakao.map.data.di -import android.app.Application import android.content.Context import android.content.SharedPreferences -import campus.tech.kakao.map.base.MyApplication -import campus.tech.kakao.map.data.db.PlaceDao +import campus.tech.kakao.map.data.db.AppDatabase import campus.tech.kakao.map.data.remote.api.KakaoApiService -import campus.tech.kakao.map.repository.LogRepository -import campus.tech.kakao.map.repository.LogRepositoryInterface -import campus.tech.kakao.map.repository.MapRepository -import campus.tech.kakao.map.repository.MapRepositoryInterface -import campus.tech.kakao.map.repository.PlaceRepository -import campus.tech.kakao.map.repository.PlaceRepositoryInterface -import campus.tech.kakao.map.repository.WelcomeRepository +import campus.tech.kakao.map.data.repository.log.LogRepository +import campus.tech.kakao.map.data.repository.log.LogRepositoryInterface +import campus.tech.kakao.map.data.repository.map.MapRepository +import campus.tech.kakao.map.data.repository.map.MapRepositoryInterface +import campus.tech.kakao.map.data.repository.place.PlaceRepository +import campus.tech.kakao.map.data.repository.place.PlaceRepositoryInterface import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -39,8 +36,8 @@ object RepositoryModule { @Provides @Singleton - fun provideLogRepository(context: Context, placeDao: PlaceDao): LogRepositoryInterface { - return LogRepository(context.applicationContext as MyApplication, placeDao) + fun provideLogRepository(placeDatabase: AppDatabase): LogRepositoryInterface { + return LogRepository(placeDatabase) } @Provides @@ -48,10 +45,4 @@ object RepositoryModule { fun provideMapRepository(sharedPreferences: SharedPreferences): MapRepositoryInterface { return MapRepository(sharedPreferences) } - - @Provides - @Singleton - fun provideWelcomeRepository(): WelcomeRepository { - return WelcomeRepository() - } } diff --git a/app/src/main/java/campus/tech/kakao/map/repository/RemoteConfigManager.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/config/RemoteConfigManager.kt similarity index 96% rename from app/src/main/java/campus/tech/kakao/map/repository/RemoteConfigManager.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/config/RemoteConfigManager.kt index 8588b601..5e819a9d 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/RemoteConfigManager.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/config/RemoteConfigManager.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.repository +package campus.tech.kakao.map.data.remote.config import android.util.Log import com.google.firebase.remoteconfig.FirebaseRemoteConfig diff --git a/app/src/main/java/campus/tech/kakao/map/data/remote/service/FCMservice.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/service/FCMservice.kt new file mode 100644 index 00000000..66a6fa5a --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/service/FCMservice.kt @@ -0,0 +1,82 @@ +package campus.tech.kakao.map.data.remote.service + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.util.Log +import androidx.core.app.NotificationCompat +import campus.tech.kakao.map.R +import campus.tech.kakao.map.presentation.view.WelcomeActivity +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage + +class FCMservice : FirebaseMessagingService() { + override fun onCreate() { + super.onCreate() + createNotificationChannel() + } + + override fun onMessageReceived(remoteMessage: RemoteMessage) { + super.onMessageReceived(remoteMessage) + Log.d("TEST_FcmService", "Received Message") + + remoteMessage.notification?.let { notification -> + // 일반 알림 처리 + showNotification(notification.title, notification.body) + } + + remoteMessage.data.let { data -> + // 커스텀 알림 처리 + val title = data["title"] + val body = data["body"] + if (title != null && body != null) { + showNotification(title, body) + } + } + } + + private fun showNotification(title: String?, body: String?) { + val intent = Intent(this, WelcomeActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } + val pendingIntent: PendingIntent = PendingIntent.getActivity(applicationContext, + REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE) + + val notification = NotificationCompat.Builder(this, CHANNEL_ID) + .setSmallIcon(R.drawable.icon) + .setContentTitle(title) + .setContentText(body) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + .build() + + val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.notify(NOTIFICATION_ID, notification) + } + + private fun createNotificationChannel() { + val channelId = CHANNEL_ID + val channelName = CHANNEL_NAME + val channelDescription = CHANNEL_DESCRIPTION + val importance = NotificationManager.IMPORTANCE_DEFAULT + + val channel = NotificationChannel(channelId, channelName, importance).apply { + description = channelDescription + } + + val notificationManager: NotificationManager = + getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.createNotificationChannel(channel) + } + + companion object { + private const val NOTIFICATION_ID = 222222 + private const val REQUEST_CODE = 0 + private const val CHANNEL_ID = "Mychannel" + private const val CHANNEL_NAME = "Mychannel" + private const val CHANNEL_DESCRIPTION = "This is Mychannel" + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/repository/log/LogRepository.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/log/LogRepository.kt new file mode 100644 index 00000000..0af6cb65 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/repository/log/LogRepository.kt @@ -0,0 +1,23 @@ +package campus.tech.kakao.map.data.repository.log + +import campus.tech.kakao.map.data.db.AppDatabase +import campus.tech.kakao.map.data.db.entity.Place +import javax.inject.Inject + +class LogRepository @Inject constructor (private val placeDatabase: AppDatabase): LogRepositoryInterface { + override suspend fun getAllLogs(): List { + return placeDatabase.placeDao().getAllLogs() + } + + override suspend fun haveAnyLog(): Boolean { + return placeDatabase.placeDao().getPlaceCount() > 0 + } + + override suspend fun insertLog(place: Place) { + placeDatabase.placeDao().insertLog(place) + } + + override suspend fun deleteLog(place: Place) { + placeDatabase.placeDao().deleteLog(place) + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/repository/log/LogRepositoryInterface.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/log/LogRepositoryInterface.kt new file mode 100644 index 00000000..3ce002ee --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/repository/log/LogRepositoryInterface.kt @@ -0,0 +1,10 @@ +package campus.tech.kakao.map.data.repository.log + +import campus.tech.kakao.map.data.db.entity.Place + +interface LogRepositoryInterface { + suspend fun getAllLogs(): List + suspend fun haveAnyLog(): Boolean + suspend fun insertLog(place: Place) + suspend fun deleteLog(place: Place) +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/repository/MapRepository.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/map/MapRepository.kt similarity index 91% rename from app/src/main/java/campus/tech/kakao/map/repository/MapRepository.kt rename to app/src/main/java/campus/tech/kakao/map/data/repository/map/MapRepository.kt index fb95b10e..38bc2c9f 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/MapRepository.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/repository/map/MapRepository.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.repository +package campus.tech.kakao.map.data.repository.map import android.content.SharedPreferences import javax.inject.Inject diff --git a/app/src/main/java/campus/tech/kakao/map/repository/MapRepositoryInterface.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/map/MapRepositoryInterface.kt similarity index 63% rename from app/src/main/java/campus/tech/kakao/map/repository/MapRepositoryInterface.kt rename to app/src/main/java/campus/tech/kakao/map/data/repository/map/MapRepositoryInterface.kt index ffb3cf2b..6b667452 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/MapRepositoryInterface.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/repository/map/MapRepositoryInterface.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.repository +package campus.tech.kakao.map.data.repository.map interface MapRepositoryInterface { fun getLastLocation(): Pair? diff --git a/app/src/main/java/campus/tech/kakao/map/repository/PlaceRepository.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/place/PlaceRepository.kt similarity index 92% rename from app/src/main/java/campus/tech/kakao/map/repository/PlaceRepository.kt rename to app/src/main/java/campus/tech/kakao/map/data/repository/place/PlaceRepository.kt index c29b053b..14a22be8 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/PlaceRepository.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/repository/place/PlaceRepository.kt @@ -1,9 +1,8 @@ -package campus.tech.kakao.map.repository +package campus.tech.kakao.map.data.repository.place import android.content.SharedPreferences import android.util.Log import campus.tech.kakao.map.BuildConfig -import campus.tech.kakao.map.R import campus.tech.kakao.map.data.db.entity.Place import campus.tech.kakao.map.data.remote.api.KakaoApiService import javax.inject.Inject @@ -20,7 +19,6 @@ class PlaceRepository @Inject constructor( val documentList = response.documents ?: emptyList() documentList.map { Place( - img = R.drawable.location, name = it.placeName, location = it.addressName, category = it.categoryGroupName, @@ -45,4 +43,4 @@ class PlaceRepository @Inject constructor( companion object { private const val KAKAOAK = "KakaoAK " } -} +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/repository/PlaceRepositoryInterface.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/place/PlaceRepositoryInterface.kt similarity index 78% rename from app/src/main/java/campus/tech/kakao/map/repository/PlaceRepositoryInterface.kt rename to app/src/main/java/campus/tech/kakao/map/data/repository/place/PlaceRepositoryInterface.kt index 873e4e3e..9743cb8e 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/PlaceRepositoryInterface.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/repository/place/PlaceRepositoryInterface.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.repository +package campus.tech.kakao.map.data.repository.place import campus.tech.kakao.map.data.db.entity.Place diff --git a/app/src/main/java/campus/tech/kakao/map/view/RecyclerViewAdapter.kt b/app/src/main/java/campus/tech/kakao/map/presentation/adapter/RecyclerViewAdapter.kt similarity index 92% rename from app/src/main/java/campus/tech/kakao/map/view/RecyclerViewAdapter.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/adapter/RecyclerViewAdapter.kt index 9154fdaf..8f452716 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/RecyclerViewAdapter.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/adapter/RecyclerViewAdapter.kt @@ -1,10 +1,7 @@ -package campus.tech.kakao.map.view +package campus.tech.kakao.map.presentation.adapter import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter diff --git a/app/src/main/java/campus/tech/kakao/map/view/TapViewAdapter.kt b/app/src/main/java/campus/tech/kakao/map/presentation/adapter/TapViewAdapter.kt similarity index 92% rename from app/src/main/java/campus/tech/kakao/map/view/TapViewAdapter.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/adapter/TapViewAdapter.kt index 7bc3a8a3..b11f8f9b 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/TapViewAdapter.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/adapter/TapViewAdapter.kt @@ -1,10 +1,7 @@ -package campus.tech.kakao.map.view +package campus.tech.kakao.map.presentation.adapter import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter diff --git a/app/src/main/java/campus/tech/kakao/map/view/ErrorActivity.kt b/app/src/main/java/campus/tech/kakao/map/presentation/view/ErrorActivity.kt similarity index 92% rename from app/src/main/java/campus/tech/kakao/map/view/ErrorActivity.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/view/ErrorActivity.kt index fea78dcc..6951d729 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/ErrorActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/view/ErrorActivity.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.view +package campus.tech.kakao.map.presentation.view import android.os.Bundle import android.widget.TextView diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/presentation/view/MainActivity.kt similarity index 92% rename from app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/view/MainActivity.kt index 50a70484..dcfcabce 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/view/MainActivity.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.view +package campus.tech.kakao.map.presentation.view import android.content.Intent import android.os.Bundle @@ -8,11 +8,13 @@ import androidx.core.view.isVisible import androidx.core.widget.doAfterTextChanged import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.LinearLayoutManager -import campus.tech.kakao.map.viewmodel.PlaceViewModel +import campus.tech.kakao.map.presentation.viewmodel.PlaceViewModel import campus.tech.kakao.map.data.db.entity.Place import campus.tech.kakao.map.R import campus.tech.kakao.map.databinding.ActivityMainBinding -import campus.tech.kakao.map.viewmodel.LogViewModel +import campus.tech.kakao.map.presentation.adapter.RecyclerViewAdapter +import campus.tech.kakao.map.presentation.adapter.TapViewAdapter +import campus.tech.kakao.map.presentation.viewmodel.LogViewModel import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint diff --git a/app/src/main/java/campus/tech/kakao/map/view/MapViewActivity.kt b/app/src/main/java/campus/tech/kakao/map/presentation/view/MapViewActivity.kt similarity index 96% rename from app/src/main/java/campus/tech/kakao/map/view/MapViewActivity.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/view/MapViewActivity.kt index 6ff91676..11d1e36f 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MapViewActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/view/MapViewActivity.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.view +package campus.tech.kakao.map.presentation.view import android.content.Intent import android.graphics.Color @@ -8,10 +8,10 @@ import android.widget.LinearLayout import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.databinding.DataBindingUtil -import campus.tech.kakao.map.viewmodel.MapViewModel +import campus.tech.kakao.map.presentation.viewmodel.MapViewModel import campus.tech.kakao.map.R import campus.tech.kakao.map.databinding.ActivityMapViewBinding -import campus.tech.kakao.map.repository.MapRepositoryInterface +import campus.tech.kakao.map.data.repository.map.MapRepositoryInterface import com.google.android.material.bottomsheet.BottomSheetBehavior import com.kakao.vectormap.KakaoMap import com.kakao.vectormap.KakaoMapReadyCallback diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/view/WelcomeActivity.kt b/app/src/main/java/campus/tech/kakao/map/presentation/view/WelcomeActivity.kt new file mode 100644 index 00000000..9151ca2e --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/presentation/view/WelcomeActivity.kt @@ -0,0 +1,98 @@ +package campus.tech.kakao.map.presentation.view + +import android.Manifest +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.lifecycleScope +import campus.tech.kakao.map.R +import campus.tech.kakao.map.databinding.ActivityWelcomeBinding +import campus.tech.kakao.map.data.remote.config.RemoteConfigManager +import campus.tech.kakao.map.presentation.viewmodel.WelcomeViewModel +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +@AndroidEntryPoint +class WelcomeActivity : AppCompatActivity() { + private lateinit var binding: ActivityWelcomeBinding + private val welcomeViewModel: WelcomeViewModel by viewModels() + private val requestPermissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (isGranted) { + // FCM SDK와 앱이 알림을 게시할 수 있게 된다 + } else { + Toast.makeText(this, R.string.notification_disabled_message, Toast.LENGTH_LONG).show() + } + } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setupBinding() + observeServiceStateChanges() + askNotificationPermission() + } + + private fun setupBinding() { + binding = DataBindingUtil.setContentView(this, R.layout.activity_welcome) + binding.viewModel = welcomeViewModel + binding.lifecycleOwner = this + } + private fun observeServiceStateChanges(){ + welcomeViewModel.serviceState.observe(this){ state -> + when(state) { + RemoteConfigManager.REMOTE_ON_SERVICE -> { + Log.d("arieum", state) + lifecycleScope.launch { + delay(1000L) + moveMapView() + } + } + else -> { Log.d("arieum", state) } + } + } + } + private fun moveMapView() { + val intent = Intent(this@WelcomeActivity, MapViewActivity::class.java) + startActivity(intent) + } + private fun askNotificationPermission() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + when { + ContextCompat.checkSelfPermission( + this, + Manifest.permission.POST_NOTIFICATIONS + ) == PackageManager.PERMISSION_GRANTED -> { + // FCM SDK와 앱이 이미 알림을 게시할 수 있다 + // 알림 관련 기능을 초기화하거나 필요한 서비스를 시작한다 + } + shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS) -> { + // 사용자에게 권한 요청 이유를 설명하는 UI + AlertDialog.Builder(this) + .setTitle(R.string.notification_permission_required_title) + .setMessage(R.string.notification_permission_message) + .setPositiveButton(R.string.positive_button) { _, _ -> + requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) + } + .setNegativeButton(R.string.negative_button) { dialog, _ -> + dialog.dismiss() + Toast.makeText(this, R.string.notification_permission_denied_message, Toast.LENGTH_LONG).show() + } + .show() + } + else -> { + // 직접 권한요청 + requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/LogViewModel.kt b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/LogViewModel.kt new file mode 100644 index 00000000..0595a2e6 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/LogViewModel.kt @@ -0,0 +1,57 @@ +package campus.tech.kakao.map.presentation.viewmodel + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import campus.tech.kakao.map.data.db.entity.Place +import campus.tech.kakao.map.data.repository.log.LogRepositoryInterface +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class LogViewModel @Inject constructor( + private val logRepository: LogRepositoryInterface +): ViewModel() { + private var _logList = MutableLiveData>() + val logList: LiveData> get() = _logList + + private var _tabViewVisible = MutableLiveData() + val tabViewVisible: LiveData get() = _tabViewVisible + + init { + initLogData() + } + + private fun initLogData(){ + viewModelScope.launch { + initLogList() + updateLogViewVisible() + } + } + + private suspend fun initLogList(){ + _logList.value = logRepository.getAllLogs() + } + + private suspend fun updateLogViewVisible(){ + _tabViewVisible.value = logRepository.haveAnyLog() + } + + fun deleteLog(item: Place){ + viewModelScope.launch { + logRepository.deleteLog(item) + _logList.value = logRepository.getAllLogs() + updateLogViewVisible() + } + } + + fun insertLog(item: Place) { + viewModelScope.launch { + logRepository.insertLog(item) + _logList.value = logRepository.getAllLogs() + updateLogViewVisible() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MapViewModel.kt b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/MapViewModel.kt similarity index 90% rename from app/src/main/java/campus/tech/kakao/map/viewmodel/MapViewModel.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/MapViewModel.kt index 19904914..02f11a59 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/MapViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/MapViewModel.kt @@ -1,8 +1,8 @@ -package campus.tech.kakao.map.viewmodel +package campus.tech.kakao.map.presentation.viewmodel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import campus.tech.kakao.map.repository.MapRepositoryInterface +import campus.tech.kakao.map.data.repository.map.MapRepositoryInterface import com.google.android.material.bottomsheet.BottomSheetBehavior import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/PlaceViewModel.kt b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/PlaceViewModel.kt similarity index 91% rename from app/src/main/java/campus/tech/kakao/map/viewmodel/PlaceViewModel.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/PlaceViewModel.kt index f7040c21..364ce03f 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/PlaceViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/PlaceViewModel.kt @@ -1,11 +1,11 @@ -package campus.tech.kakao.map.viewmodel +package campus.tech.kakao.map.presentation.viewmodel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import campus.tech.kakao.map.data.db.entity.Place -import campus.tech.kakao.map.repository.PlaceRepositoryInterface +import campus.tech.kakao.map.data.repository.place.PlaceRepositoryInterface import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/WelcomeViewModel.kt b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/WelcomeViewModel.kt similarity index 70% rename from app/src/main/java/campus/tech/kakao/map/viewmodel/WelcomeViewModel.kt rename to app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/WelcomeViewModel.kt index f849711b..a2603823 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/WelcomeViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/viewmodel/WelcomeViewModel.kt @@ -1,10 +1,10 @@ -package campus.tech.kakao.map.viewmodel +package campus.tech.kakao.map.presentation.viewmodel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import campus.tech.kakao.map.repository.RemoteConfigManager +import campus.tech.kakao.map.data.remote.config.RemoteConfigManager import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @@ -17,16 +17,23 @@ class WelcomeViewModel @Inject constructor( private val _serviceMessage = MutableLiveData() val serviceMessage: LiveData get() = _serviceMessage + init { + processRemoteConfig() + } - fun processRemoteConfig() { + private fun processRemoteConfig() { viewModelScope.launch { val success = remoteConfigManager.fetchAndActivateConfig() if (success) { val setServiceState = remoteConfigManager.getServiceState() _serviceState.value = setServiceState when (setServiceState) { - RemoteConfigManager.REMOTE_ON_SERVICE -> { _serviceMessage.value = "" } - else -> { _serviceMessage.value = remoteConfigManager.getServiceMessage() } + RemoteConfigManager.REMOTE_ON_SERVICE -> { + _serviceMessage.value = "" + } + else -> { + _serviceMessage.value = remoteConfigManager.getServiceMessage() + } } } else { _serviceState.value = remoteConfigManager.REMOTE_ON_ERROR diff --git a/app/src/main/java/campus/tech/kakao/map/repository/LogRepository.kt b/app/src/main/java/campus/tech/kakao/map/repository/LogRepository.kt deleted file mode 100644 index 3b8c1e09..00000000 --- a/app/src/main/java/campus/tech/kakao/map/repository/LogRepository.kt +++ /dev/null @@ -1,54 +0,0 @@ -package campus.tech.kakao.map.repository - -import campus.tech.kakao.map.base.MyApplication -import campus.tech.kakao.map.data.db.AppDatabase -import campus.tech.kakao.map.data.db.PlaceDao -import campus.tech.kakao.map.data.db.entity.Place -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext -import javax.inject.Inject - -class LogRepository @Inject constructor (private val application: MyApplication, private val placeDao: PlaceDao): LogRepositoryInterface { - - private var logList = mutableListOf() - - override fun getAllLogs(): List { - runBlocking { - withContext(Dispatchers.IO) { - logList = placeDao.getAllLogs().toMutableList() - } - } - return logList - } - - override fun haveAnyLog() : Boolean { - return runBlocking { - withContext(Dispatchers.IO) { - placeDao.getPlaceCount() > 0 - } - } - } - - override fun insertLog(place: Place): List { - CoroutineScope(Dispatchers.IO).launch { - placeDao.insertLog(place) - withContext(Dispatchers.Main) { - logList.add(place) - } - } - return logList - } - - override fun deleteLog(place: Place): List { - CoroutineScope(Dispatchers.IO).launch { - placeDao.deleteLog(place) - withContext(Dispatchers.Main) { - logList.remove(place) - } - } - return logList - } -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/repository/LogRepositoryInterface.kt b/app/src/main/java/campus/tech/kakao/map/repository/LogRepositoryInterface.kt deleted file mode 100644 index b28f4aae..00000000 --- a/app/src/main/java/campus/tech/kakao/map/repository/LogRepositoryInterface.kt +++ /dev/null @@ -1,10 +0,0 @@ -package campus.tech.kakao.map.repository - -import campus.tech.kakao.map.data.db.entity.Place - -interface LogRepositoryInterface { - fun getAllLogs(): List - fun haveAnyLog() : Boolean - fun insertLog(place: Place): List - fun deleteLog(place: Place): List -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/repository/WelcomeRepository.kt b/app/src/main/java/campus/tech/kakao/map/repository/WelcomeRepository.kt deleted file mode 100644 index 53fa151b..00000000 --- a/app/src/main/java/campus/tech/kakao/map/repository/WelcomeRepository.kt +++ /dev/null @@ -1,4 +0,0 @@ -package campus.tech.kakao.map.repository - -class WelcomeRepository { -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/WelcomeActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/WelcomeActivity.kt deleted file mode 100644 index eb26b9bc..00000000 --- a/app/src/main/java/campus/tech/kakao/map/view/WelcomeActivity.kt +++ /dev/null @@ -1,53 +0,0 @@ -package campus.tech.kakao.map.view - -import android.content.Intent -import android.os.Bundle -import android.util.Log -import androidx.activity.viewModels -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import campus.tech.kakao.map.R -import campus.tech.kakao.map.databinding.ActivityWelcomeBinding -import campus.tech.kakao.map.repository.RemoteConfigManager -import campus.tech.kakao.map.viewmodel.WelcomeViewModel -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch - -@AndroidEntryPoint -class WelcomeActivity : AppCompatActivity() { - private lateinit var binding: ActivityWelcomeBinding - private val welcomeViewModel: WelcomeViewModel by viewModels() - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setupBinding() - welcomeViewModel.processRemoteConfig() - observeServiceStateChanges() - } - - private fun setupBinding() { - binding = DataBindingUtil.setContentView(this, R.layout.activity_welcome) - binding.viewModel = welcomeViewModel - binding.lifecycleOwner = this - } - private fun observeServiceStateChanges(){ - welcomeViewModel.serviceState.observe(this){ state -> - when(state) { - RemoteConfigManager.REMOTE_ON_SERVICE -> { - Log.d("arieum", "$state") - lifecycleScope.launch { - delayBeforeMoveMapView() - runOnUiThread { moveMapView() } - } - } - else -> { Log.d("arieum", "$state") } - } - } - } - private suspend fun delayBeforeMoveMapView(){ delay(1000L) } - private fun moveMapView() { - val intent = Intent(this@WelcomeActivity, MapViewActivity::class.java) - startActivity(intent) - } -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/LogViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/LogViewModel.kt deleted file mode 100644 index 27de5674..00000000 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/LogViewModel.kt +++ /dev/null @@ -1,56 +0,0 @@ -package campus.tech.kakao.map.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import campus.tech.kakao.map.data.db.entity.Place -import campus.tech.kakao.map.repository.LogRepositoryInterface -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import javax.inject.Inject - -@HiltViewModel -class LogViewModel @Inject constructor( - private val logRepository: LogRepositoryInterface -): ViewModel() { - private var _logList = MutableLiveData>() - val logList: LiveData> get() = _logList - - private var _tabViewVisible = MutableLiveData() - val tabViewVisible: LiveData get() = _tabViewVisible - - init { - initLogData() - } - - private fun initLogData(){ - initLogList() - updateLogViewVisible() - } - - private fun initLogList(){ - _logList.postValue(logRepository.getAllLogs()) - } - - private fun updateLogViewVisible(){ - val isVisible = logRepository.haveAnyLog() - _tabViewVisible.postValue(isVisible) - } - - fun deleteLog(item: Place){ - val logListAfterRemoving = logRepository.deleteLog(item) - _logList.value = logListAfterRemoving - - updateLogViewVisible() - } - - fun insertLog(item: Place) { - val logListAfterInserting = logRepository.insertLog(item) - _logList.value = logListAfterInserting - - updateLogViewVisible() - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable/icon.png b/app/src/main/res/drawable/icon.png new file mode 100644 index 00000000..07ba6a43 Binary files /dev/null and b/app/src/main/res/drawable/icon.png differ diff --git a/app/src/main/res/layout/activity_error.xml b/app/src/main/res/layout/activity_error.xml index 2385526e..cfee9dec 100644 --- a/app/src/main/res/layout/activity_error.xml +++ b/app/src/main/res/layout/activity_error.xml @@ -5,7 +5,7 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".view.ErrorActivity"> + tools:context=".presentation.view.ErrorActivity"> + tools:context=".presentation.view.MainActivity"> + type="campus.tech.kakao.map.presentation.viewmodel.PlaceViewModel" /> + tools:context=".presentation.view.MapViewActivity"> + type="campus.tech.kakao.map.presentation.view.MapViewActivity" /> + type="campus.tech.kakao.map.presentation.viewmodel.MapViewModel" /> + type="campus.tech.kakao.map.presentation.view.WelcomeActivity" /> + type="campus.tech.kakao.map.presentation.viewmodel.WelcomeViewModel" /> + tools:context=".presentation.view.WelcomeActivity"> + type="campus.tech.kakao.map.presentation.viewmodel.MapViewModel" /> Map ON_SERVICE ON_PAUSE + default_channel + + Notifications are disabled + 알림권한이 필요합니다 + This app needs notification permission to send you updates and important information + 알림권한이 거절됐습니다 + OK + NO \ No newline at end of file diff --git a/gradlew.bat b/gradlew.bat index 297c6fcb..7fe44917 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -93,4 +93,4 @@ exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal -:omega +:omega \ No newline at end of file