I am trying to play videos in VideoView in the recyclerView using realTime database. Here is my adapter code of the recyclerView. :-
class VideoAdapter(private var mContext: Context,private var mvideos: List<VID>) : RecyclerView.Adapter<VideoAdapter.ViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {val view = LayoutInflater.from(mContext).inflate(R.layout.videos_adapter, parent, false)return ViewHolder(view)}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val videoid = mvideos[position]
holder.vidId.text = videoid.getilp()
val videolink = Uri.parse(videoid.getVideoUrl())
val mediaController = MediaController(mContext)
mediaController.setAnchorView(holder.videoIv)
holder.videoIv.setMediaController(mediaController)
holder.videoIv.setVideoURI(videolink)
holder.videoIv.requestFocus()
holder.videoIv.start()
}
override fun getItemCount(): Int {
return mvideos.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var videoIv: VideoView = itemView.videos_ret
var vidId: TextView = itemView.videos_id_ret
}
}
After using this code. I am getting this error.
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? at android.view.ViewRootImpl.setView(ViewRootImpl.java:1444) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:469) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:114) at android.widget.MediaController.show(MediaController.java:384)
at android.widget.MediaController.show(MediaController.java:334)
at android.widget.VideoView$2.onPrepared(VideoView.java:521)
at android.media.MediaPlayer$EventHandler.handleMessage(MediaPlayer.java:4228) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:246) at android.app.ActivityThread.main(ActivityThread.java:8653) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
It plays the video for a few seconds in the background after crashing before closing the app. someone, please help me.
CodePudding user response:
The view added to the window must have a token, in your situation, it is the activity. but when your application is in the background, it may be destroyed by the system. you can add log info in the activity onDestory
method
in most scenes, when the activity lifecycle is in onPause
, the video play should pause. if you have to play it, you should change the way you use it.
it is PIP, you can also use some third library.
PiP leverages the multi-window APIs made available in Android 7.0 to provide the pinned video overlay window. To add PiP to your app, you need to register your activities that support PiP, switch your activity to PiP mode as needed, and make sure UI elements are hidden and video playback continues when the activity is in PiP mode. The PiP window appears in the topmost layer of the screen, in a corner chosen by the system.
CodePudding user response:
Instead of VideoView use Exoplayer:-
class VideoAdapter(
private var mContext: Context,
private var mvideos: List<VID>
) : RecyclerView.Adapter<VideoAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(mContext).inflate(R.layout.videos_adapter, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val videoid = mvideos[position]
holder.vidId.text = videoid.getilp()
val dataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory()
val videoLink = Uri.parse(videoid.getVideoUrl())
val mediaSource: MediaSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(videoLink))
holder.mPlayer = SimpleExoPlayer.Builder(mContext).build()
holder.playerView.player = holder.mPlayer
holder.mPlayer!!.playWhenReady = true
holder.mPlayer!!.setMediaSource(mediaSource)
holder.mPlayer!!.stop()
}
override fun getItemCount(): Int {
return mvideos.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var mPlayer: SimpleExoPlayer? = null
var playerView: PlayerView = itemView.videos_ret
var vidId: TextView = itemView.videos_id_ret
}
}