private lateinit var youtubePLayerInit: YouTubePlayer.OnInitializedListener
private fun openTrailer(videoId: String) {
val dialog = Dialog(this)
val trailerDialogBinding = DialogTrailerBinding.inflate(layoutInflater)
dialog.setContentView(trailerDialogBinding.root)
dialog.setCanceledOnTouchOutside(false)
val youtubeApiKey = "xxxxx"
youtubePLayerInit = object: YouTubePlayer.OnInitializedListener {
override fun onInitializationSuccess(
p0: YouTubePlayer.Provider?,
p1: YouTubePlayer?,
p2: Boolean
) {
p1?.loadVideo(videoId)
}
override fun onInitializationFailure(
p0: YouTubePlayer.Provider?,
p1: YouTubeInitializationResult?
) {
Toast.makeText(applicationContext, "Video Failed to Load", Toast.LENGTH_SHORT).show()
}
}
trailerDialogBinding.vvMovieTrailer.initialize(youtubeApiKey, youtubePLayerInit)
dialog.show()
trailerDialogBinding.btnExit.setOnClickListener {
dialog.dismiss()
}
}
Thing is that video loads only one time, when I reload the video then dismissing the dialog. It doesn't load, then after like 3 or 4 times of loading, the app crashes with the errors of :
E/YouTubeAndroidPlayerAPI: Embed config is not supported in RemoteEmbeddedPlayer.
E/YouTubeAndroidPlayerAPI: Error screen presenter should be present
I call this video about 3 times, but only the video only loads one time. How can I fix this?
Related
when open the dialog first time and make a request .. the live data observer updating my ui .. but when close it and open it again ... the observer not updating my ui .. although it showing a toast
Dialog
class ChooseTerritoryDialog(
private var activity: AppCompatActivity,
private var listener: OnSelectTerritory,
private val accountId: Int
) : BaseDialog(activity), ChooseTerritoryAdapter.OnTerritoryItem {
lateinit var binding: SearchListLayoutBinding
lateinit var adapter: ChooseTerritoryAdapter
lateinit var viewModel: ChooseTerritoryViewModel
var list: ArrayList<ListEntity>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = viewDataBinding!!
viewModel = ViewModelProvider(activity)[ChooseTerritoryViewModel::class.java]
binding.search.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
if (charSequence.isNotEmpty()) {
} else {
}
}
override fun afterTextChanged(editable: Editable) {}
})
binding.close.setOnClickListener(View.OnClickListener { dismiss() })
viewModel.getTerritories(accountId)
setObservers()
}
Observers
fun setObservers() {
viewModel.state.observeOnce(activity , Observer {
binding.search.setText("test")
binding.progress.isVisible = it == Status.Loading
when (it) {
is Status.Loading -> {
}
is Status.Success<*> -> {
Toast.makeText(activity, "Success", Toast.LENGTH_SHORT).show()
val response = it.data as BaseResponse<ArrayList<TerritoryItem>>
adapter = ChooseTerritoryAdapter(response.data!!, this)
binding.recycler.adapter = adapter
}
is Status.Error -> {
Toast.makeText(activity, it.message!!, Toast.LENGTH_SHORT).show()
}
}
})
}
The problem is that you are calling functions that are updating UI inside of onCreate(). However this is Fragment. These methods should be called inside of onViewCreated(). That's why your Toast is showing, but the UI can't be updated.
Another potential problem is in these 2 lines:
viewModel.getTerritories(accountId)
setObservers()
Switch order. First subscribe and then fetch.
I'm interested to know if there is a way to get a callback when there are chromecast casting failures:
The user start to cast something from my app, background the app and start casting a different asset from a different application like YouTube/Spotify
When there is a power drop and the chromecast disconnected from the wifi.
Connectivity issues with chromecast and the router
I'm currently using RemoteMediaClient with setResultCallback but setResultCallback is never been called when there is one of those failures.
There is a session manager listener , you can use it
val mSessionManagerListener = object : SessionManagerListener<CastSession> {
override fun onSessionEnded(session: CastSession, error: Int) {
onApplicationDisconnected()
}
override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
onApplicationConnected(session)
}
override fun onSessionResumeFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
showToast("ResumeFailed $error")
}
override fun onSessionStarted(session: CastSession, sessionId: String) {
onApplicationConnected(session)
}
override fun onSessionStartFailed(session: CastSession, error: Int) {
onApplicationDisconnected()
showToast("Error $error")
}
override fun onSessionStarting(session: CastSession) {}
override fun onSessionEnding(session: CastSession) {}
override fun onSessionResuming(session: CastSession, sessionId: String) {}
override fun onSessionSuspended(session: CastSession, reason: Int) {}
private fun onApplicationConnected(castSession: CastSession) {
mCastSession = castSession
}
private fun onApplicationDisconnected() {
}
}
mCastContext?.sessionManager?.addSessionManagerListener(
mSessionManagerListener!!,
CastSession::class.java
)
I am trying to test myself in android development. For that I am trying to make a social media app with the help of firebase (using firebase authentication), but the problem is. After I login with every credentials correct, its is not showing the next activity screen which is meant to be opened. I don't know what mistake did I make. Here is the code for loginAcitivity screen:
class LoginActivity : AppCompatActivity() {
private val firebaseAuth = FirebaseAuth.getInstance()
private val firebaseAuthListener = FirebaseAuth.AuthStateListener {
val user = firebaseAuth.currentUser?.uid
user?.let {
startActivity(HomeActivity.newIntent(this))
finish()
}
}
#SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
setTextChangeListener(emailET, emailTIL)
setTextChangeListener(passwordET, passwordTIL)
loginProgressLayout.setOnTouchListener { v :View, event :MotionEvent -> true }
}
private fun setTextChangeListener(et: EditText, til: TextInputLayout) {
et.addTextChangedListener(object: TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
til.isErrorEnabled = false
}
})
}
fun onLogin(v: View){
var proceed = true
if(emailET.text.isNullOrEmpty()){
emailTIL.error = "Email is required"
emailTIL.isErrorEnabled = true
proceed = false
}
if(passwordET.text.isNullOrEmpty()){
passwordTIL.error ="Password is required"
passwordTIL.isErrorEnabled = true
proceed = false
}
if(proceed){
loginProgressLayout.visibility = View.VISIBLE
firebaseAuth.signInWithEmailAndPassword(emailET.text.toString(), passwordET.text.toString())
.addOnCompleteListener { task: Task<AuthResult> ->
if (!task.isSuccessful) {
loginProgressLayout.visibility = View.GONE
Toast.makeText(this#LoginActivity, "Login error: Either the username or password is wrong.", Toast.LENGTH_SHORT).show()
}
}.addOnFailureListener{e: Exception ->
e.printStackTrace()
loginProgressLayout.visibility = View.GONE
}
}
}
fun goToSignUp(v: View){
startActivity(SignUpActivity.newIntent(this))
finish()
}
override fun onStart() {
super.onStart()
firebaseAuth.addAuthStateListener { firebaseAuthListener }
}
override fun onStop() {
super.onStop()
firebaseAuth.removeAuthStateListener { firebaseAuthListener }
}
companion object{
fun newIntent(context: Context) = Intent(context, LoginActivity::class.java)
}
}
To test out that authentication is working or not I place a button in the activity to logout.
Help me please it's been week since I am stuck on it.
You were using lambda and in there you were no doing any task.
override fun onStart() {
super.onStart()
firebaseAuth.addAuthStateListener(firebaseAuthListener)
}
override fun onStop() {
super.onStop()
firebaseAuth.removeAuthStateListener(firebaseAuthListener)
}
I am trying to implement ExoPlayer's Notification Manager, it works pretty well but I do not want to show fast rewind and fast forward buttons. I checked documentation but can not find a way to hide these button. Is there any tricky way to hide them?
Here is my code
private fun initListener() {
val playerNotificationManager: PlayerNotificationManager
val notificationId = 1234
val mediaDescriptionAdapter = object : PlayerNotificationManager.MediaDescriptionAdapter {
override fun getCurrentSubText(player: Player?): String {
return "Sub text"
}
override fun getCurrentContentTitle(player: Player): String {
return "Title"
}
override fun createCurrentContentIntent(player: Player): PendingIntent? {
return null
}
override fun getCurrentContentText(player: Player): String {
return "ContentText"
}
override fun getCurrentLargeIcon(
player: Player,
callback: PlayerNotificationManager.BitmapCallback
): Bitmap? {
return null
}
}
playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
context,
"My_channel_id",
R.string.app_name,
notificationId,
mediaDescriptionAdapter,
object : PlayerNotificationManager.NotificationListener {
override fun onNotificationPosted(notificationId: Int, notification: Notification, ongoing: Boolean) {}
override fun onNotificationCancelled(notificationId: Int, dismissedByUser: Boolean) {}
})
playerNotificationManager.setUseNavigationActions(false)
playerNotificationManager.setUseNavigationActionsInCompactView(false)
playerNotificationManager.setVisibility(View.VISIBLE)
playerNotificationManager.setPlayer(mPlayer)
}
You can set rewindIncrementMs and fastForwardIncrementMs to 0 to hide the buttons.
The link to the JavaDoc you posted above explaines this: https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/ui/PlayerNotificationManager.html
playerNotificationManager.setRewindIncrementMs(0);
playerNotificationManager.setFastForwardIncrementMs(0);
You can do this in ExoPlayer 2.15.0 -
playerNotificationManager.setUseFastForwardAction(false)
playerNotificationManager.setUseFastForwardActionInCompactView(false)
playerNotificationManager.setUseRewindAction(false)
playerNotificationManager.setUseRewindActionInCompactView(false)
I'm using Paging Library from JetPack for infinite scrolling. Everything is working fine, but I have more API addresses(URLs).
And what I want to do is for my fragments to change the URL but I don't know what function should I create to fetch each URL for the respective fragment.
I've tried a function to fetch each URL based on which Fragment is opened with a SortType class
Function to fetch:
private fun fetchPhotos(page : Int): Call<List<Photo>> {
if (sortType != null) {
return dataSource.fetchPhotos(sortType = sortType, page = page)
} else if (query.isNotEmpty()) {
return dataSource.fetchPhotos(page = page, query = query)
}
throw RuntimeException("Unknown state to fetch movies")
}
Here is PhotoDataSource where is the Pagination and where pages are fetched and API URLs:
override fun loadInitial(params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Photo>) {
networkState.postValue(NetworkState.LOADING)
initialLoad.postValue(NetworkState.LOADING)
fetchPhotos.getPhotos(FIRST_PAGE_NUMBER, params.requestedLoadSize).enqueue(object : Callback<List<Photo>>{
override fun onFailure(call: Call<List<Photo>>, t: Throwable) {
// keep a Completable for future retry
setRetry(Action { loadInitial(params, callback) })
val error = NetworkState.error(t.message)
// publish the error
networkState.postValue(error)
initialLoad.postValue(error) }
override fun onResponse(call: Call<List<Photo>>, response: Response<List<Photo>>) {
if (response.body() != null) {
setRetry(null)
networkState.postValue(NetworkState.LOADED)
initialLoad.postValue(NetworkState.LOADED)
callback.onResult(response.body()!!, null, FIRST_PAGE_NUMBER + INCREMENT_PAGE_VALUE)
}
}
})
}
API Services:
#GET("photos")
fun getPhotos(#Query("page") page: Int, #Query("per_page") per_page: Int): Call<List<Photo>>
#GET("photos/curated")
fun getCuratedPhotos(#Query("page") page: Int, #Query("per_page") per_page: Int): Call<List<Photo>>
#GET("/collections/featured")
fun getFeaturedCollections(#Query("page") page: Int, #Query("per_page") per_page: Int): Call<List<Photo>>
#GET("search/photos")
fun searchPhotos(#Query("page") page: Int, #Query("query") query: String): Call<List<Photo>>
SortType class:
enum class SortType(val value: Int) {
MOST_POPULAR(0),
HIGHEST_RATED(1),
UPCOMING(2)
}
I get no errors and nothing happens. I just want a way to make this more productive and I want to avoid creating a DataSource class for each API URL.
Hope you understand, I really need your help I've been struggling with this error for a few months and no idea what should I do. For any better explanations just ask.