diff --git a/app/src/main/java/com/runnect/runnect/application/ApplicationClass.kt b/app/src/main/java/com/runnect/runnect/application/ApplicationClass.kt index 8365d7c3c..0051070b5 100644 --- a/app/src/main/java/com/runnect/runnect/application/ApplicationClass.kt +++ b/app/src/main/java/com/runnect/runnect/application/ApplicationClass.kt @@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatDelegate import com.kakao.sdk.common.KakaoSdk import com.runnect.runnect.BuildConfig import com.runnect.runnect.R +import com.runnect.runnect.util.analytics.Analytics import dagger.hilt.android.HiltAndroidApp import timber.log.Timber @@ -20,8 +21,9 @@ class ApplicationClass : Application() { Timber.plant(Timber.DebugTree()) } appContext = applicationContext - KakaoSdk.init(this,getString(R.string.kakao_native_app_key)) + KakaoSdk.init(this, getString(R.string.kakao_native_app_key)) initApiMode() + initAnalytics() } private fun initApiMode() { @@ -29,6 +31,10 @@ class ApplicationClass : Application() { PreferenceManager.setString(appContext, API_MODE, currentApi.name) } + private fun initAnalytics() { + Analytics.initializeFirebaseAnalytics(applicationContext) + } + companion object { lateinit var appContext: Context const val API_MODE = "API_MODE" @@ -39,7 +45,7 @@ class ApplicationClass : Application() { !::appContext.isInitialized -> BuildConfig.RUNNECT_NODE_URL else -> { val mode = ApiMode.getCurrentApiMode(appContext) - when(mode) { + when (mode) { ApiMode.JAVA -> BuildConfig.RUNNECT_PROD_URL ApiMode.TEST -> BuildConfig.RUNNECT_DEV_URL else -> BuildConfig.RUNNECT_NODE_URL diff --git a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt index 59c90fde6..d67dd2ab8 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt @@ -42,6 +42,10 @@ import com.runnect.runnect.presentation.login.LoginActivity import com.runnect.runnect.presentation.mypage.upload.MyUploadActivity import com.runnect.runnect.presentation.profile.ProfileActivity import com.runnect.runnect.presentation.state.UiStateV2 +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_SHARE +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_USER_PROFILE +import com.runnect.runnect.util.analytics.EventName.VIEW_COURSE_DETAIL import com.runnect.runnect.util.custom.dialog.CommonDialogFragment import com.runnect.runnect.util.custom.dialog.CommonDialogText import com.runnect.runnect.util.custom.dialog.RequireLoginDialogFragment @@ -84,6 +88,8 @@ class CourseDetailActivity : binding.vm = viewModel binding.lifecycleOwner = this + Analytics.logClickedItemEvent(VIEW_COURSE_DETAIL) + initIntentExtraData() updatePublicCourseIdFromDeepLink() getCourseDetail() @@ -142,6 +148,7 @@ class CourseDetailActivity : startActivity(this) } applyScreenEnterAnimation() + Analytics.logClickedItemEvent(EVENT_CLICK_USER_PROFILE) } private fun handleBackButtonByCurrentScreenMode() { @@ -238,6 +245,7 @@ class CourseDetailActivity : desc = courseDetail.description, image = courseDetail.image ) + Analytics.logClickedItemEvent(EVENT_CLICK_SHARE) } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt index 7141c91eb..e16b446a8 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt @@ -17,7 +17,6 @@ import com.runnect.runnect.R import com.runnect.runnect.binding.BindingFragment import com.runnect.runnect.databinding.FragmentDiscoverBinding import com.runnect.runnect.domain.entity.DiscoverBanner -import com.runnect.runnect.presentation.discover.model.EditableDiscoverCourse import com.runnect.runnect.presentation.MainActivity import com.runnect.runnect.presentation.MainActivity.Companion.isVisitorMode import com.runnect.runnect.presentation.detail.CourseDetailActivity @@ -25,10 +24,16 @@ import com.runnect.runnect.presentation.detail.CourseDetailRootScreen import com.runnect.runnect.presentation.discover.adapter.BannerAdapter import com.runnect.runnect.presentation.discover.adapter.multiview.DiscoverMultiViewAdapter import com.runnect.runnect.presentation.discover.adapter.multiview.DiscoverMultiViewType +import com.runnect.runnect.presentation.discover.model.EditableDiscoverCourse import com.runnect.runnect.presentation.discover.pick.DiscoverPickActivity import com.runnect.runnect.presentation.discover.search.DiscoverSearchActivity import com.runnect.runnect.presentation.state.UiStateV2 import com.runnect.runnect.presentation.storage.StorageScrapFragment +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_DATE +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_SCRAP +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_TRY_BANNER +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_UPLOAD_BUTTON import com.runnect.runnect.util.custom.toast.RunnectToast import com.runnect.runnect.util.extension.applyScreenEnterAnimation import com.runnect.runnect.util.extension.getCompatibleParcelableExtra @@ -40,6 +45,7 @@ import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import timber.log.Timber @AndroidEntryPoint class DiscoverFragment : BindingFragment(R.layout.fragment_discover) { @@ -98,12 +104,22 @@ class DiscoverFragment : BindingFragment(R.layout.fragm }, onSortButtonClick = { criteria -> viewModel.sortRecommendCourses(criteria) + Analytics.logClickedItemEvent(returnEventName(criteria)) } ).apply { binding.rvDiscoverMultiView.adapter = this } } + private fun returnEventName(criteria: String): String { + var eventName = "" + when (criteria) { + "date" -> eventName = EVENT_CLICK_DATE + "scrap" -> eventName = EVENT_CLICK_SCRAP + } + return eventName + } + private fun navigateToDetailScreen(publicCourseId: Int) { val context = context ?: return Intent(context, CourseDetailActivity::class.java).apply { @@ -139,6 +155,7 @@ class DiscoverFragment : BindingFragment(R.layout.fragm ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { super.onPageSelected(position) + Timber.d("viewpager position: $position") updateBannerPosition(position) updateBannerIndicatorPosition() } @@ -257,6 +274,7 @@ class DiscoverFragment : BindingFragment(R.layout.fragm showCourseUploadWarningToast(context) return } + Analytics.logClickedItemEvent(EVENT_CLICK_UPLOAD_BUTTON) startActivity(Intent(context, DiscoverPickActivity::class.java)) activity?.applyScreenEnterAnimation() } @@ -309,6 +327,7 @@ class DiscoverFragment : BindingFragment(R.layout.fragm banners = banners, onBannerItemClick = { url -> showPromotionWebsite(url) + Analytics.logClickedItemEvent(EVENT_CLICK_TRY_BANNER) } ).apply { binding.vpDiscoverBanner.adapter = this diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt index d93179ddc..993c2c953 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt @@ -17,12 +17,15 @@ import androidx.recyclerview.widget.GridLayoutManager import com.runnect.runnect.R import com.runnect.runnect.binding.BindingActivity import com.runnect.runnect.databinding.ActivityDiscoverSearchBinding -import com.runnect.runnect.presentation.discover.model.EditableDiscoverCourse import com.runnect.runnect.presentation.detail.CourseDetailActivity import com.runnect.runnect.presentation.detail.CourseDetailRootScreen import com.runnect.runnect.presentation.discover.DiscoverFragment.Companion.EXTRA_EDITABLE_DISCOVER_COURSE +import com.runnect.runnect.presentation.discover.model.EditableDiscoverCourse import com.runnect.runnect.presentation.discover.search.adapter.DiscoverSearchAdapter import com.runnect.runnect.presentation.state.UiStateV2 +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_TRY_SEARCH_COURSE +import com.runnect.runnect.util.analytics.EventName.VIEW_COURSE_SEARCH import com.runnect.runnect.util.custom.deco.GridSpacingItemDecoration import com.runnect.runnect.util.extension.applyScreenEnterAnimation import com.runnect.runnect.util.extension.getCompatibleParcelableExtra @@ -52,7 +55,7 @@ class DiscoverSearchActivity : super.onCreate(savedInstanceState) binding.vm = viewModel binding.lifecycleOwner = this@DiscoverSearchActivity - + Analytics.logClickedItemEvent(VIEW_COURSE_SEARCH) showSearchKeyboard() initSearchAdapter() initSearchRecyclerView() @@ -129,6 +132,7 @@ class DiscoverSearchActivity : if (actionId == IME_ACTION_SEARCH) { val keyword = binding.etDiscoverSearchTitle.text if (!keyword.isNullOrBlank()) { + Analytics.logClickedItemEvent(EVENT_CLICK_TRY_SEARCH_COURSE) viewModel.getCourseSearch(keyword = keyword.toString()) hideKeyboard(binding.etDiscoverSearchTitle) } diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/upload/DiscoverUploadActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/upload/DiscoverUploadActivity.kt index 7dbce9df4..2131dd7d8 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/upload/DiscoverUploadActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/upload/DiscoverUploadActivity.kt @@ -14,6 +14,9 @@ import com.runnect.runnect.binding.BindingActivity import com.runnect.runnect.databinding.ActivityDiscoverUploadBinding import com.runnect.runnect.presentation.MainActivity import com.runnect.runnect.presentation.state.UiState +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_COURSE_UPLOAD +import com.runnect.runnect.util.analytics.EventName.VIEW_COURSE_UPLOAD import com.runnect.runnect.util.extension.hideKeyboard import com.runnect.runnect.util.extension.showToast import dagger.hilt.android.AndroidEntryPoint @@ -27,7 +30,7 @@ class DiscoverUploadActivity : super.onCreate(savedInstanceState) binding.vm = viewModel binding.lifecycleOwner = this - + Analytics.logClickedItemEvent(VIEW_COURSE_UPLOAD) initLayout() addListener() addObserver() @@ -54,6 +57,7 @@ class DiscoverUploadActivity : if (it.isActivated) { viewModel.postUploadMyCourse() } + Analytics.logClickedItemEvent(EVENT_CLICK_COURSE_UPLOAD) } //키보드 이벤트에 따른 동작 정의 binding.root.viewTreeObserver.addOnGlobalLayoutListener { @@ -84,6 +88,7 @@ class DiscoverUploadActivity : UiState.Success -> { handleReturnToDiscover() } + UiState.Failure -> { binding.indeterminateBar.isVisible = false Timber.tag(ContentValues.TAG) diff --git a/app/src/main/java/com/runnect/runnect/presentation/mypage/MyPageFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/mypage/MyPageFragment.kt index 1f716a15b..e0aebe72c 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/mypage/MyPageFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/mypage/MyPageFragment.kt @@ -25,6 +25,10 @@ import com.runnect.runnect.presentation.mypage.reward.MyRewardActivity import com.runnect.runnect.presentation.mypage.setting.MySettingFragment import com.runnect.runnect.presentation.mypage.upload.MyUploadActivity import com.runnect.runnect.presentation.state.UiState +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_GOAL_REWARD +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_RUNNING_RECORD +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_UPLOADED_COURSE import com.runnect.runnect.util.extension.getStampResId import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber @@ -34,10 +38,8 @@ class MyPageFragment : BindingFragment(R.layout.fragment_ private val viewModel: MyPageViewModel by activityViewModels() private lateinit var resultEditNameLauncher: ActivityResultLauncher var isVisitorMode: Boolean = MainActivity.isVisitorMode - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - if (isVisitorMode) { activateVisitorMode() } else { @@ -103,18 +105,22 @@ class MyPageFragment : BindingFragment(R.layout.fragment_ } binding.viewMyPageMainRewardFrame.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_GOAL_REWARD) startActivity(Intent(requireContext(), MyRewardActivity::class.java)) requireActivity().overridePendingTransition( R.anim.slide_in_right, R.anim.slide_out_left ) } binding.viewMyPageMainHistoryFrame.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_RUNNING_RECORD) startActivity(Intent(requireContext(), MyHistoryActivity::class.java)) requireActivity().overridePendingTransition( R.anim.slide_in_right, R.anim.slide_out_left ) } + binding.viewMyPageMainUploadFrame.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_UPLOADED_COURSE) startActivity(Intent(requireContext(), MyUploadActivity::class.java)) requireActivity().overridePendingTransition( R.anim.slide_in_right, R.anim.slide_out_left @@ -171,10 +177,11 @@ class MyPageFragment : BindingFragment(R.layout.fragment_ } } - private fun inquiryKakao(){ + private fun inquiryKakao() { val url = TalkApiClient.instance.channelChatUrl(BuildConfig.KAKAO_CHANNEL_ID) KakaoCustomTabsClient.openWithDefault(requireActivity(), url) } + companion object { const val RES_NAME = "mypage_img_stamp_" const val RES_STAMP_TYPE = "drawable" diff --git a/app/src/main/java/com/runnect/runnect/presentation/mypage/history/MyHistoryActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/mypage/history/MyHistoryActivity.kt index a98f1dfbf..f21edbb5e 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/mypage/history/MyHistoryActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/mypage/history/MyHistoryActivity.kt @@ -17,8 +17,10 @@ import com.runnect.runnect.presentation.mypage.history.adapter.MyHistoryAdapter import com.runnect.runnect.presentation.mypage.history.detail.MyHistoryDetailActivity import com.runnect.runnect.presentation.search.SearchActivity import com.runnect.runnect.presentation.state.UiState -import com.runnect.runnect.util.custom.deco.RecyclerOffsetDecorationHeight +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_COURSE_DRAWING_IN_RUNNING_RECORD import com.runnect.runnect.util.callback.listener.OnMyHistoryItemClick +import com.runnect.runnect.util.custom.deco.RecyclerOffsetDecorationHeight import com.runnect.runnect.util.extension.navigateToPreviousScreenWithAnimation import com.runnect.runnect.util.extension.setCustomDialog import com.runnect.runnect.util.extension.setDialogButtonClickListener @@ -84,6 +86,7 @@ class MyHistoryActivity : BindingActivity(R.layout.act navigateToPreviousScreenWithAnimation() } binding.cvHistoryMyPageDrawCourse.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_COURSE_DRAWING_IN_RUNNING_RECORD) startDrawCourseSearchActivity() } binding.btnMyPageHistoryEditHistory.setOnClickListener { @@ -245,6 +248,7 @@ class MyHistoryActivity : BindingActivity(R.layout.act onBackPressedDispatcher.addCallback(this, callback) } + companion object { const val CHOICE_MODE_DESC = "기록 선택" const val EDIT_CANCEL = "취소" diff --git a/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/MySettingFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/MySettingFragment.kt index 8aa50598d..303f11fb9 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/MySettingFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/MySettingFragment.kt @@ -90,5 +90,6 @@ class MySettingFragment : BindingFragment(R.layout.fra const val TERMS_URL = "https://third-sight-046.notion.site/Runnect-5dfee19ccff04c388590e5ee335e77ed" private const val DEV_MODE_SCHEME = "runnect://devmode" + } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/accountinfo/MySettingAccountInfoFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/accountinfo/MySettingAccountInfoFragment.kt index 5954421f8..9f9e40d6a 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/accountinfo/MySettingAccountInfoFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/mypage/setting/accountinfo/MySettingAccountInfoFragment.kt @@ -17,6 +17,11 @@ import com.runnect.runnect.databinding.FragmentMySettingAccountInfoBinding import com.runnect.runnect.presentation.login.LoginActivity import com.runnect.runnect.presentation.mypage.setting.MySettingFragment import com.runnect.runnect.presentation.state.UiState +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_TRY_LOGOUT +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_TRY_WITHDRAW +import com.runnect.runnect.util.analytics.EventName.EVENT_VIEW_SUCCESS_LOGOUT +import com.runnect.runnect.util.analytics.EventName.EVENT_VIEW_SUCCESS_WITHDRAW import com.runnect.runnect.util.extension.setCustomDialog import com.runnect.runnect.util.extension.setDialogButtonClickListener import com.runnect.runnect.util.extension.showToast @@ -57,10 +62,12 @@ class MySettingAccountInfoFragment : } binding.viewSettingAccountInfoLogoutFrame.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_TRY_LOGOUT) logoutDialog.show() } binding.viewSettingAccountInfoWithdrawalFrame.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_TRY_WITHDRAW) withdrawalDialog.show() } requireActivity().onBackPressedDispatcher.addCallback( @@ -84,6 +91,7 @@ class MySettingAccountInfoFragment : } private fun handleSuccessfulUserDeletion() { + Analytics.logClickedItemEvent(EVENT_VIEW_SUCCESS_WITHDRAW) binding.indeterminateBar.isVisible = false moveToLogin() showToast("탈퇴 처리되었습니다.") @@ -114,6 +122,7 @@ class MySettingAccountInfoFragment : logoutDialog.setDialogButtonClickListener { which -> when (which) { logoutDialog.btn_delete_yes -> { + Analytics.logClickedItemEvent(EVENT_VIEW_SUCCESS_LOGOUT) moveToLogin() } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/mypage/upload/MyUploadActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/mypage/upload/MyUploadActivity.kt index f98e3ecfa..120d8d75d 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/mypage/upload/MyUploadActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/mypage/upload/MyUploadActivity.kt @@ -17,8 +17,10 @@ import com.runnect.runnect.presentation.detail.CourseDetailRootScreen import com.runnect.runnect.presentation.discover.pick.DiscoverPickActivity import com.runnect.runnect.presentation.mypage.upload.adapter.MyUploadAdapter import com.runnect.runnect.presentation.state.UiState -import com.runnect.runnect.util.custom.deco.GridSpacingItemDecoration +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_COURSE_UPLOAD_IN_UPLOADED_COURSE import com.runnect.runnect.util.callback.listener.OnMyUploadItemClick +import com.runnect.runnect.util.custom.deco.GridSpacingItemDecoration import com.runnect.runnect.util.extension.navigateToPreviousScreenWithAnimation import com.runnect.runnect.util.extension.setCustomDialog import com.runnect.runnect.util.extension.setDialogButtonClickListener @@ -39,7 +41,6 @@ class MyUploadActivity : BindingActivity(R.layout.activ binding.vm = viewModel binding.lifecycleOwner = this viewModel.getUserUploadCourse() - initLayout() addListener() addObserver() @@ -52,6 +53,7 @@ class MyUploadActivity : BindingActivity(R.layout.activ initRecyclerView() } + private fun initRecyclerView() { binding.rvMyPageUpload.layoutManager = GridLayoutManager(this, 2) binding.rvMyPageUpload.addItemDecoration( @@ -75,6 +77,7 @@ class MyUploadActivity : BindingActivity(R.layout.activ handleDeleteButtonClicked(it) } binding.cvUploadMyPageUploadCourse.setOnClickListener { + Analytics.logClickedItemEvent(EVENT_CLICK_COURSE_UPLOAD_IN_UPLOADED_COURSE) startActivity(Intent(this, DiscoverPickActivity::class.java)) finish() overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left) diff --git a/app/src/main/java/com/runnect/runnect/presentation/profile/ProfileActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/profile/ProfileActivity.kt index 21d30c6d7..5781284a3 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/profile/ProfileActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/profile/ProfileActivity.kt @@ -9,6 +9,8 @@ import com.runnect.runnect.binding.BindingActivity import com.runnect.runnect.databinding.ActivityProfileBinding import com.runnect.runnect.presentation.detail.CourseDetailActivity import com.runnect.runnect.presentation.state.UiStateV2 +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.VIEW_USER_PROFILE import com.runnect.runnect.util.extension.applyScreenEnterAnimation import com.runnect.runnect.util.extension.showSnackbar import dagger.hilt.android.AndroidEntryPoint @@ -22,6 +24,7 @@ class ProfileActivity : BindingActivity(R.layout.activit super.onCreate(savedInstanceState) binding.vm = viewModel binding.lifecycleOwner = this + Analytics.logClickedItemEvent(VIEW_USER_PROFILE) initAdapter() addListener() addObserver() diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMainFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMainFragment.kt index 66f3d7b23..b7576fb0a 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMainFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMainFragment.kt @@ -14,19 +14,20 @@ import com.runnect.runnect.binding.BindingFragment import com.runnect.runnect.databinding.FragmentStorageMainBinding import com.runnect.runnect.presentation.MainActivity import com.runnect.runnect.presentation.login.LoginActivity +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_MY_DRAW_STORAGE_COURSE_DRAWING_START +import com.runnect.runnect.util.analytics.EventName.EVENT_CLICK_SCRAP_COURSE import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber @AndroidEntryPoint class StorageMainFragment : BindingFragment(R.layout.fragment_storage_main) { - val viewModel: StorageViewModel by viewModels() var isVisitorMode: Boolean = MainActivity.isVisitorMode override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - if (isVisitorMode) { activateVisitorMode() } else { @@ -76,14 +77,19 @@ class StorageMainFragment : override fun onTabSelected(tab: TabLayout.Tab?) { when (tab?.position) { 0 -> childFragmentManager.commit { + Analytics.logClickedItemEvent( + EVENT_CLICK_MY_DRAW_STORAGE_COURSE_DRAWING_START + ) replace(R.id.fl_main) Timber.tag("hu").d("내가 그린 코스로 이동하였음") } 1 -> childFragmentManager.commit { + Analytics.logClickedItemEvent(EVENT_CLICK_SCRAP_COURSE) replace(R.id.fl_main) Timber.tag("hu").d("스크랩으로 이동하였음") } + else -> IllegalArgumentException("${this::class.java.simpleName} Not found menu item id") } } @@ -91,6 +97,7 @@ class StorageMainFragment : // 다른 탭 버튼을 눌러 선택된 탭 버튼이 해제될 때 이벤트 override fun onTabUnselected(tab: TabLayout.Tab?) { } + // 선택된 탭 버튼을 다시 선택할 때 이벤트 override fun onTabReselected(tab: TabLayout.Tab?) { } @@ -98,6 +105,4 @@ class StorageMainFragment : } ) } - - } diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt index 0c4d407d2..6a78e36ba 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt @@ -21,9 +21,11 @@ import com.runnect.runnect.presentation.mydrawdetail.MyDrawDetailActivity import com.runnect.runnect.presentation.search.SearchActivity import com.runnect.runnect.presentation.state.UiState import com.runnect.runnect.presentation.storage.adapter.StorageMyDrawAdapter -import com.runnect.runnect.util.custom.deco.GridSpacingItemDecoration +import com.runnect.runnect.util.analytics.Analytics +import com.runnect.runnect.util.analytics.EventName.EVENT_MY_STORAGE_TRY_REMOVE import com.runnect.runnect.util.callback.ItemCount import com.runnect.runnect.util.callback.listener.OnMyDrawItemClick +import com.runnect.runnect.util.custom.deco.GridSpacingItemDecoration import com.runnect.runnect.util.extension.setFragmentDialog import dagger.hilt.android.AndroidEntryPoint import kotlinx.android.synthetic.main.custom_dialog_delete.view.* @@ -34,7 +36,6 @@ import timber.log.Timber class StorageMyDrawFragment : BindingFragment(R.layout.fragment_storage_my_draw), OnMyDrawItemClick, ItemCount { - val viewModel: StorageViewModel by viewModels() lateinit var storageMyDrawAdapter: StorageMyDrawAdapter @@ -95,6 +96,7 @@ class StorageMyDrawFragment : binding.recyclerViewStorageMyDraw.adapter = storageMyDrawAdapter } + fun hideBottomNav() { animDown = AnimationUtils.loadAnimation(requireActivity(), R.anim.slide_out_down) @@ -214,6 +216,7 @@ class StorageMyDrawFragment : } private fun handleSuccessfulUploadDeletion() { + Analytics.logClickedItemEvent(EVENT_MY_STORAGE_TRY_REMOVE) binding.indeterminateBar.isVisible = false storageMyDrawAdapter.removeItems(viewModel.itemsToDelete) storageMyDrawAdapter.clearSelection() diff --git a/app/src/main/java/com/runnect/runnect/util/analytics/Analytics.kt b/app/src/main/java/com/runnect/runnect/util/analytics/Analytics.kt new file mode 100644 index 000000000..588631812 --- /dev/null +++ b/app/src/main/java/com/runnect/runnect/util/analytics/Analytics.kt @@ -0,0 +1,40 @@ +package com.runnect.runnect.util.analytics + +import android.content.Context +import android.os.Bundle +import android.util.StatsLog.logEvent +import com.google.android.gms.common.wrappers.InstantApps +import com.google.firebase.analytics.FirebaseAnalytics + +object Analytics { + private const val STATUS_INSTALLED = "installed" + private const val STATUS_INSTANT = "instant" + private const val ANALYTICS_USER_PROP = "app_type" + + private var firebaseAnalytics: FirebaseAnalytics? = null + + fun initializeFirebaseAnalytics(context: Context) { + firebaseAnalytics = FirebaseAnalytics.getInstance(context) + + // 현재 앱이 인스턴트 앱인지를 확인하고, 그 여부에 따라 UserProperty 다르게 세팅 + if (InstantApps.isInstantApp(context)) { + setUserProperty(ANALYTICS_USER_PROP, STATUS_INSTANT) + } else { + setUserProperty(ANALYTICS_USER_PROP, STATUS_INSTALLED) + } + } + + private fun setUserProperty(property: String, value: String) { + firebaseAnalytics?.setUserProperty(property, value) + } + + fun logClickedItemEvent(eventName: String, itemName: String? = null) { + val bundle = itemName?.let { + Bundle().apply { + putString(FirebaseAnalytics.Param.ITEM_NAME, it) + } + } + firebaseAnalytics?.logEvent(eventName, bundle) + } + +} diff --git a/app/src/main/java/com/runnect/runnect/util/analytics/EventName.kt b/app/src/main/java/com/runnect/runnect/util/analytics/EventName.kt new file mode 100644 index 000000000..9dda34dca --- /dev/null +++ b/app/src/main/java/com/runnect/runnect/util/analytics/EventName.kt @@ -0,0 +1,45 @@ +package com.runnect.runnect.util.analytics + +object EventName { + // Discover + const val EVENT_CLICK_UPLOAD_BUTTON = "click_upload_button" + const val EVENT_CLICK_DATE = "click_date_sort" + const val EVENT_CLICK_SCRAP = "click_scrap_sort" + const val EVENT_CLICK_TRY_BANNER = "click_try_banner" + const val EVENT_CLICK_TRY_SEARCH_COURSE = "click_try_search_course" + const val EVENT_CLICK_SHARE = "click_share" + const val EVENT_CLICK_USER_PROFILE = "click_user_profile" + const val EVENT_CLICK_COURSE_UPLOAD = "click_course_upload" + + const val VIEW_COURSE_SEARCH = "view_course_search" + const val VIEW_COURSE_DETAIL = "view_course_detail" + const val VIEW_USER_PROFILE = "view_user_profile" + const val VIEW_COURSE_UPLOAD = "view_course_upload" + + // MyPage + const val EVENT_CLICK_RUNNING_RECORD = "click_running_record" + const val EVENT_CLICK_GOAL_REWARD = "click_goal_reward" + const val EVENT_CLICK_UPLOADED_COURSE = "click_uploaded_course" + + // MyHistory + const val EVENT_CLICK_COURSE_DRAWING_IN_RUNNING_RECORD = + "click_course_drawing_in_running_record" + + // MySettingAccountInfo + const val EVENT_VIEW_SUCCESS_LOGOUT = "view_success_logout" + const val EVENT_CLICK_TRY_LOGOUT = "click_try_logout" + const val EVENT_VIEW_SUCCESS_WITHDRAW = "view_success_withdraw" + const val EVENT_CLICK_TRY_WITHDRAW = "click_try_withdraw" + + // MyUpload + const val EVENT_CLICK_COURSE_UPLOAD_IN_UPLOADED_COURSE = + "click_course_upload_in_uploaded_course" + + // StorageMain + const val EVENT_CLICK_MY_DRAW_STORAGE_COURSE_DRAWING_START = + "click_my_storage_course_drawing_start" + const val EVENT_CLICK_SCRAP_COURSE = "click_scrap_course" + + // StorageMyDraw + const val EVENT_MY_STORAGE_TRY_REMOVE = "click_my_storage_try_remove" +} \ No newline at end of file