diff --git a/app/build.gradle b/app/build.gradle index a99e22b7a..9d1c672c0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { applicationId "org.sopt.havit" minSdk 23 targetSdk 31 - versionCode 103 - versionName "1.0.3" + versionCode 104 + versionName "1.0.4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "HAVIT_BASE_URL_DEV", properties["HAVIT_BASE_URL_DEV"]) buildConfigField("String", "HAVIT_BASE_URL_PROD", properties["HAVIT_BASE_URL_PROD"]) diff --git a/app/src/main/java/org/sopt/havit/MainActivity.kt b/app/src/main/java/org/sopt/havit/MainActivity.kt index d429a94da..896e80d91 100644 --- a/app/src/main/java/org/sopt/havit/MainActivity.kt +++ b/app/src/main/java/org/sopt/havit/MainActivity.kt @@ -9,6 +9,11 @@ import com.google.android.material.bottomnavigation.BottomNavigationView import dagger.hilt.android.AndroidEntryPoint import org.sopt.havit.databinding.ActivityMainBinding import org.sopt.havit.ui.save.SaveFragment +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.GNB_ADD_CONTENT +import org.sopt.havit.util.GoogleAnalyticsUtil.GNB_CATEGORY +import org.sopt.havit.util.GoogleAnalyticsUtil.GNB_HOME +import org.sopt.havit.util.GoogleAnalyticsUtil.GNB_MYPAGE @AndroidEntryPoint class MainActivity : AppCompatActivity() { @@ -16,6 +21,7 @@ class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var navController: NavController private lateinit var navView: BottomNavigationView + private var isInitialized: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -32,6 +38,26 @@ class MainActivity : AppCompatActivity() { navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) as NavHostFragment navController = navHostFragment.navController + // 바텀네비게이션 클릭 시 ga 이벤트 보냄 + navController.addOnDestinationChangedListener { _, destination, _ -> + when (destination.id) { + R.id.navigation_home -> { + // 처음 홈 화면 진입 시는 클릭해서 진입한게 아니므로 이벤트 보내지 않음 + if (isInitialized) { + GoogleAnalyticsUtil.logClickEvent(GNB_HOME) + } else { + isInitialized = true + } + } + R.id.navigation_category -> { + GoogleAnalyticsUtil.logClickEvent(GNB_CATEGORY) + } + R.id.navigation_my_page -> { + GoogleAnalyticsUtil.logClickEvent(GNB_MYPAGE) + } + else -> {} + } + } navView.setupWithNavController(navController) binding.navView.background = null } @@ -39,6 +65,8 @@ class MainActivity : AppCompatActivity() { private fun setListeners() { binding.floatingSave.bringToFront() binding.floatingSave.setOnClickListener { + // 콘텐츠 추가 플로팅 버튼 클릭 시 + GoogleAnalyticsUtil.logClickEvent(GNB_ADD_CONTENT) SaveFragment("").show(supportFragmentManager, "save") } } diff --git a/app/src/main/java/org/sopt/havit/ui/contents/ContentsActivity.kt b/app/src/main/java/org/sopt/havit/ui/contents/ContentsActivity.kt index a6df800c7..9793e8a12 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents/ContentsActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents/ContentsActivity.kt @@ -432,6 +432,10 @@ class ContentsActivity : BaseBindingActivity(R.layout.a contentsViewModel.setIsSeen(contentsAdapter.currentList[position].id) currentHavitView = v currentHavitPosition = position + GoogleAnalyticsUtil.logClickEventWithContentCheck( + GoogleAnalyticsUtil.CLICK_CONTENT_CHECK, + !(contentsAdapter.currentList[position].isSeen) + ) } }) } diff --git a/app/src/main/java/org/sopt/havit/ui/contents/ContentsViewModel.kt b/app/src/main/java/org/sopt/havit/ui/contents/ContentsViewModel.kt index 4aaaa47c4..cf5b2d925 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents/ContentsViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents/ContentsViewModel.kt @@ -7,7 +7,6 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.sopt.havit.data.remote.ContentsMoreData import org.sopt.havit.domain.entity.Contents import org.sopt.havit.domain.entity.NetworkState import org.sopt.havit.domain.repository.ContentsRepository diff --git a/app/src/main/java/org/sopt/havit/ui/home/HomeFragment.kt b/app/src/main/java/org/sopt/havit/ui/home/HomeFragment.kt index da17b54fb..b772ffd4b 100644 --- a/app/src/main/java/org/sopt/havit/ui/home/HomeFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/home/HomeFragment.kt @@ -23,6 +23,13 @@ import org.sopt.havit.ui.web.WebActivity import org.sopt.havit.util.PopupSharedPreference import org.sopt.havit.util.setDragSensitivity import org.sopt.havit.util.setOnSingleClickListener +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_MUST_SEE_CONTENT +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_SEARCH_CONTENT +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_WHOLE_CATEGORY +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_HAVIT_SERVICE_GUIDE +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_SEE_MORE +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_RECOMMENDED_SITE @AndroidEntryPoint class HomeFragment : BaseBindingFragment(R.layout.fragment_home) { @@ -92,6 +99,8 @@ class HomeFragment : BaseBindingFragment(R.layout.fragment_ recommendRvAdapter.setItemClickListener(object : HomeRecommendRvAdapter.OnItemClickListener { override fun onWebClick(v: View, position: Int) { + GoogleAnalyticsUtil.logClickEventWithRecommendedSiteNum(CLICK_RECOMMENDED_SITE, position) + val intent = Intent(v.context, WebActivity::class.java) homeViewModel.recommendList.value?.get(position) ?.let { @@ -229,24 +238,29 @@ class HomeFragment : BaseBindingFragment(R.layout.fragment_ startActivity(intent) } binding.clReachContents.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_MUST_SEE_CONTENT) val intent = Intent(requireActivity(), ContentsSimpleActivity::class.java) intent.putExtra(CONTENT_TYPE, "unseen") startActivity(intent) } binding.layoutCategory.tvCategoryAll.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_WHOLE_CATEGORY) val intent = Intent(requireActivity(), HomeCategoryAllActivity::class.java) startActivity((intent)) } binding.clSearchClickable.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_SEARCH_CONTENT) val intent = Intent(requireActivity(), SearchActivity::class.java) startActivity(intent) } binding.tvMoreContents.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_SEE_MORE) val intent = Intent(requireActivity(), ContentsSimpleActivity::class.java) intent.putExtra(CONTENT_TYPE, "recent") startActivity(intent) } binding.ivServiceGuide.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_HAVIT_SERVICE_GUIDE) val intent = Intent(requireActivity(), ServiceGuideActivity::class.java) startActivity(intent) } diff --git a/app/src/main/java/org/sopt/havit/ui/mypage/MyPageFragment.kt b/app/src/main/java/org/sopt/havit/ui/mypage/MyPageFragment.kt index 4d029427c..0c3d91a0e 100644 --- a/app/src/main/java/org/sopt/havit/ui/mypage/MyPageFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/mypage/MyPageFragment.kt @@ -13,6 +13,10 @@ import org.sopt.havit.databinding.FragmentMyPageBinding import org.sopt.havit.ui.base.BaseBindingFragment import org.sopt.havit.ui.contents.ContentsActivity import org.sopt.havit.ui.setting.SettingActivity +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_CHECKED_CONTENT +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_MY_CATEGORY +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_MY_CONTENT @AndroidEntryPoint class MyPageFragment : BaseBindingFragment(R.layout.fragment_my_page) { @@ -42,6 +46,7 @@ class MyPageFragment : BaseBindingFragment(R.layout.fragm private fun setListeners() { binding.clCategoryNum.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_MY_CATEGORY) startActivity( Intent( requireContext(), @@ -50,6 +55,7 @@ class MyPageFragment : BaseBindingFragment(R.layout.fragm ) } binding.clSavedContents.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_MY_CONTENT) startActivity( Intent(requireContext(), ContentsActivity::class.java).apply { putExtra("categoryId", ALL_CONTENTS_ID) @@ -58,6 +64,7 @@ class MyPageFragment : BaseBindingFragment(R.layout.fragm ) } binding.clSeenContents.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_CHECKED_CONTENT) startActivity( Intent(requireContext(), ContentsActivity::class.java).apply { putExtra("categoryId", SEEN_CONTENTS_ID) diff --git a/app/src/main/java/org/sopt/havit/ui/search/SearchActivity.kt b/app/src/main/java/org/sopt/havit/ui/search/SearchActivity.kt index 883d0faf2..021b315db 100644 --- a/app/src/main/java/org/sopt/havit/ui/search/SearchActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/search/SearchActivity.kt @@ -17,6 +17,7 @@ import org.sopt.havit.ui.base.BaseBindingActivity import org.sopt.havit.ui.contents.more.ContentsMoreFragment import org.sopt.havit.ui.web.WebActivity import org.sopt.havit.util.DialogUtil +import org.sopt.havit.util.GoogleAnalyticsUtil import org.sopt.havit.util.KeyBoardUtil import java.io.Serializable @@ -118,6 +119,10 @@ class SearchActivity : BaseBindingActivity(R.layout.activ ) { searchContentsAdapter.searchContents[pos].isSeen = !(data.isSeen) searchViewModel.setIsSeen(data.id) + GoogleAnalyticsUtil.logClickEventWithContentCheck( + GoogleAnalyticsUtil.CLICK_CONTENT_CHECK, + data.isSeen + ) if (v.tag == "seen") { Glide.with(v.context) .load(R.drawable.ic_contents_unread) diff --git a/app/src/main/java/org/sopt/havit/ui/search/SearchViewModel.kt b/app/src/main/java/org/sopt/havit/ui/search/SearchViewModel.kt index 899a37f6b..f9dc28d16 100644 --- a/app/src/main/java/org/sopt/havit/ui/search/SearchViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/search/SearchViewModel.kt @@ -12,6 +12,7 @@ import org.sopt.havit.domain.entity.Contents import org.sopt.havit.domain.entity.NetworkState import org.sopt.havit.domain.repository.ContentsRepository import org.sopt.havit.domain.usecase.SearchUseCase +import org.sopt.havit.util.GoogleAnalyticsUtil import javax.inject.Inject @HiltViewModel @@ -23,14 +24,10 @@ class SearchViewModel @Inject constructor( private val _searchResult = MutableLiveData>() var searchResult: LiveData> = _searchResult - var searchResultSize = MutableLiveData(0) - private var _searchReload = MutableLiveData(false) + private var _searchReload = MutableLiveData(false) var searchReload: LiveData = _searchReload - fun setReload() { - _searchReload.value = !(_searchReload.value)!! - } var searchTv = MutableLiveData(false) private var isSeenCheck = MutableLiveData(false) @@ -38,6 +35,8 @@ class SearchViewModel @Inject constructor( private var _isRead = MutableLiveData() var isRead: LiveData = _isRead + var isServerNetwork = MutableLiveData() + fun getSearchContents(keyWord: String) { viewModelScope.launch { searchUseCase.getSearchContents(keyWord).collect { @@ -59,10 +58,14 @@ class SearchViewModel @Inject constructor( fun setIsSeen(contentsId: Int) { viewModelScope.launch(Dispatchers.IO) { - try { - val response = contentsRepository.isSeen(contentsId) - isSeenCheck.postValue(response.success) - } catch (e: Exception) { + kotlin.runCatching { + contentsRepository.isSeen(contentsId) + + }.onSuccess { + isServerNetwork.postValue(NetworkState.SUCCESS) + isSeenCheck.postValue(it.success) + }.onFailure { + isServerNetwork.postValue(NetworkState.FAIL) } } } diff --git a/app/src/main/java/org/sopt/havit/ui/share/add_category/ChooseIconFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/add_category/ChooseIconFragment.kt index 8ad59d061..d7588151a 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/add_category/ChooseIconFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/add_category/ChooseIconFragment.kt @@ -13,10 +13,8 @@ import org.sopt.havit.ui.base.BaseBindingFragment import org.sopt.havit.ui.category.CategoryAddActivity import org.sopt.havit.ui.share.AddCategoryViewModel import org.sopt.havit.ui.share.add_category.IconAdapter.Companion.clickedPosition -import org.sopt.havit.util.ADD_CATEGORY_TYPE -import org.sopt.havit.util.ToastUtil -import org.sopt.havit.util.setOnSingleClickListener -import org.sopt.havit.util.setOnSinglePostClickListener +import org.sopt.havit.util.* +import org.sopt.havit.util.GoogleAnalyticsUtil.SELECT_ICON @AndroidEntryPoint class ChooseIconFragment : @@ -35,6 +33,7 @@ class ChooseIconFragment : initNetworkErrorViewClickListener() toolbarClickListener() observeNetworkStatus() + setScreenEventLogging() } private fun toolbarClickListener() { @@ -66,9 +65,16 @@ class ChooseIconFragment : private fun initNormalViewClickNext() { binding.btnNext.setOnSinglePostClickListener { viewModel.addCategory() + setClickEventLogging() } } + private fun setClickEventLogging() { + val iconIdx = requireNotNull(viewModel.selectedIconPosition.value) + GoogleAnalyticsUtil.logClickEventOnAddCategory(iconNum = iconIdx) + } + + private fun observeNetworkStatus() { viewModel.addCategoryViewState.observe(viewLifecycleOwner) { when (it) { @@ -95,4 +101,8 @@ class ChooseIconFragment : categoryName = viewModel.categoryTitle.value ?: throw IllegalStateException() ) } + + private fun setScreenEventLogging() { + GoogleAnalyticsUtil.logScreenEvent(SELECT_ICON) + } } diff --git a/app/src/main/java/org/sopt/havit/ui/share/add_category/EnterCategoryTitleFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/add_category/EnterCategoryTitleFragment.kt index fd9ec04fe..36a95b9ac 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/add_category/EnterCategoryTitleFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/add_category/EnterCategoryTitleFragment.kt @@ -12,6 +12,8 @@ import org.sopt.havit.databinding.FragmentEnterCategoryTitleBinding import org.sopt.havit.domain.model.NetworkStatus import org.sopt.havit.ui.base.BaseBindingFragment import org.sopt.havit.ui.share.AddCategoryViewModel +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.ADD_CATEGORY import org.sopt.havit.util.KeyBoardUtil import org.sopt.havit.util.KeyBoardUtil.setUpAsSoftKeyboard import org.sopt.havit.util.setOnSingleClickListener @@ -34,6 +36,7 @@ class EnterCategoryTitleFragment : setKeyBoardState() toolbarClickListener() setUpAsSoftKeyboard(view) // 다음버튼 위/아래 움직이게 + setScreenEventLogging() } private fun getExistingCategoryList() { @@ -87,4 +90,8 @@ class EnterCategoryTitleFragment : KeyBoardUtil.openKeyBoard(requireContext(), binding.etCategoryTitle) else KeyBoardUtil.hideKeyBoard(requireActivity()) } + + private fun setScreenEventLogging() { + GoogleAnalyticsUtil.logScreenEvent(ADD_CATEGORY) + } } diff --git a/app/src/main/java/org/sopt/havit/ui/share/contents_summery/ContentsSummeryFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/contents_summery/ContentsSummeryFragment.kt index 6eb454e56..f5b00f9e3 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/contents_summery/ContentsSummeryFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/contents_summery/ContentsSummeryFragment.kt @@ -12,6 +12,8 @@ import org.sopt.havit.domain.model.NetworkStatus import org.sopt.havit.ui.base.BaseBindingFragment import org.sopt.havit.ui.share.ShareViewModel import org.sopt.havit.util.* +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_COMPLETE_SAVE_CONTENT +import org.sopt.havit.util.GoogleAnalyticsUtil.CONTENT_CUSTOM import javax.inject.Inject @AndroidEntryPoint @@ -30,6 +32,7 @@ class ContentsSummeryFragment : initListener() toolbarClickListener() onClickRefreshButtonOnNetworkError() + setScreenEventLogging() } private fun initListener() { @@ -74,6 +77,7 @@ class ContentsSummeryFragment : private fun saveContents() { viewModel.saveContents() + setClickEventLogging() } private fun toolbarClickListener() { @@ -99,5 +103,13 @@ class ContentsSummeryFragment : } } + private fun setScreenEventLogging() { + GoogleAnalyticsUtil.logScreenEvent(CONTENT_CUSTOM) + } + + private fun setClickEventLogging() { + GoogleAnalyticsUtil.logClickEvent(CLICK_COMPLETE_SAVE_CONTENT) + } + private fun setCustomToast() = ToastUtil(requireContext()).makeToast(ADD_CONTENT_TYPE) } diff --git a/app/src/main/java/org/sopt/havit/ui/share/edit_title/EditTitleFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/edit_title/EditTitleFragment.kt index de618b8c4..b48ed9b01 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/edit_title/EditTitleFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/edit_title/EditTitleFragment.kt @@ -11,10 +11,9 @@ import androidx.navigation.fragment.navArgs import dagger.hilt.android.AndroidEntryPoint import org.sopt.havit.databinding.FragmentEditTitleBinding import org.sopt.havit.ui.share.ShareViewModel -import org.sopt.havit.util.AutoClearedValue -import org.sopt.havit.util.DialogUtil -import org.sopt.havit.util.KeyBoardUtil -import org.sopt.havit.util.OnBackPressedHandler +import org.sopt.havit.util.* +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_COMPLETE_MODIFY_TITLE +import org.sopt.havit.util.GoogleAnalyticsUtil.MODIFY_TITLE @AndroidEntryPoint class EditTitleFragment : Fragment(), OnBackPressedHandler { @@ -36,6 +35,7 @@ class EditTitleFragment : Fragment(), OnBackPressedHandler { setKeyBoardUp() initClickListener() setCursor() + setScreenEventLogging() } private fun setCursor() { @@ -58,10 +58,15 @@ class EditTitleFragment : Fragment(), OnBackPressedHandler { binding.icBack.setOnClickListener { onBackClicked() } binding.tvComplete.setOnClickListener { viewModel.ogData.value?.ogTitle = binding.etTitle.text.toString() + setClickEventLogging() goBack() } } + private fun setClickEventLogging() { + GoogleAnalyticsUtil.logClickEvent(CLICK_COMPLETE_MODIFY_TITLE) + } + private fun onBackClicked() { if (isTitleChanged) showEditTitleWarningDialog() else goBack() @@ -83,4 +88,8 @@ class EditTitleFragment : Fragment(), OnBackPressedHandler { private fun goBack() { findNavController().popBackStack() } + + private fun setScreenEventLogging() { + GoogleAnalyticsUtil.logScreenEvent(MODIFY_TITLE) + } } diff --git a/app/src/main/java/org/sopt/havit/ui/share/notification/SetNotificationFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/notification/SetNotificationFragment.kt index 7c7bbb05a..7746eaffe 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/notification/SetNotificationFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/notification/SetNotificationFragment.kt @@ -15,6 +15,9 @@ import org.sopt.havit.ui.share.notification.SetNotificationFragment.Companion.TH import org.sopt.havit.ui.share.notification.SetNotificationFragment.Companion.TWENTY_FOUR import org.sopt.havit.ui.share.notification.SetNotificationFragment.Companion.TWO import org.sopt.havit.util.DialogUtil +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_COMPLETE_SETTING_ALARM +import org.sopt.havit.util.GoogleAnalyticsUtil.SETTING_ALARM import org.sopt.havit.util.OnBackPressedHandler import java.util.* @@ -33,6 +36,7 @@ class SetNotificationFragment : initRadioGroupListener() initToolbarListener() initDeleteNotiBtn() + setScreenEventLogging() } private fun initDeleteNotiBtn() { @@ -68,10 +72,15 @@ class SetNotificationFragment : binding.icBack.setOnClickListener { onBackClicked() } binding.tvComplete.setOnClickListener { viewModel.syncFinalDataWithTempData() + setClickEventLogging() goBack() } } + private fun setClickEventLogging() { + GoogleAnalyticsUtil.logClickEvent(CLICK_COMPLETE_SETTING_ALARM) + } + private fun showPickerFragment() { val bottomSheet = PickerFragment() bottomSheet.show(childFragmentManager, bottomSheet.tag) @@ -114,6 +123,10 @@ class SetNotificationFragment : findNavController().popBackStack() } + private fun setScreenEventLogging() { + GoogleAnalyticsUtil.logScreenEvent(SETTING_ALARM) + } + companion object { const val ONE = 1 const val TWO = 2 diff --git a/app/src/main/java/org/sopt/havit/ui/share/select_category/SelectCategoryFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/select_category/SelectCategoryFragment.kt index da912db7a..89e5a095e 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/select_category/SelectCategoryFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/select_category/SelectCategoryFragment.kt @@ -12,6 +12,8 @@ import org.sopt.havit.databinding.FragmentSelectCategoryBinding import org.sopt.havit.ui.base.BaseBindingFragment import org.sopt.havit.ui.contents.more.edit_category.SelectableCategoryAdapter import org.sopt.havit.ui.share.ShareViewModel +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.SELECT_CATEGORY import org.sopt.havit.util.setOnSingleClickListener @AndroidEntryPoint @@ -33,6 +35,7 @@ class SelectCategoryFragment : initListener() toolbarClickListener() onClickRefreshButtonOnNetworkError() + setScreenEventLogging() } private fun getCategoryData() { @@ -96,6 +99,10 @@ class SelectCategoryFragment : toast.show() } + private fun setScreenEventLogging() { + GoogleAnalyticsUtil.logScreenEvent(SELECT_CATEGORY) + } + override fun onDestroyView() { viewModel.clearCategoryViewState() super.onDestroyView() diff --git a/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt b/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt index ed45c81f8..0f61cc59d 100644 --- a/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt @@ -2,13 +2,12 @@ package org.sopt.havit.ui.web import android.content.Intent import android.os.Bundle -import android.util.Log +import android.os.SystemClock +import android.view.View.GONE import android.view.animation.AnimationUtils import android.webkit.* import android.widget.Toast import androidx.activity.viewModels -import androidx.core.content.ContentProviderCompat.requireContext -import androidx.core.view.isVisible import com.bumptech.glide.Glide import dagger.hilt.android.AndroidEntryPoint import org.sopt.havit.R @@ -16,17 +15,24 @@ import org.sopt.havit.databinding.ActivityWebBinding import org.sopt.havit.domain.entity.NetworkState import org.sopt.havit.ui.base.BaseBindingActivity import org.sopt.havit.util.EventObserver -import retrofit2.http.Url +import org.sopt.havit.util.GoogleAnalyticsUtil +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_GO_BACK +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_REFRESH +import org.sopt.havit.util.GoogleAnalyticsUtil.CLICK_SHARE +import org.sopt.havit.util.GoogleAnalyticsUtil.CONTENT_SCREEN_TIME @AndroidEntryPoint class WebActivity : BaseBindingActivity(R.layout.activity_web) { private val webViewModel: WebViewModel by viewModels() + private var startTime: Int = 0 + private var endTime: Int = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) binding.vm = webViewModel + startTime = SystemClock.elapsedRealtime().toInt() initIsHavit() initHavitSeen() setUrlCheck() @@ -40,7 +46,7 @@ class WebActivity : BaseBindingActivity(R.layout.activity_we private fun initHavitSeen() { if (intent.getIntExtra("contentsId", -1) == -1) { - binding.llWebBottom.isVisible = false + binding.llWebview.visibility = GONE } if (!intent.getBooleanExtra("isSeen", false)) { Glide.with(this).load(R.drawable.ic_contents_unread).into(binding.ivWebviewUnread) @@ -100,18 +106,26 @@ class WebActivity : BaseBindingActivity(R.layout.activity_we private fun setListeners() { binding.llWebview.setOnClickListener { + GoogleAnalyticsUtil.logClickEventWithContentCheck( + GoogleAnalyticsUtil.CLICK_CONTENT_CHECK, + !(webViewModel.isHavit.value!!.peekContent()) + ) webViewModel.setHavit(intent!!.getIntExtra("contentsId", 0)) } binding.ibWebBack.setOnClickListener { + setWebViewDurationTimeLogging() + GoogleAnalyticsUtil.logClickEvent(CLICK_GO_BACK) finish() } binding.llWebShare.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_SHARE) val intentShare = Intent(Intent.ACTION_SEND) intentShare.putExtra(Intent.EXTRA_TEXT, intent.getStringExtra("url")) intentShare.type = "text/plain" startActivity(Intent.createChooser(intentShare, "앱을 선택해 주세요.")) } binding.ibWebReload.setOnClickListener { + GoogleAnalyticsUtil.logClickEvent(CLICK_REFRESH) binding.wbCustom.reload() } binding.layoutNetworkError.ivRefresh.setOnClickListener { @@ -133,9 +147,16 @@ class WebActivity : BaseBindingActivity(R.layout.activity_we toast.show() } + private fun setWebViewDurationTimeLogging() { + endTime = SystemClock.elapsedRealtime().toInt() + GoogleAnalyticsUtil.logScreenDurationTimeEvent(CONTENT_SCREEN_TIME, endTime - startTime) + } + override fun onBackPressed() { super.onBackPressed() super.finish() + setWebViewDurationTimeLogging() + GoogleAnalyticsUtil.logClickEvent(CLICK_GO_BACK) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/sopt/havit/ui/web/WebViewModel.kt b/app/src/main/java/org/sopt/havit/ui/web/WebViewModel.kt index eb9fdc606..9afbc8689 100644 --- a/app/src/main/java/org/sopt/havit/ui/web/WebViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/web/WebViewModel.kt @@ -5,7 +5,6 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.sopt.havit.domain.entity.NetworkState import org.sopt.havit.domain.repository.ContentsRepository diff --git a/app/src/main/java/org/sopt/havit/util/GoogleAnalyticsUtil.kt b/app/src/main/java/org/sopt/havit/util/GoogleAnalyticsUtil.kt new file mode 100644 index 000000000..4f9e9e4a4 --- /dev/null +++ b/app/src/main/java/org/sopt/havit/util/GoogleAnalyticsUtil.kt @@ -0,0 +1,101 @@ +package org.sopt.havit.util + +import android.os.Bundle +import com.google.firebase.analytics.FirebaseAnalytics +import com.google.firebase.analytics.ktx.analytics +import com.google.firebase.analytics.ktx.logEvent +import com.google.firebase.ktx.Firebase + +object GoogleAnalyticsUtil { + + // property + private const val OS_TYPE = "os_type" + private const val ANDROID = "android" + + init { + Firebase.analytics.setUserProperty(OS_TYPE, ANDROID) + } + + fun logScreenEvent(screenName: String) { + Firebase.analytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW) { + param(FirebaseAnalytics.Param.SCREEN_NAME, screenName) + } + } + + fun logClickEvent(contentName: String) { + Firebase.analytics.logEvent(contentName, null) + } + + fun logClickEventWithContentCheck(contentName: String, contentCheck: Boolean) { + val params = Bundle().apply { + putBoolean(CONTENT_CHECK, contentCheck) + } + Firebase.analytics.logEvent(contentName, params) + } + + fun logScreenDurationTimeEvent(contentName: String, durationTime: Int) { + val params = Bundle().apply { + putInt(SCREEN_TIME, durationTime) + } + Firebase.analytics.logEvent(contentName, params) + } + + fun logClickEventWithRecommendedSiteNum(contentName: String, siteNum: Int) { + val params = Bundle().apply { + putInt(SITE_NUM, siteNum) + } + Firebase.analytics.logEvent(contentName, params) + } + + fun logClickEventOnAddCategory(iconNum: Int) { + val params = Bundle().apply { + putInt(ICON_NUM, iconNum) + } + Firebase.analytics.logEvent(CLICK_COMPLETE_SELECT_ICON, params) + } + + // parameter + private const val CONTENT_CHECK = "click_content_check" + private const val SCREEN_TIME = "screen_time" + private const val SITE_NUM = "site_num" + private const val ICON_NUM = "icon_num" + + // save contents + const val SELECT_CATEGORY = "select_category" + const val CONTENT_CUSTOM = "content_custom" + const val CLICK_COMPLETE_SAVE_CONTENT = "click_complete_save_content" + const val SETTING_ALARM = "setting_alarm" + const val CLICK_COMPLETE_SETTING_ALARM = "click_complete_setting_alarm" + const val MODIFY_TITLE = "modify_title" + const val CLICK_COMPLETE_MODIFY_TITLE = "click_complete_modify_title" + + // create category + const val ADD_CATEGORY = "add_category" + const val SELECT_ICON = "select_icon" + const val CLICK_COMPLETE_SELECT_ICON = "click_complete_select_icon" + + // mypage + const val CLICK_MY_CATEGORY = "click_my_category" + const val CLICK_MY_CONTENT = "click_my_content" + const val CLICK_CHECKED_CONTENT = "click_checked_content" + + // webview + const val CLICK_GO_BACK = "click_go_back" + const val CLICK_REFRESH = "click_refresh" + const val CLICK_SHARE = "click_share" + const val CLICK_CONTENT_CHECK = "click_content_check" + const val CONTENT_SCREEN_TIME = "content_screen_time" + + // home + const val CLICK_MUST_SEE_CONTENT = "click_must_see_content" + const val CLICK_SEARCH_CONTENT = "click_search_content" + const val CLICK_WHOLE_CATEGORY = "click_whole_category" + const val CLICK_HAVIT_SERVICE_GUIDE = "click_havit_service_guide" + const val CLICK_SEE_MORE = "click_see_more" + const val CLICK_RECOMMENDED_SITE = "click_recommended_site" + const val GNB_HOME = "gnb_home" + const val GNB_CATEGORY = "gnb_category" + const val GNB_MYPAGE = "gnb_mypage" + const val GNB_ADD_CONTENT = "gnb_add_content" + +} diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml index 092cd8f02..a7aa894e2 100644 --- a/app/src/main/res/layout/activity_web.xml +++ b/app/src/main/res/layout/activity_web.xml @@ -1,7 +1,6 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -98,7 +97,7 @@ @@ -113,7 +112,7 @@ - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 3a89560e2..6fc6af985 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -629,4 +629,4 @@ - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_picker.xml b/app/src/main/res/layout/fragment_picker.xml index ae380bdb0..121e7e1fb 100644 --- a/app/src/main/res/layout/fragment_picker.xml +++ b/app/src/main/res/layout/fragment_picker.xml @@ -111,4 +111,4 @@ android:textColor="@color/havit_purple" app:layout_constraintBottom_toBottomOf="parent" /> - \ No newline at end of file +