we have RecyclerView with list of children songs, when you click on a song it takes you to another activity mediaPlayer.. The problem is that when I play a song and then use back bottom the song stop and that is ok, and application stop this is the problem, but when I comment //mediaPlayer.release() the application works well it didn't crash and the song only stop when I go back, but the problem is that when I choose another song from RecyclerView and click PlayBotton the song starts from the start but the SeekBar seeks to the end and don't move. does any body have idea how to solve this?
I tried to but mediaPlayer.release() between Try and Catch but the problem still the same.
class ChildrenSongsPreview : AppCompatActivity() {
private var handler = Handler()
var mediaPlayer: MediaPlayer? = null
private var startTime = 0.0
private var finalTime = 0.0
private var updateSongTime = object : Runnable {
override fun run() {
startTime = mediaPlayer?.currentPosition!!.toDouble()
txt_playing_duration.text = String.format(
"%d:%d", TimeUnit.MILLISECONDS.toMinutes(startTime.toLong()),
TimeUnit.MILLISECONDS.toSeconds(startTime.toLong()) -
TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(startTime.toLong())
)
)
songs_seekbar.progress = startTime.toInt()
handler.postDelayed(this, 100)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_children_songs_preview)
var pos = intent.getIntExtra("KEY_SONG", 0)
var song_ID: Int = R.raw.zahab_elel
when (pos) {
0 -> {
song_ID = R.raw.mama_zmanha_gaya
txt_song_name_preview.text = "ماما زمانها جاية"
}
1 -> {
song_ID = R.raw.zahab_elel
txt_song_name_preview.text = "ذهب الليل"
}
2 -> {
song_ID = R.raw.gdo_ali
txt_song_name_preview.text = "جدو علي"
}
3 -> {
song_ID = R.raw.ebre2_shay
txt_song_name_preview.text = "إبريق الشاي"
}
}
var position = 0
mediaPlayer = MediaPlayer.create(this, song_ID)
//set song duration
finalTime = mediaPlayer?.duration!!.toDouble()
txt_song_duration.text = String.format(
"%d:%d",
TimeUnit.MILLISECONDS.toMinutes(finalTime.toLong()),
TimeUnit.MILLISECONDS.toSeconds(finalTime.toLong()) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(finalTime.toLong()))
)
btn_play.setOnClickListener {
mediaPlayer?.seekTo(position)
mediaPlayer?.start()
btn_play.visibility = View.GONE
btn_pause.visibility = View.VISIBLE
if (oneTimeOnly == 0) {
songs_seekbar!!.max = finalTime.toInt()
oneTimeOnly = 1
}
songs_seekbar!!.progress = startTime.toInt()
handler.postDelayed(updateSongTime, 100)
}
btn_pause.setOnClickListener {
position = mediaPlayer?.currentPosition!!
mediaPlayer?.pause()
btn_pause.visibility = View.GONE
btn_play.visibility = View.VISIBLE
}
btn_stop.setOnClickListener {
mediaPlayer?.stop()
position = 0
btn_pause.visibility = View.GONE
btn_play.visibility = View.VISIBLE
mediaPlayer = MediaPlayer.create(this, song_ID)
}
mediaPlayer?.setOnCompletionListener {
position = 0
btn_pause.visibility = View.GONE
btn_play.visibility = View.VISIBLE
mediaPlayer = MediaPlayer.create(this, song_ID)
}
songs_seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, p: Int, fromUser: Boolean) {
if (fromUser) {
position = p
}
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {
}
override fun onStopTrackingTouch(seekBar: SeekBar?) {
mediaPlayer?.seekTo(position)
}
})
}
override fun onDestroy() {
super.onDestroy()
mediaPlayer?.stop()
mediaPlayer?.release()
}
companion object {
var oneTimeOnly = 0
}
}
Media player instance should also be released in onDestroy()
override fun onDestroy() {
mediaPlayer?.release()
mediaPlayer = null
super.onDestroy()
}
Related
My task is to load recyclerView and show pagination which I both implemented.
I also implemented LoadingState for adapter.
ApiCall:
#GET("top-headlines?sources=bbc-news,techcrunch&apiKey=${BuildConfig.API_KEY}")
suspend fun getTopHeadlinesArticles(
#Query("page") page:Int = 1,
#Query("q") query: String,
) : Response<ArticleListResponse>
I wont show paging because it is working so I will jump to repository:
fun getSearchResult(query: String) =
Pager(
config = PagingConfig(
pageSize = 1,
maxSize = 20,
enablePlaceholders = false
),
pagingSourceFactory = { ArticlePaging(newsService, query)}
).flow
ViewModel:
#OptIn(ExperimentalCoroutinesApi::class)
val news = _currentQuery.flatMapLatest { query ->
articleRepository.getSearchResult(query).cachedIn(viewModelScope)
}
Fragment:
binding.recyclerViewTop.layoutManager = LinearLayoutManager(context)
binding.recyclerViewTop.adapter = adapter.withLoadStateHeaderAndFooter(
header = ArticleLoadStateAdapter { adapter.retry() },
footer = ArticleLoadStateAdapter { adapter.retry() }
)
lifecycleScope.launchWhenCreated {
viewModel.news.collect { articles ->
adapter.submitData(articles)
}
}
And LoadStateViewHolder in LoadStateAdapter:
init {
binding.buttonRetry.setOnClickListener {
retry.invoke()
}
}
fun bind(loadState: LoadState) {
binding.apply {
progressBar.isVisible = loadState is LoadState.Loading
buttonRetry.isVisible = loadState !is LoadState.Loading
textViewError.isVisible = loadState !is LoadState.Loading
}
}
I already predefined DEFAULT_QUERY so I only get 1 Article.
Problem is that progressBar loading is always visible and I have no more articles to show.
Edit: when i have at least 10 items to show this works fine
Edit 2nd: Add ArticlePagingSource if that can help
override fun getRefreshKey(state: PagingState<Int, ArticleResponse>): Int? {
return state.anchorPosition?.let {
val anchorPage = state.closestPageToPosition(it)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}
try {
val currentPageList = params.key ?: 1
response = if(query != ""){
newsService.getTopHeadlinesArticles(currentPageList, query)
} else{
newsService.getTopHeadlinesArticles(currentPageList)
}
val responseList = mutableListOf<ArticleResponse>()
val data = response.body()?.articleResponses ?: emptyList()
responseList.addAll(data)
val prevKey = if (currentPageList == 1) null else currentPageList - 1
return LoadResult.Page(
responseList,
prevKey,
currentPageList.plus(1)
)
I got blocked for this problem, Api will call and get the objects from the response and it will display on the recyclerview. But it is not showing,
fetchProductCategories will do the api call.
prepareProducts will handle the fetched from fetchProductCategories
Fragment:
#AndroidEntryPoint
class ProductsWelcomeFragment : BaseProductsFragment<ProductsWelcomeViewModel, ProductsWelcomeFragmentBinding>() {
private val TAG = "ProductsWelcomeFragment"
#Inject
lateinit var animationQueue: AnimationQueue
override fun getViewModelClass(): KClass<ProductsWelcomeViewModel> = ProductsWelcomeViewModel::class
override fun getContentViewRes(): Int = R.layout.products_welcome_fragment
private val cordovaViewModel: CordovaViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/**
* Initialize only once when everytime accessing products screen.
* */
sharedViewModel.initialSetUpRequest()
viewModel.fetchProductCategories()
}
override fun onBindView() {
with(dataBinding) {
viewModel = this#ProductsWelcomeFragment.viewModel
title = getString(R.string.products_screen_welcome_header)
recyclerViewProducts.configure()
executePendingBindings()
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.productCategoriesLiveData.observe(viewLifecycleOwner) {
Log.i(TAG, it.toString())
viewModel.items.observe(viewLifecycleOwner) {
viewModel.prepareProducts()
}
}
viewModel.showProgress.observe(viewLifecycleOwner) {}
viewModel.failedAtRetrievingData.observe(viewLifecycleOwner) {
// showErrorScreen(true)
}
}
private fun RecyclerView.configure() {
with(dataBinding.recyclerViewProducts) {
addItemBindings(SectionHeaderItemViewBinder)
addItemBindings(SpaceItemViewDtoBinder)
addItemBindings(getListButtonItemViewBinder(ProductItem.NormalProduct::dto, ::onProductItemClick))
addItemBindings(getListBigtileItemViewBinder(ProductItem.FeaturedProduct::dto, ::onProductItemClick))
}
}
private fun onProductItemClick(product: ProductItem.NormalProduct) {
when (product.id) {
else -> { // TODO : )}
}
// TODO : implement move to another screen
}
private fun onProductItemClick(product: ProductItem.FeaturedProduct) {
// TODO : implement move to another screen
}
private fun showErrorScreen(isDataRetrievalError: Boolean) {
val dismissAction = ErrorHandlingAction(
getString(R.string.native_done),
null,
null,
ButtonType.PRIMARY
) { dismissDialog ->
dismissDialog.dismiss()
if (isDataRetrievalError) {
findNavController().popBackStack()
}
}
DialogFactory().showBottomDialog(
fragmentManager = parentFragmentManager,
window = requireActivity().window,
title = getString(R.string.native_error_title),
description = getString(R.string.online_identity_something_went_wrong_error_description),
iconId = R.drawable.ic_error_thick_exclamation_icon,
errorHandlingActions = arrayOf(dismissAction),
isHtmlDescription = true
)
}
private fun openCordovaScreen(destination: CordovaPage) {
cordovaViewModel.requestPage(destination)
findNavController().popBackStack(R.id.homeScreenMainFragment, false)
}
}
ViewModel:
#HiltViewModel
class ProductsWelcomeViewModel #Inject constructor(
private val productsRepository: ProductsRepository
) : BaseRequestViewModel(), ViewModelWithItems {
private val TAG = "ProductsWelcomeViewModel"
private val _failedAtRetrievingData = SingleLiveEvent<Boolean>()
val failedAtRetrievingData: LiveData<Boolean> = _failedAtRetrievingData
private val _showProgress = MutableLiveData<Boolean>()
val showProgress: LiveData<Boolean> = _showProgress
private val onProductCategories: SingleLiveEvent<ProductBasketsCategoriesModel?> = SingleLiveEvent()
val productCategoriesLiveData: LiveData<ProductBasketsCategoriesModel?> = onProductCategories
private val _items: MutableLiveData<List<Any>> = MutableLiveData()
override val items: LiveData<List<Any>> = _items
fun fetchProductCategories() {
viewModelScope.launch {
request({ productsRepository.getProductCategories() },
success = { response -> onProductCategories.value = response },
failure = { })
}
}
fun prepareProducts() {
_items.value = mutableListOf<Any>().apply {
productCategoriesLiveData.value?.embedded?.categories?.filter { categories ->
categories.isFeatured == true }?.let { filteredCategories ->
add(HeaderItem(ListSectionHeaderItemViewDto(
text = TextLine(
textRes = if (filteredCategories.isNotEmpty()) {
R.string.products_screen_welcome_header } else { null }
)
)
))
filteredCategories.toItems()?.let { addAll(it) }
}
productCategoriesLiveData.value?.embedded?.categories?.filter { categories ->
categories.isFeatured == false }.let { filteredCategories ->
if (filteredCategories != null) {
add(HeaderItem(ListSectionHeaderItemViewDto(
text = TextLine(
textRes = if (filteredCategories.isNotEmpty()) {
R.string.products_screen_welcome_header } else { null }
)
)
))
}
filteredCategories.toItems()?.let { addAll(it) }
}
}
}
private fun List<CategoriesItemModel>?.toItems(): List<ProductItem>? =
this?.mapIndexed { index, item ->
if (item.isFeatured == true) {
ProductItem.FeaturedProduct(
id = item.id as Any,
name = item.name,
dto = BigTileDto(
title = TextLine(text = item.name),
image = item.id.toString().let { toFeatureIcon(it, item.isFeatured) },
description = TextLine(item.description.toString()),
background = BackgroundType.SINGLE
)
)
} else {
ProductItem.NormalProduct(
id = item.id as Any,
name = item.name,
dto = ListButtonItemViewDto(
firstLine = TextLine(text = item.name),
rightDrawable = R.drawable.ic_arrow_right,
separatorDrawable = R.drawable.list_divider_margin_start_72dp,
background = index.indexToBackgroundType(this.size),
avatarDto = AvatarDto(iconBackgroundColor = R.color.ubs_concrete, avatarSize = AvatarDto.AvatarSize.SMALL_ICON_SIZE, iconId = toFeatureIcon(
item.id, item.isFeatured
)),
)
)
}
}
private fun toFeatureIcon(id: String?, isFeature: Boolean?): Int = if (ProductFeature.verify(id) == true) {
ProductFeature.icon()
} else { if (isFeature == true) { R.drawable.abc_vector_test } else {
R.drawable.balloon_illustration } }
}
I have an application built using Jetpack Compose , where i also use paging library 3 to fetch data from db , i have multiple remote mediator where i fetch data and save it directly into database , the issue is that sometimes data gets saved , sometimes not , it goes to the point that sometimes one of the two only gets data stored.
Remote Mediator 1:
#ExperimentalPagingApi
class PopularClothingRemoteMediator #Inject constructor(
private val clothingApi: ClothingApi,
private val clothingDatabase: ClothingDatabase
) : RemoteMediator<Int, Clothing>(){
private val clothingDao = clothingDatabase.clothingDao()
private val clothingRemoteKeysDao = clothingDatabase.clothingRemoteKeysDao()
override suspend fun initialize(): InitializeAction {
val currentTime = System.currentTimeMillis()
val lastUpdated = clothingRemoteKeysDao.getRemoteKeys(clothingId = 1)?.lastUpdated ?: 0L
val cacheTimeout = 1440
val diffInMinutes = (currentTime - lastUpdated) / 1000 / 60
return if (diffInMinutes.toInt() <= cacheTimeout) {
// Log.d("RemoteMediator", "UP TO DATE")
InitializeAction.SKIP_INITIAL_REFRESH
} else {
// Log.d("RemoteMediator", "REFRESH")
InitializeAction.LAUNCH_INITIAL_REFRESH
}
}
override suspend fun load(loadType: LoadType, state: PagingState<Int, Clothing>): MediatorResult {
return try {
val page = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
remoteKeys?.nextPage?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
val prevPage = remoteKeys?.prevPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
prevPage
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastItem(state)
val nextPage = remoteKeys?.nextPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
nextPage
}
}
val response = clothingApi.getPopularClothing(page = page)
if (response.popularClothing.isNotEmpty()) {
clothingDatabase.withTransaction {
if (loadType == LoadType.REFRESH) {
clothingDao.deleteAllClothing()
clothingRemoteKeysDao.deleteAllRemoteKeys()
}
val prevPage = response.prevPage
val nextPage = response.nextPage
val keys = response.popularClothing.map { clothing ->
ClothingRemoteKeys(
clothingId = clothing.clothingId,
prevPage = prevPage,
nextPage = nextPage,
lastUpdated = response.lastUpdated
)
}
// When i debug this code , it works fine and the last line is executed
// the issue data sometimes gets saved , sometimes not
clothingRemoteKeysDao.addAllRemoteKeys(clothingRemoteKeys = keys)
clothingDao.addClothing(clothing = response.popularClothing)
}
}
MediatorResult.Success(endOfPaginationReached = response.nextPage == null)
} catch (e: Exception) {
return MediatorResult.Error(e)
}
}
private suspend fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, Clothing>
): ClothingRemoteKeys? {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.clothingId?.let { clothingId ->
clothingRemoteKeysDao.getRemoteKeys(clothingId = clothingId)
}
}
}
private suspend fun getRemoteKeyForFirstItem(
state: PagingState<Int, Clothing>
): ClothingRemoteKeys? {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { clothing ->
clothingRemoteKeysDao.getRemoteKeys(clothingId = clothing.clothingId)
}
}
private suspend fun getRemoteKeyForLastItem(
state: PagingState<Int, Clothing>
): ClothingRemoteKeys? {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { clothing ->
clothingRemoteKeysDao.getRemoteKeys(clothingId = clothing.clothingId)
}
}
}
Remote Mediator 2:
class OuterwearRemoteMediator #Inject constructor(
private val clothingApi: ClothingApi,
private val clothingDatabase: ClothingDatabase
) : RemoteMediator<Int, Clothing>() {
private val clothingDao = clothingDatabase.clothingDao()
private val clothingRemoteKeysDao = clothingDatabase.clothingRemoteKeysDao()
override suspend fun initialize(): InitializeAction {
val currentTime = System.currentTimeMillis()
val lastUpdated = clothingRemoteKeysDao.getRemoteKeys(clothingId = 1)?.lastUpdated ?: 0L
val cacheTimeout = 1440
val diffInMinutes = (currentTime - lastUpdated) / 1000 / 60
return if (diffInMinutes.toInt() <= cacheTimeout) {
// Log.d("RemoteMediator", "UP TO DATE")
InitializeAction.SKIP_INITIAL_REFRESH
} else {
// Log.d("RemoteMediator", "REFRESH")
InitializeAction.LAUNCH_INITIAL_REFRESH
}
}
override suspend fun load(loadType: LoadType, state: PagingState<Int, Clothing>): MediatorResult {
return try {
val page = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
remoteKeys?.nextPage?.minus(1) ?: 1
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
val prevPage = remoteKeys?.prevPage
?: return MediatorResult.Success(
endOfPaginationReached = remoteKeys != null
)
prevPage
}
LoadType.APPEND -> {
val remoteKeys = getRemoteKeyForLastItem(state)
val nextPage = remoteKeys?.nextPage
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
nextPage
}
}
val response = clothingApi.getOuterwear(page = page)
if (response.outerwear.isNotEmpty()) {
clothingDatabase.withTransaction {
if (loadType == LoadType.REFRESH) {
clothingDao.deleteAllClothing()
clothingRemoteKeysDao.deleteAllRemoteKeys()
}
val prevPage = response.prevPage
val nextPage = response.nextPage
val keys = response.outerwear.map { clothing ->
ClothingRemoteKeys(
clothingId = clothing.clothingId,
prevPage = prevPage,
nextPage = nextPage,
lastUpdated = response.lastUpdated
)
}
// the same thing here
// When i debug this code , it works fine and the last line is executed
// the issue data sometimes gets saved , sometimes not
clothingRemoteKeysDao.addAllRemoteKeys(clothingRemoteKeys = keys)
clothingDao.addClothing(clothing = response.outerwear)
}
}
MediatorResult.Success(endOfPaginationReached = response.nextPage == null)
} catch (e: Exception) {
return MediatorResult.Error(e)
}
}
private suspend fun getRemoteKeyClosestToCurrentPosition(
state: PagingState<Int, Clothing>): ClothingRemoteKeys? {
return state.anchorPosition?.let { position ->
state.closestItemToPosition(position)?.clothingId?.let { clothingId ->
clothingRemoteKeysDao.getRemoteKeys(clothingId = clothingId)
}
}
}
private suspend fun getRemoteKeyForFirstItem(
state: PagingState<Int, Clothing>): ClothingRemoteKeys? {
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
?.let { clothing ->
clothingRemoteKeysDao.getRemoteKeys(clothingId = clothing.clothingId)
}
}
private suspend fun getRemoteKeyForLastItem(
state: PagingState<Int, Clothing>
): ClothingRemoteKeys? {
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
?.let { clothing ->
clothingRemoteKeysDao.getRemoteKeys(clothingId = clothing.clothingId)
}
}
I have followed this tutorial Tutorial by Alex mamo and got it finnished. When i now check if a user exist and i have a clean build of my emulator it works but if i run it on an already hot build of my emulator the firebase database still answers me with a user id why is this? this is my code...
AuthListener:
override fun getFirebaseAuthState() = callbackFlow<Boolean>{
val authStateListener = FirebaseAuth.AuthStateListener { auth ->
println("Current user:" + auth.currentUser)
trySend(auth.currentUser == null)
}
auth.checkIfUserExists()?.addAuthStateListener(authStateListener)
awaitClose {
auth.checkIfUserExists()?.removeAuthStateListener(authStateListener)
}
}
ViewModel:
#HiltViewModel
class SplashViewModel #Inject constructor(private val repository: IAuthRepository) : ViewModel() {
private val _event : MutableStateFlow<AuthEvent> = MutableStateFlow(AuthEvent.notBeingUsed)
val event : StateFlow<AuthEvent> = _event
fun checkIfUserExists() = viewModelScope.launch {
repository.getFirebaseAuthState().collectLatest{task ->
println("Task2:" + task)
if(task){
_event.value = AuthEvent.Failure("User is not logged in")
}else{
_event.value = AuthEvent.Success
}
}
}
}
UI:
#Composable
fun SplashScreen(navController: NavController, viewModel : SplashViewModel = hiltViewModel()){
val coroutineScope = rememberCoroutineScope()
Surface(modifier = Modifier.fillMaxSize()) {
val overshootInterpolator = remember {
OvershootInterpolator(2f)
}
val scale = remember {
Animatable(0f)
}
LaunchedEffect(key1 = true){
scale.animateTo(
targetValue = 1f,
animationSpec = tween(
durationMillis = 500,
easing = {
overshootInterpolator.getInterpolation(it)
}
)
)
delay(Constants.SPLASH_SCREEN_DURATION)
viewModel.checkIfUserExists()
viewModel.event.collect{
println("Task it: " + it)
when(it){
is AuthEvent.Success -> {
navController.popBackStack()
navController.navigate(PaperSellerScreens.CustomerListScreen.name)
}
is AuthEvent.Failure ->{
navController.popBackStack()
navController.navigate(PaperSellerScreens.LoginScreen.name)
}
}
}
}
val painterIcon = painterResource(R.drawable.logo_size_invert)
val painterBackground = painterResource(id = R.drawable.paper_seller_background)
Box(modifier = Modifier.fillMaxSize()){
Image(painter = painterBackground, contentDescription = "SplashScreen",contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize())
Image(painterIcon, "Icon Image", modifier = Modifier
.size(200.dp, 200.dp)
.scale(scale.value)
.align(
Alignment.Center
)
.clip(RoundedCornerShape(10.dp)))
}
}
}
A very newbie programmer here and not a good English typer. Im trying to create a checker for purchase that already made previous using the PurchaseHistoryResponseListener. And When a checker found something, it will add to a list and then feed the recyclerview_MYBook with that data. The issue is that when launching the app, the data is flow through the recyclerview_MYBook perfectly, but when moving to different activity and going back to the previous activity through a different method (button click) the data on the recyclerview_MYBook doesn't show up, only through a conventional back button, the data on the recyclerview show up. Below here is my noob code
class MainActivity : AppCompatActivity(), PurchasesUpdatedListener {
private lateinit var billingClient: BillingClient
private lateinit var blogadapternew: BlogRecyclerAdapterNew
private lateinit var blogadapterpremium: BlogRecyclerAdapterPremium
private lateinit var blogadapterfree: BlogRecyclerAdapterFree
private lateinit var blogadaptermybook: BlogRecyclerAdapterMyBook
private lateinit var auth: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
auth = FirebaseAuth.getInstance()
//FirebaseAuth.getInstance().signOut()
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
setContentView(R.layout.activity_main)
recycler_viewNew.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL,false)
recycler_viewNew.adapter= BlogRecyclerAdapterNew()
recycler_viewPremium.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
recycler_viewPremium.adapter= BlogRecyclerAdapterPremium()
recycler_viewFree.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
recycler_viewFree.adapter= BlogRecyclerAdapterFree()
recycler_viewMyBook.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
recycler_viewMyBook.adapter= BlogRecyclerAdapterMyBook()
if (supportActionBar != null)
supportActionBar?.hide()
setupBillingClient()
initrecyclerView()
initrecyclerViewPremium()
initrecyclerViewFree()
initrecyclerViewMyBook()
addDataSetNew()
addDataSetPremium()
addDataSetFree()
Logo.setOnClickListener{
val intent = Intent(MonstaLogo.context, MainActivity::class.java)
MonstaLogo.context.startActivity(intent)
}
MainFeaturedButton.setOnClickListener {
val intent = Intent(MainFeaturedButton.context, MainActivity::class.java)
MainFeaturedButton.context.startActivity(intent)
}
MainNewButton.setOnClickListener {
val intent = Intent(MainNewButton.context, NewActivity::class.java)
MainNewButton.context.startActivity(intent)
}
NewMore.setOnClickListener{
val intent = Intent(NewMore.context, NewActivity::class.java)
NewMore.context.startActivity(intent)
}
MainPremiumButton.setOnClickListener {
val intent = Intent(MainPremiumButton.context, PremiumActivity::class.java)
MainPremiumButton.context.startActivity(intent)
}
PremiumMore.setOnClickListener{
val intent = Intent(PremiumMore.context, PremiumActivity::class.java)
PremiumMore.context.startActivity(intent)
}
MainFreeButton.setOnClickListener {
val intent = Intent(MainFreeButton.context, FreeActivity::class.java)
MainFreeButton.context.startActivity(intent)
}
FreeMore.setOnClickListener {
val intent = Intent(FreeMore.context, FreeActivity::class.java)
FreeMore.context.startActivity(intent)
}
MainMyBookButton.setOnClickListener {
val intent = Intent(MainMyBookButton.context, MyBookActivity::class.java)
MainMyBookButton.context.startActivity(intent)
}
MyBookMore.setOnClickListener {
val intent = Intent(MyBookMore.context, MyBookActivity::class.java)
MyBookMore.context.startActivity(intent)
}
}
private fun setupBillingClient() {
billingClient = BillingClient.newBuilder(this)
.enablePendingPurchases()
.setListener(this)
.build()
billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready. You can query purchases here.
println("Setup Billing Done")
PurchaseHistoryResponseListener()
}
}
override fun onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
println("Failed")
setupBillingClient()
println("Restart Connection")
}
})
}
override fun onPurchasesUpdated(
billingResult: BillingResult?,
purchases: MutableList<Purchase>?
) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
private fun PurchaseHistoryResponseListener (){
billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP) {
responseCode, result ->
// println("queryPurchasesAsync INAPP results: ${result?.size}")
// println("Getting Purchase History")
println("$result")
val dataMyBook1 = DataSourceMyBook.createDataSet()
if ("testcode1" in result.toString()) {
println("found it 1")
dataMyBook1.add((BlogPost( "BookName","Link","No")))
}
if ("testcode2" in result.toString()) {
println("found it 2")
dataMyBook1.add((BlogPost( "BookName","Link","No")))
}
if ("testcode3" in result.toString()) {
println("found it 3")
dataMyBook1.add((BlogPost( "BookName","Link","No")))
}
blogadaptermybook.submitList(dataMyBook1)
println(dataMyBook1)
}
}
private fun addDataSetNew(){
val dataNew = DataSourceNew.createDataSet()
blogadapternew.submitList(dataNew)
}
private fun addDataSetPremium(){
val dataPremium = DataSourcePremium.createDataSet()
blogadapterpremium.submitList(dataPremium)
}
private fun addDataSetFree(){
val dataFree = DataSourceFree.createDataSet()
blogadapterfree.submitList(dataFree)
}
/*private fun addDataSetMyBook(){
val dataMyBook1 = DataSourceMyBook.createDataSet()
blogadaptermybook.submitList(dataMyBook1)
}*/
/*private fun addDataSetMyBook(){
val dataMyBook1 = DataSourceMyBook.createDataSet()
billingClient.queryPurchaseHistoryAsync(BillingClient.SkuType.INAPP) {
responseCode, result ->
println("$result")
if ("bbbg_s2_c1_testcode1" in result.toString()){
dataMyBook1.add((BlogPost( "Mini Comic 1","Link","No")))
}
if ("bbbg_s2_c1_testcode2" in result.toString()){
dataMyBook1.add((BlogPost( "Mini Comic 2","Link","No")))
}
if ("bbbg_s2_c1_testcode3" in result.toString()){
dataMyBook1.add((BlogPost( "Mini Comic 3","Link","No")))
}
blogadaptermybook.submitList(dataMyBook1)
}}*/
/*dataMyBook.add((BlogPost( "Mini Comic 1","Link","No")))
dataMyBook.add((BlogPost( "Mini Comic 1","Link","No")))
dataMyBook.add((BlogPost( "Mini Comic 1","Link","No")))*/
private fun initrecyclerView(){
recycler_viewNew.apply {
layoutManager = LinearLayoutManager(this#MainActivity,RecyclerView.HORIZONTAL,false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadapternew = BlogRecyclerAdapterNew()
adapter = blogadapternew
}
}
private fun initrecyclerViewPremium(){
recycler_viewPremium.apply {
layoutManager = LinearLayoutManager(this#MainActivity,RecyclerView.HORIZONTAL,false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadapterpremium = BlogRecyclerAdapterPremium()
adapter = blogadapterpremium
}
}
private fun initrecyclerViewFree(){
recycler_viewFree.apply {
layoutManager = LinearLayoutManager(this#MainActivity,RecyclerView.HORIZONTAL,false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadapterfree = BlogRecyclerAdapterFree()
adapter = blogadapterfree
}
}
private fun initrecyclerViewMyBook(){
recycler_viewMyBook.apply {
layoutManager =
LinearLayoutManager(this#MainActivity, RecyclerView.HORIZONTAL, false)
val topSpacingItemDecoration = TopSpacingItemDecoration(padding = 30)
addItemDecoration(topSpacingItemDecoration)
blogadaptermybook = BlogRecyclerAdapterMyBook()
adapter = blogadaptermybook
}
}
public override fun onStart() {
super.onStart()
val currentUser = auth.currentUser
updateUI(currentUser)
}
private fun updateUI(currentUser: FirebaseUser?) {
if (currentUser != null) {
AccountSettingButton.setImageResource(R.drawable.profileicon)
}
}
}
Here is adapter
class BlogRecyclerAdapterMyBook : RecyclerView.Adapter() {
private var items: List<BlogPost> = ArrayList()
private var items2: List<BlogPost> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return BlogViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.layout_blog_list_item_mybook,
parent,
false
)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is BlogViewHolder -> {
holder.bind(items.get(position))
holder.bind(items2.get(position))
}
}
}
override fun getItemCount(): Int {
return items.size
}
fun submitList(bloglist: List<BlogPost>) {
items = bloglist
items2 = bloglist
}
class BlogViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
val blogImage: ImageButton = itemView.blog_imagemybook
val blogTitle: TextView = itemView.blog_titlemybook
val premiumImage: ImageView = itemView.premiumicon
fun bind(blogPost: BlogPost) {
blogTitle.setText(blogPost.title)
val requestOptions = RequestOptions()
.placeholder(R.drawable.mocksplash)
.error(R.drawable.disconnect)
Glide.with(itemView.blog_imagemybook)
.applyDefaultRequestOptions(requestOptions)
.load(blogPost.image)
.into(blogImage)
blogImage.setOnClickListener {
Toast.makeText(blogImage.context, "<<Swipe left<<", Toast.LENGTH_SHORT).show()
val intent = Intent(blogTitle.context, ComicReadingActivity::class.java)
var KomikName = blogTitle.text.toString()
intent.putExtra("KomikName",Name)
blogImage.context.startActivity(intent)
}
}
}
}
and here the data source file where that will store the data for the adapter
class DataSourceMyBook{
companion object{
fun createDataSet(): ArrayList<BlogPost> {
val dataMyBook1 = ArrayList<BlogPost>()
return dataMyBook1
}
}
}