Android WebView播放音乐时调用系统MediaPlayer并在通知栏展示播放控制的实现问询
Android WebView播放音乐时调用系统MediaPlayer并在通知栏展示播放控制的实现问询
Hey there! 我看你现在遇到的问题是:用WebView加载音乐网站时,没办法像Chrome那样调用系统自带的MediaPlayer来播放音乐,还希望能在通知栏显示播放控制对吧?先别急,咱们一步步来搞定这个问题。
首先得说,你当前的代码只是做了最基础的WebView加载网页,没有配置任何和媒体播放相关的关键设置,也没处理系统媒体会话的关联,所以系统根本识别不到WebView里的媒体播放,自然不会唤起系统的MediaPlayer和通知栏控制。
接下来咱们直接上解决方案,分步骤来:
第一步:修改WebView的核心配置,开启媒体相关支持
咱们需要给WebSettings添加几个关键属性,同时设置WebChromeClient(它是WebView处理媒体播放、网页交互的核心类,没有它,系统抓不到媒体播放事件)。
第二步:关联系统媒体会话,让通知栏自动显示播放控制
从Android 7.0(API 24)开始,WebView支持直接关联系统的MediaSession,只要开启这个设置,系统检测到WebView里的媒体播放时,就会自动弹出通知栏的播放控制,和Chrome的效果一致。
第三步:处理Android 13+的通知权限
从Android 13开始,显示通知必须申请POST_NOTIFICATIONS权限,不然通知栏的播放控制根本出不来,这一步可不能忘!
下面是修改后的完整代码:
1. 先在AndroidManifest.xml里添加权限
<!-- Android 13+ 通知权限 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- 基础网络权限(加载网页必须) --> <uses-permission android:name="android.permission.INTERNET" />
2. 修改MainActivity的代码
package com.prymie; import android.Manifest; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.Toast; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; public class MainActivity extends AppCompatActivity { public WebView p_ww_main; @Override protected void onCreate(Bundle p_be_main) { super.onCreate(p_be_main); setContentView(R.layout.activity_main); // 先处理Android 13+的通知权限申请 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { checkNotificationPermission(); } else { // 低版本直接初始化WebView initWebView(); } } @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) private void checkNotificationPermission() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { // 注册权限申请回调 ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult( new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { Toast.makeText(this, "通知权限已开启,将显示播放控制", Toast.LENGTH_SHORT).show(); initWebView(); } else { Toast.makeText(this, "未开启通知权限,无法显示播放控制", Toast.LENGTH_SHORT).show(); initWebView(); } } ); // 发起权限申请 requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS); } else { // 已经有权限,直接初始化 initWebView(); } } private void initWebView() { p_ww_main = findViewById(R.id.p_ww_main); WebSettings webSettings = p_ww_main.getSettings(); // 基础设置:已开启JavaScript webSettings.setJavaScriptEnabled(true); // 启用DOM存储,多数音乐网站依赖这个 webSettings.setDomStorageEnabled(true); // 允许内容访问 webSettings.setAllowContentAccess(true); // 允许文件访问 webSettings.setAllowFileAccess(true); // 允许自动播放(如果网站需要,可选,默认是true需要用户手势触发播放) webSettings.setMediaPlaybackRequiresUserGesture(false); // 必须设置WebChromeClient,否则系统捕获不到媒体播放事件 p_ww_main.setWebChromeClient(new WebChromeClient()); // 开启WebView的媒体会话支持,关联系统MediaSession(API 24+) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { p_ww_main.setMediaSessionEnabled(true); } // 加载音乐网站 p_ww_main.loadUrl("https://music.com"); } }
补充说明
- 为什么要设置
WebChromeClient?因为它是WebView和系统之间处理媒体播放、网页弹窗、通知等交互的桥梁,没有它,WebView里的媒体播放事件根本传不到系统层,自然不会唤起系统MediaPlayer和通知栏控制。 - 关于
setMediaSessionEnabled(true):这个设置是让WebView把内部的媒体播放会话和系统的MediaSession绑定,这样系统就能识别到WebView里的媒体播放状态,自动生成带播放/暂停/上一曲/下一曲的通知栏控制,和Chrome的逻辑完全一致。 - 如果你的音乐网站用了非标准的HTML5音频播放(比如自定义的JS播放器),那上面的方法可能失效,这时候就需要你自己拦截网页的媒体播放请求,用Android原生的MediaPlayer来播放,同时手动创建MediaSession和通知栏控制——不过这种情况复杂度会高很多,得具体问题具体分析。
如果按照上面的步骤配置后还是有问题,你可以检查一下音乐网站是不是用了特殊的媒体加密或者自定义播放逻辑,或者测试一下不同版本的Android系统(毕竟不同版本的WebView对媒体会话的支持可能有差异)。
备注:内容来源于stack exchange,提问作者Matin Javid
相关产品推荐
相关产品推荐

