Fragment中配置VideoView播放失败问题求助
解决VideoView无法播放网络视频的问题
问题症状
在Fragment的onViewCreated()中配置了VideoView,已添加网络权限,但播放时提示“无法播放此视频”。
核心原因及解决方案
1. Android 9+明文网络限制
从Android 9(API级别28)开始,系统默认禁止应用使用明文HTTP流量,你的视频链接为HTTP协议,需在AndroidManifest.xml的<application>标签中添加配置:
<application ... android:usesCleartextTraffic="true">
2. 为VideoView添加错误监听排查问题
添加错误监听可获取具体播放错误码,精准定位问题:
// 在视频配置代码中插入 videoview.setOnErrorListener { _, errorCode, extraCode -> Log.e("VideoPlayError", "错误码: $errorCode, 附加码: $extraCode") true }
3. 正确关联MediaController
需将MediaController的锚点绑定到VideoView,确保控制器正常工作:
val mediaController = MediaController(context) mediaController.setAnchorView(videoview) // 新增该行 videoview.setMediaController(mediaController)
4. 处理Fragment生命周期
Fragment切换时需管理VideoView的播放状态,避免异常:
override fun onPause() { super.onPause() videoview.pause() } override fun onResume() { super.onResume() if (!videoview.isPlaying) { videoview.start() } } override fun onDestroyView() { super.onDestroyView() videoview.stopPlayback() // 释放资源 }
修改后的完整Fragment代码
package com.service.bookitapp import android.net.Uri import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.MediaController import android.widget.Toast import androidx.fragment.app.Fragment import androidx.lifecycle.LifecycleCoroutineScope import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.coroutines.delay private const val ARG_PARAM1 = "param1" private const val ARG_PARAM2 = "param2" class HomeFragment : Fragment() { private var param1: String? = null private var param2: String? = null private lateinit var viewpager : ViewPager2 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_home, container, false) return view } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val arrCategory = ArrayList<CategoryModel>() val recyclerView = view.findViewById<RecyclerView>(R.id.recyclerCategory) arrCategory.add(CategoryModel(R.drawable.electrician,"Electrician")) arrCategory.add(CategoryModel(R.drawable.plumber,"Plumber")) arrCategory.add(CategoryModel(R.drawable.acservice,"AC Service")) arrCategory.add(CategoryModel(R.drawable.carpentry,"Carpentry")) arrCategory.add(CategoryModel(R.drawable.drop,"Pick up & Drop")) arrCategory.add(CategoryModel(R.drawable.painting,"Paint Service")) arrCategory.add(CategoryModel(R.drawable.waterfilter,"Water Filter")) arrCategory.add(CategoryModel(R.drawable.packer,"Pack and Move")) recyclerView.layoutManager = GridLayoutManager(context,4) val recyclerAdapter = context?.let { RecycleCategoryAdapter(it,arrCategory) } recyclerView.adapter = recyclerAdapter viewpager = view.findViewById(R.id.imageSlider) val imageList = listOf(R.drawable.slider1,R.drawable.slider2,R.drawable.slider3) val adapter = context?.let { ViewerPagerAdapter(it,imageList) } viewpager.adapter = adapter viewpager.autoScroll(lifecycleScope,3000) // 视频配置修改 val mediaController = MediaController(context) mediaController.setAnchorView(videoview) val path : Uri = Uri.parse("http://videocdn.bodybuilding.com/video/mp4/62000/62792m.mp4") videoview.setMediaController(mediaController) videoview.setVideoURI(path) // 添加错误监听 videoview.setOnErrorListener { _, what, extra -> Log.e("VideoError", "错误码: $what, 附加信息: $extra") Toast.makeText(context, "播放失败,错误码: $what", Toast.LENGTH_SHORT).show() true } videoview.requestFocus() videoview.start() } override fun onPause() { super.onPause() videoview.pause() } override fun onResume() { super.onResume() if (!videoview.isPlaying) { videoview.start() } } override fun onDestroyView() { super.onDestroyView() videoview.stopPlayback() } } fun ViewPager2.autoScroll(lifecycleScope: LifecycleCoroutineScope, interval: Long){ lifecycleScope.launchWhenResumed{ scrollIndefinitely(interval) } } private suspend fun ViewPager2.scrollIndefinitely(interval: Long){ delay(interval) val numberOfItems = adapter?.itemCount?:0 val lastIndex = if(numberOfItems>0) numberOfItems - 1 else 0 val nextItem = if(currentItem==lastIndex) 0 else currentItem + 1 setCurrentItem(nextItem,true) scrollIndefinitely(interval) }
补充检查项
- 确认已添加网络权限:
<uses-permission android:name="android.permission.INTERNET" /> - 测试视频链接是否可正常访问:在浏览器中打开链接,确认视频能正常播放
- 检查视频格式是否被设备支持:VideoView支持MP4、3GP等常见格式,若格式不兼容需转码
内容的提问来源于stack exchange,提问作者Parish Jain
相关产品推荐
相关产品推荐

