-
-
Save eldartsa/ba3e0f47e279d21242aa09b1c51e863f to your computer and use it in GitHub Desktop.
First Gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.name.activities | |
import android.annotation.SuppressLint | |
import android.content.Context | |
import android.content.pm.ActivityInfo | |
import android.content.res.Configuration | |
import android.os.Bundle | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.view.WindowManager | |
import android.widget.ImageView | |
import android.widget.RelativeLayout | |
import androidx.activity.viewModels | |
import androidx.appcompat.app.AppCompatActivity | |
import androidx.appcompat.app.AppCompatDelegate | |
import androidx.core.os.bundleOf | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.addRepeatingJob | |
import androidx.navigation.fragment.NavHostFragment | |
import androidx.viewbinding.ViewBinding | |
import com.ironsource.mediationsdk.IronSource | |
import com.name.R | |
import com.name.customViews.CustomHeaderView | |
import com.name.dataClasses.HeaderItem | |
import com.name.dataClasses.Point | |
import com.name.enums.EAlertDialogType | |
import com.name.enums.ECountAnimAction | |
import com.name.helpers.LocaleHelper | |
import com.name.utils.MyUtils | |
import com.name.utils.SnappLog | |
import com.name.utils.constants.General | |
import com.name.utils.extensions.coinsToHeaderAnimation | |
import com.name.utils.extensions.getNonNullBundle | |
import com.name.utils.extensions.navigateSafe | |
import kotlinx.coroutines.flow.collect | |
import java.util.* | |
/** | |
* Created by Eldar Tsafar on 13/10/2017. | |
*/ | |
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() { | |
private val baseActivitySharedViewModel: BaseActivitySharedViewModel by viewModels() | |
private val baseActivityViewModel: BaseActivityViewModel by viewModels() | |
private var _binding: ViewBinding? = null | |
abstract val bindingInflater: (LayoutInflater) -> VB | |
protected val navHostFragment | |
get() = (supportFragmentManager.findFragmentById(getNavHostId()) as NavHostFragment) | |
protected val currentFragmentId | |
get() = navHostFragment.navController.currentDestination?.id ?: 0 | |
@Suppress("UNCHECKED_CAST") | |
protected val binding: VB | |
get() = _binding as VB | |
abstract fun getNavHostId(): Int | |
abstract fun getHeaderView(): CustomHeaderView? | |
abstract fun getBundle(bundle: Bundle) | |
abstract fun initView() | |
abstract fun subscribeToViewModel() | |
override fun attachBaseContext(newBase: Context) { | |
SnappLog.log("${javaClass.simpleName}-> attachBaseContext") | |
super.attachBaseContext(LocaleHelper.onAttach(newBase)) | |
} | |
@SuppressLint("SourceLockedOrientationActivity") | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
SnappLog.log("${javaClass.simpleName}-> onCreate") | |
setTheme(R.style.AppTheme) | |
_binding = bindingInflater.invoke(layoutInflater) | |
val view = binding.root | |
setContentView(view) | |
val screenLayoutSize: Int = resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK | |
if (screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_SMALL || screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_NORMAL) { | |
if (!General.IS_DEBUG_MODE) { | |
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT | |
} | |
} | |
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) | |
getBundle(intent.extras.getNonNullBundle()) | |
initView() | |
setHeaderViewCallbacks() | |
subscribeToViewModel() | |
subscribeBaseActivitySharedViewModel() | |
} | |
private fun subscribeBaseActivitySharedViewModel() { | |
addRepeatingJob(Lifecycle.State.RESUMED) { | |
baseActivitySharedViewModel.baseActivitySharedViewModelFragment.collect { event -> | |
when (event) { | |
is BaseActivitySharedViewModel.BaseActivitySharedViewModelEvent.BlockScreen -> { | |
blockScreen(event.isBlocked) | |
} | |
is BaseActivitySharedViewModel.BaseActivitySharedViewModelEvent.UpdateHeaderContent -> { | |
updateHeaderContent(event.headerItem) | |
} | |
is BaseActivitySharedViewModel.BaseActivitySharedViewModelEvent.UpdateCoinsAmount -> { | |
updateHeaderCoins(event.coinsAmount) | |
} | |
is BaseActivitySharedViewModel.BaseActivitySharedViewModelEvent.ShowCoinsAnimation -> { | |
showCoinsAnimation(event.amount, event.countAnimAction, event.coinsAmount, event.shouldShowCoinsSpreadAnimation) | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Header view callbacks | |
*/ | |
private fun setHeaderViewCallbacks() { | |
getHeaderView()?.setCallback(object : CustomHeaderView.HeaderCallback { | |
override fun onCoinsClicked() { | |
navigateToMarket() | |
} | |
override fun onBackClicked() { | |
onBackPressed() | |
} | |
}) | |
} | |
private fun navigateToMarket() { | |
navigateSafe(viewId = R.id.nav_host_fragment, resId = R.id.action_global_marketFragment, currentFragmentId = currentFragmentId) | |
} | |
/** | |
* Init header content | |
*/ | |
private fun updateHeaderContent(headerItem: HeaderItem?) { | |
val headerView = getHeaderView() | |
headerView?.let { | |
headerView.initView(headerItem) | |
} | |
} | |
/** | |
* Update header coins | |
*/ | |
private fun updateHeaderCoins(coinsAmount: Int) { | |
val headerView = getHeaderView() | |
headerView?.updateCoins(coinsAmount) | |
} | |
/**\ | |
* Update header visibility | |
*/ | |
protected fun showCustomHeaderLayout(shouldShow: Boolean) { | |
val headerView = getHeaderView() | |
headerView?.let { | |
if (shouldShow) { | |
headerView.visibility = View.VISIBLE | |
} else { | |
headerView.visibility = View.GONE | |
} | |
} | |
} | |
/** | |
* Block screen for touch | |
*/ | |
private fun blockScreen(shouldBlock: Boolean) { | |
if (shouldBlock) { | |
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) | |
} else { | |
window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) | |
} | |
} | |
/** | |
* Show coins animation in header | |
*/ | |
private fun showCoinsAnimation(amount: Int, countAnimAction: ECountAnimAction, coinsAmount: Int, shouldShowCoinsSpreadAnimation: Boolean) { | |
val headerView = getHeaderView() | |
headerView?.let { | |
it.updateCoins(coinsAmount) | |
it.showCoinsAnimation(amount, countAnimAction) | |
if (shouldShowCoinsSpreadAnimation) { | |
val desPoint = headerView.getCoinsTvPositionPoint() | |
animateCoins(desPoint, coinsAmount) | |
} | |
} | |
} | |
private fun animateCoins(desPoint: Point, coinsAmount: Int) { | |
val coinSize = resources.getDimensionPixelSize(R.dimen.header_coins_animation_coin_size) | |
val maximumCoinsAmount = 30 | |
val range = resources.getDimensionPixelOffset(R.dimen.header_coins_animation_range) | |
val screenCenterX = MyUtils.getScreenWidth() / 2 | |
val screenCenterY = MyUtils.getScreenHeight() / 2 | |
var coinsAmountForAnimation = coinsAmount / 10 | |
if (coinsAmountForAnimation > maximumCoinsAmount) { | |
coinsAmountForAnimation = maximumCoinsAmount | |
} | |
val rnd = Random() | |
for (i in 0..coinsAmountForAnimation) { | |
val coinIv = ImageView(this) | |
val layoutParams: RelativeLayout.LayoutParams = RelativeLayout.LayoutParams(coinSize, coinSize) | |
coinIv.layoutParams = layoutParams | |
coinIv.setImageResource(R.drawable.ic_coin) | |
val randomX = (screenCenterX - range / 2) + rnd.nextInt(range) | |
val randomY = (screenCenterY - range / 2) + rnd.nextInt(range) | |
coinIv.x = randomX.toFloat() | |
coinIv.y = randomY.toFloat() | |
val parentView = binding.root as ViewGroup | |
parentView.addView(coinIv) | |
val animDuration = rnd.nextInt(500) + 1000 | |
coinIv.coinsToHeaderAnimation(parentView, desPoint.x, desPoint.y, animDuration.toLong()) { | |
baseActivityViewModel.onCoinsToHeaderAnimationEnd() | |
} | |
} | |
} | |
protected fun showAlertDialog(title: String? = null, message: String? = null, positiveButton: String? = null, negativeButton: String? = null, | |
titleImageRes: Int = 0, isDialogCancelable: Boolean = true, dialogType: EAlertDialogType = EAlertDialogType.NON) { | |
val args = bundleOf("title" to title, "message" to message, "positiveButton" to positiveButton, "negativeButton" to negativeButton, | |
"titleImageRes" to titleImageRes, "isDialogCancelable" to isDialogCancelable, "dialogType" to dialogType) | |
navigateSafe(viewId = getNavHostId(), resId = R.id.action_global_alertDialogFragment, currentFragmentId = currentFragmentId, args = args) | |
} | |
override fun onStart() { | |
super.onStart() | |
baseActivityViewModel.startTimer() | |
} | |
override fun onStop() { | |
super.onStop() | |
baseActivityViewModel.stopTimer() | |
} | |
override fun onResume() { | |
super.onResume() | |
SnappLog.log("${javaClass.simpleName}-> onResume") | |
IronSource.onResume(this) | |
} | |
override fun onPause() { | |
super.onPause() | |
SnappLog.log("${javaClass.simpleName}-> onPause") | |
IronSource.onPause(this) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.name.activities | |
import android.content.Intent | |
import android.os.Bundle | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import androidx.activity.viewModels | |
import androidx.core.content.ContextCompat | |
import androidx.core.os.bundleOf | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.addRepeatingJob | |
import com.gameanalytics.sdk.GameAnalytics | |
import com.name.R | |
import com.name.dataClasses.EventDialogData | |
import com.name.databinding.ActivityMainBinding | |
import com.name.enums.EEventDialogType | |
import com.name.helpers.LocaleHelper | |
import com.name.helpers.NavigationHelper | |
import com.name.managers.* | |
import com.name.managers.adsManager.AdsManager | |
import com.name.managers.adsManager.BannerHelper | |
import com.name.utils.FlavorConsts | |
import com.name.utils.constants.CoinsAmount | |
import com.name.utils.extensions.* | |
import com.tenjin.android.TenjinSDK | |
import dagger.hilt.android.AndroidEntryPoint | |
import kotlinx.coroutines.flow.collect | |
import java.util.* | |
import javax.inject.Inject | |
@AndroidEntryPoint | |
class MainActivity : BaseActivity<ActivityMainBinding>() { | |
companion object { | |
const val SHOULD_AVOID_INTERSTITIAL_RESULT_PARAM = "shouldAvoidInterstitial" | |
} | |
override val bindingInflater: (LayoutInflater) -> ActivityMainBinding | |
get() = ActivityMainBinding::inflate | |
private val mainActivityViewModel: MainActivityViewModel by viewModels() | |
private val mainSharedViewModel: MainSharedViewModel by viewModels() | |
@Inject | |
lateinit var purchaseManager: PurchaseManager | |
@Inject | |
lateinit var adsManager: AdsManager | |
@Inject | |
lateinit var actionManager: ActionManager | |
override fun onNewIntent(intent: Intent?) { | |
super.onNewIntent(intent) | |
mainActivityViewModel.onNewIntent(intent) | |
} | |
override fun getNavHostId() = binding.navHostFragment.id | |
override fun getHeaderView() = binding.headerView | |
override fun getBundle(bundle: Bundle) { | |
} | |
override fun initView() { | |
mainActivityViewModel.init() | |
binding.adViewContainer.layoutParams.height = BannerHelper.getAdmobBannerSize(this).getHeightInPixels(this) | |
initGameAnalytics() | |
} | |
private fun initGameAnalytics() { | |
// Enable log | |
GameAnalytics.setEnabledInfoLog(true) | |
GameAnalytics.setEnabledVerboseLog(true) | |
// Configure build version | |
GameAnalytics.configureAutoDetectAppVersion(true) | |
GameAnalytics.initialize(this, getString(R.string.game_analytics_game_key), getString(R.string.game_analytics_secret_key)) | |
} | |
private fun firstNavigation(eStartDestination: MainActivityViewModel.EStartDestination) { | |
val navController = navHostFragment.navController | |
val inflater = navController.navInflater | |
val graph = inflater.inflate(R.navigation.nav_main) | |
when (eStartDestination) { | |
MainActivityViewModel.EStartDestination.SPLASH -> { | |
// no need to make a change!! | |
graph.startDestination = R.id.splashFragment | |
navController.graph = graph | |
} | |
MainActivityViewModel.EStartDestination.CHOOSE_DB_TYPE -> { | |
graph.startDestination = R.id.chooseDbTypeFragment | |
navController.graph = graph | |
} | |
} | |
navController.addOnDestinationChangedListener { _, destination, _ -> | |
when (destination.id) { | |
R.id.splashFragment -> { | |
showCustomHeaderLayout(shouldShow = false) | |
showBannerContainer(canShowByPremium = actionManager.shouldShowAds(), canShowByDestination = false) | |
} | |
R.id.chooseDbTypeFragment -> { | |
showCustomHeaderLayout(shouldShow = true) | |
showBannerContainer(canShowByPremium = actionManager.shouldShowAds(), canShowByDestination = false) | |
} | |
else -> { | |
showCustomHeaderLayout(shouldShow = true) | |
showBannerContainer(canShowByPremium = actionManager.shouldShowAds(), canShowByDestination = true) | |
} | |
} | |
} | |
} | |
override fun subscribeToViewModel() { | |
addRepeatingJob(Lifecycle.State.CREATED) { | |
mainActivityViewModel.mainActivityViewModelEvent.collect { event -> | |
when (event) { | |
MainActivityViewModel.MainActivityViewModelEvent.ShowWelcomeDialog -> { | |
navigateSafe(viewId = R.id.nav_host_fragment, resId = R.id.action_global_welcomeDialogFragment, currentFragmentId = currentFragmentId) | |
} | |
is MainActivityViewModel.MainActivityViewModelEvent.NavigateToStartDestination -> { | |
firstNavigation(event.eStartDestination) | |
} | |
is MainActivityViewModel.MainActivityViewModelEvent.UpdateLanguage -> { | |
adsManager.onDestroy() | |
LocaleHelper.setLocale(this@MainActivity, event.languageCode) | |
NavigationHelper.restartActivity(this@MainActivity) | |
} | |
is MainActivityViewModel.MainActivityViewModelEvent.ShowEventDialog -> { | |
showEventDialog(event.eventDialogData) | |
} | |
MainActivityViewModel.MainActivityViewModelEvent.ShowInterstitialAd -> { | |
adsManager.showInterstitialAd() | |
} | |
is MainActivityViewModel.MainActivityViewModelEvent.NavigateToUrlAndCloseApp -> { | |
finish() | |
NavigationHelper.openUrl(this@MainActivity, event.url) | |
} | |
MainActivityViewModel.MainActivityViewModelEvent.InitAdsManager -> { | |
adsManager.init(this@MainActivity, lifecycle) | |
} | |
MainActivityViewModel.MainActivityViewModelEvent.InitTenjin -> { | |
val instance = TenjinSDK.getInstance(this@MainActivity, FlavorConsts.TENJIN_SDK_KEY) | |
instance.connect() | |
} | |
} | |
} | |
} | |
addRepeatingJob(Lifecycle.State.RESUMED) { | |
mainSharedViewModel.gamePlayChannel.collect { event -> | |
when (event) { | |
is MainSharedViewModel.GamePlayEvent.AddLevelFinishDialog -> { | |
addLevelFinishDialog(event.levelNum) | |
} | |
is MainSharedViewModel.GamePlayEvent.AddTopicFinishDialog -> { | |
addTopicFinishDialog(event.topicName) | |
} | |
is MainSharedViewModel.GamePlayEvent.AddGameFinishDialog -> { | |
addGameFinishDialog() | |
} | |
is MainSharedViewModel.GamePlayEvent.AddLevelsUnlockDialog -> { | |
addLevelsUnlockDialog(event.levels) | |
} | |
is MainSharedViewModel.GamePlayEvent.AddTopicUnlockDialog -> { | |
addTopicUnlockedDialog(event.topicName) | |
} | |
is MainSharedViewModel.GamePlayEvent.ShowDialogs -> { | |
mainActivityViewModel.showEventDialog(event.shouldAvoidInterstitial) | |
} | |
MainSharedViewModel.GamePlayEvent.CheckWelcome -> { | |
mainActivityViewModel.checkWelcomeDialog() | |
} | |
is MainSharedViewModel.GamePlayEvent.OnQuestionSolved -> { | |
// GoogleGameHelper.onQuestionSolved(this@MainActivity, event.topicType, event.solvedQuestionsInGame) | |
} | |
} | |
} | |
} | |
addRepeatingJob(Lifecycle.State.RESUMED) { | |
adsManager.bannerAdsEvent.collect { event -> | |
when (event) { | |
is AdsManager.BannerAdsEvent.OnBannerCreated -> { | |
onBannerCreated(event.adView) | |
} | |
is AdsManager.BannerAdsEvent.OnBannerHeightMeasured -> { | |
setBannerHeight(event.bannerHeight) | |
} | |
is AdsManager.BannerAdsEvent.ForceShowBannerContainer -> { | |
showBannerContainer(event.shouldShow) | |
} | |
else -> return@collect | |
} | |
} | |
} | |
} | |
private fun setBannerHeight(bannerHeight: Int) { | |
binding.adViewContainer.layoutParams.height = bannerHeight | |
binding.adViewContainer.requestLayout() | |
} | |
private fun showEventDialog(eventDialogData: EventDialogData) { | |
getNavigationDialogResult<Boolean>(R.id.nav_host_fragment, currentFragmentId, SHOULD_AVOID_INTERSTITIAL_RESULT_PARAM) { shouldAvoidInterstitial -> | |
mainActivityViewModel.showEventDialog(shouldAvoidInterstitial) | |
} | |
navigateSafe(viewId = R.id.nav_host_fragment, | |
resId = R.id.action_global_eventDialogFragment, | |
currentFragmentId = currentFragmentId, | |
args = bundleOf("eventDialogData" to eventDialogData)) | |
} | |
private fun onBannerCreated(bannerView: View) { | |
binding.adViewContainer.apply { | |
bannerView.parent?.let { | |
(bannerView.parent as ViewGroup).removeView(bannerView) | |
} | |
addView(bannerView) | |
} | |
} | |
private fun showBannerContainer(canShowByPremium: Boolean, canShowByDestination: Boolean = true) { | |
if (canShowByPremium && canShowByDestination) { | |
binding.adViewContainer.visibility = View.VISIBLE | |
} else { | |
binding.adViewContainer.visibility = View.GONE | |
} | |
} | |
private fun addLevelsUnlockDialog(levels: List<Int>) { | |
val eventDialogData = EventDialogData(eventDialogType = EEventDialogType.LEVEL_UNLOCK, | |
title = getString(R.string.level_unlocked_dialog_title), | |
subTitle = levels.getUnlockLevelsText(this), | |
backgroundColor = ContextCompat.getColor(this, R.color.dark_gray), | |
rewardAmount = CoinsAmount.LEVEL_UNLOCKED) | |
mainActivityViewModel.addEventDialogData(eventDialogData) | |
} | |
private fun addLevelFinishDialog(levelNum: Int) { | |
val eventDialogData = EventDialogData(eventDialogType = EEventDialogType.LEVEL_FINISH, | |
title = getString(R.string.level_unlocked_dialog_title), | |
subTitle = getString(R.string.level_finished_dialog_message, levelNum), | |
backgroundColor = ContextCompat.getColor(this, R.color.dark_gray), | |
rewardAmount = CoinsAmount.LEVEL_FINISHED) | |
mainActivityViewModel.addEventDialogData(eventDialogData) | |
} | |
private fun addTopicUnlockedDialog(topicName: String) { | |
val eventDialogData = EventDialogData(eventDialogType = EEventDialogType.TOPIC_UNLOCK, | |
title = getString(R.string.topic_unlocked_dialog_title), | |
subTitle = getString(R.string.topic_unlocked_dialog_message, topicName), | |
backgroundColor = ContextCompat.getColor(this, R.color.dark_gray), | |
rewardAmount = CoinsAmount.LEVEL_FINISHED) | |
mainActivityViewModel.addEventDialogData(eventDialogData) | |
} | |
private fun addTopicFinishDialog(topicName: String) { | |
val eventDialogData = EventDialogData(eventDialogType = EEventDialogType.TOPIC_FINISH, | |
title = getString(R.string.topic_finished_dialog_title), | |
subTitle = getString(R.string.topic_finished_dialog_message, topicName), | |
backgroundColor = ContextCompat.getColor(this, R.color.dark_gray), | |
rewardAmount = CoinsAmount.LEVEL_FINISHED) | |
mainActivityViewModel.addEventDialogData(eventDialogData) | |
} | |
private fun addGameFinishDialog() { | |
} | |
@Suppress("DEPRECATION") | |
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | |
if (!purchaseManager.bp.handleActivityResult(requestCode, resultCode, data)) { | |
super.onActivityResult(requestCode, resultCode, data) | |
} | |
} | |
override fun onResume() { | |
super.onResume() | |
mainActivityViewModel.onResume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment