关于音乐播放器与系统功能联动功能梳理

主要实现功能:

一、通知栏播放显示和控制

二、系统下拉栏中播放模块显示同步

三、与其他播放器状态同步:本应用播放时暂停其他应用播放,进入其他应用播放时,暂停本应用的后台播放

通知栏播放的显示和控制:

通过Notification + RemoteViews + 广播实现,主要代码如下:
    /*** 初始化自定义通知栏 的按钮点击事件*/private void initRemoteViews() {remoteViews = new RemoteViews(this.getPackageName(), R.layout.notification);//通知栏控制器上一首按钮广播操作Intent intentPrev = new Intent(ACTION_PRE_SONG);PendingIntent prevPendingIntent = PendingIntent.getBroadcast(this, 5100, intentPrev, PendingIntent.FLAG_CANCEL_CURRENT);//为prev控件注册事件remoteViews.setOnClickPendingIntent(R.id.btn_notification_previous, prevPendingIntent);//通知栏控制器播放暂停按钮广播操作  //用于接收广播时过滤意图信息Intent intentPlay = new Intent(ACTION_PAUSE);PendingIntent playPendingIntent = PendingIntent.getBroadcast(this, 5101, intentPlay, PendingIntent.FLAG_CANCEL_CURRENT);//为play控件注册事件remoteViews.setOnClickPendingIntent(R.id.btn_notification_play, playPendingIntent);//通知栏控制器下一首按钮广播操作Intent intentNext = new Intent(ACTION_NEXT_SONG);PendingIntent nextPendingIntent = PendingIntent.getBroadcast(this, 5102, intentNext, PendingIntent.FLAG_CANCEL_CURRENT);//为next控件注册事件remoteViews.setOnClickPendingIntent(R.id.btn_notification_next, nextPendingIntent);//通知栏控制器关闭按钮广播操作Intent intentClose = new Intent(ACTION_PLAY_CLOSE);PendingIntent closePendingIntent = PendingIntent.getBroadcast(this, 5103, intentClose, 0);//为close控件注册事件remoteViews.setOnClickPendingIntent(R.id.btn_notification_close, closePendingIntent);}/*** 初始化通知*/@SuppressLint("NotificationTrampoline")private void initNotification() {String channelId = "play_control";String channelName = "播放控制";int importance = NotificationManager.IMPORTANCE_HIGH;createNotificationChannel(channelId, channelName, importance);//点击整个通知时发送广播Intent intent = new Intent(getApplicationContext(), NotificationClickReceiver.class);PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0,intent, FLAG_UPDATE_CURRENT);//初始化通知notification = new NotificationCompat.Builder(this, "play_control").setContentIntent(pendingIntent).setWhen(System.currentTimeMillis()).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))//   .setCustomContentView(remoteViews).setCustomBigContentView(remoteViews).setVisibility(NotificationCompat.VISIBILITY_PUBLIC)// .setStyle(new NotificationCompat.BigTextStyle())//  .setStyle(new NotificationCompat.InboxStyle()).setDefaults(NotificationCompat.DEFAULT_ALL).setAutoCancel(false).setOnlyAlertOnce(true).setOngoing(true).build();}/*** 创建通知渠道** @param channelId   渠道id* @param channelName 渠道名称* @param importance  渠道重要性*/@TargetApi(Build.VERSION_CODES.O)private void createNotificationChannel(String channelId, String channelName, int importance) {NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);channel.enableLights(false);channel.enableVibration(false);channel.setVibrationPattern(new long[]{0});channel.setSound(null, null);manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);manager.createNotificationChannel(channel);}

通知栏整体点击跳转到播放界面:注册全局监听广播

public class NotificationClickReceiver extends BroadcastReceiver {public static final String TAG = "NotificationClickReceiver";@Overridepublic void onReceive(Context context, Intent intent) {LogUtil.showLog(TAG,"通知栏点击");//获取栈顶的Activity// Activity currentActivity = ActivityManager.getCurrentActivity();intent = new Intent(Intent.ACTION_MAIN);intent.addCategory(Intent.CATEGORY_LAUNCHER);intent.setClass(context, MusicPlayerActivity.class);intent.putExtra("from","notify");// intent.putExtra("file",MyApplication.currentPlayMusic);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);context.startActivity(intent);}
}

系统下拉栏媒体播放信息和状态同步:

通过MediaSession + MediaMetadata + PlaybackState实现

public void initMediaSession(){mediaSession = new MediaSession(this, "music_player_session");mediaSession.setCallback(new MediaSession.Callback() {// 覆盖必要的回调方法,如onPlay, onPause等@Overridepublic void onPause() {super.onPause();mediaSession.setPlaybackState(stateBuilder.setState(PlaybackState.STATE_PAUSED,mPlayer.getCurrentPosition(), 0.0f).build());sendBroadcast(new Intent(ACTION_PAUSE));}@Overridepublic void onPlay() {super.onPlay();mediaSession.setPlaybackState(stateBuilder.setState(PlaybackState.STATE_PLAYING, mPlayer.getCurrentPosition(), 0.0f).build());sendBroadcast(new Intent(ACTION_PLAY_SONG));}@Overridepublic void onSkipToNext() {super.onSkipToNext();sendBroadcast(new Intent(ACTION_NEXT_SONG));}@Overridepublic void onSkipToPrevious() {super.onSkipToPrevious();sendBroadcast(new Intent(ACTION_PRE_SONG));}});mediaSession.setActive(true);metaDataBuilder = new MediaMetadata.Builder();//播放状态stateBuilder = new PlaybackState.Builder();stateBuilder.setActions(PlaybackState.ACTION_PLAY | PlaybackState.ACTION_PAUSE| PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS);}

状态和信息同步:

    /*** 更改通知的信息和UI*/private Intent intentPlay;private PendingIntent playPendingIntent;public void updateNotificationShow() {//通知栏控制器播放暂停按钮广播操作  //用于接收广播时过滤意图信息intentPlay = new Intent(mPlayer.isPlaying()?ACTION_PAUSE:ACTION_PLAY_SONG);playPendingIntent = PendingIntent.getBroadcast(this, 5101, intentPlay, PendingIntent.FLAG_CANCEL_CURRENT);//为play控件注册事件remoteViews.setOnClickPendingIntent(R.id.btn_notification_play, playPendingIntent);//播放状态判断if (mPlayer.isPlaying()) {remoteViews.setImageViewResource(R.id.btn_notification_play, R.mipmap.notify_pause);} else {remoteViews.setImageViewResource(R.id.btn_notification_play, R.mipmap.notify_play);}//封面专辑remoteViews.setImageViewResource(R.id.iv_album_cover,R.mipmap.ic_launcher);//歌曲名remoteViews.setTextViewText(R.id.tv_notification_song_name,defaultSongName.substring(0,defaultSongName.lastIndexOf(".")));//歌手名remoteViews.setTextViewText(R.id.tv_notification_singer,"");remoteViews.setTextViewText(R.id.tv_duration,StringUtil.formatDuration(mPlayer.getDuration()));remoteViews.setTextViewText(R.id.tv_current_time,StringUtil.formatDuration(mPlayer.getCurrentPosition()));if(mPlayer.getDuration() > 0)remoteViews.setProgressBar(R.id.seekbar,100,mPlayer.getCurrentPosition()*100/mPlayer.getDuration(),false);//发送通知manager.notify(NOTIFICATION_ID,notification);WindowUtils.isNotifyShow = true;//同步下拉栏播放控制区信息metaDataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE,defaultSongName.substring(0,defaultSongName.lastIndexOf(".")));mediaSession.setMetadata(metaDataBuilder.build());}

与其他应用播放器状态同步

通过AudioManager监听onAudioFocusChange音频焦点变化实现

 /** 监测其他应用播放音视频 */mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);mListener = new AudioManager.OnAudioFocusChangeListener() {@Overridepublic void onAudioFocusChange(int focusChange) {LogUtil.showLog(TAG,"==onAudioFocusChange=="+focusChange);abandonAudioFocus(); //禁用音频sendBroadcast(new Intent(ACTION_PAUSE));switch (focusChange) {case AudioManager.AUDIOFOCUS_GAIN:// TBD 继续播放break;case AudioManager.AUDIOFOCUS_LOSS:// TBD 停止播放break;case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:// TBD 暂停播放break;case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:// TBD 混音播放break;default:break;}}};//android 版本 5.0if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {mAttribute = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();}//android 版本 8.0if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT).setWillPauseWhenDucked(true).setAcceptsDelayedFocusGain(true).setOnAudioFocusChangeListener(mListener, mHandler).setAudioAttributes(mAttribute).build();}requestAudioFocus();//启动获取音频

效果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/850334.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字人实战第一天——最新数字人MuseTalk效果展示

最新数字人MuseTalk效果展示 MuseTalk 是由腾讯团队开发的先进技术,项目地址:GitHub - TMElyralab/MuseTalk: MuseTalk: Real-Time High Quality Lip Synchorization with Latent Space Inpainting,它是一个实时的音频驱动唇部同步模型。该模…

简单通用的系统安装、备份、还原方法,支持 ARM 系统【Ventory+FirePE+DiskGenius】

文章目录 0. 简介1. 制作 Ventory 启动盘1.1. 下载 Ventory1.2. 制作 Ventory 启动盘 2. 添加 FirePE 等系统镜像到启动盘2.1. 下载 FirePE2.2. 导出 .iso 系统镜像文件2.3. .iso 系统镜像文件添加至启动盘 3. 启动 FirePE 等系统镜像3.1. 在 bios 中选择启动盘启动3.2. 启动系…

访问网站时IP被阻止?原因及解决方法

在互联网上,用户可能会面临一个令人困扰的问题——当尝试访问某个特定的网站时,却发现自己的IP地址被该网站屏蔽。 IP地址被网站屏蔽是一个相对常见的现象,而导致这种情况的原因多种多样,包括恶意行为、违规访问等。本文将解释IP地…

大学搜题软件网课?推荐五个搜题软件和学习工具 #其他#经验分享#知识分享

大学生活中,选择适合自己的学习工具能够提高学习效率,让学习更加轻松愉快。 1.彩虹搜题 这个是公众号 提供了各大教材以及网课平台的练习题答案,强大的平台支持,无论是智慧树还是MOOC,只有老师们用不到,…

理解JVM内存模型与Java内存模型(JMM)

理解JVM内存模型与Java内存模型(JMM) 在Java程序的运行过程中,内存管理和线程的同步是两个重要的概念。本文将深入探讨JVM内存模型(Java Virtual Machine Memory Model)和JMM(Java Memory Model&#xff0…

实现开源可商用的 ChatPDF RAG:密集向量检索(R)+上下文学习(AG)

实现 ChatPDF & RAG:密集向量检索(R)上下文学习(AG) RAG 是啥?实现 ChatPDF怎么优化 RAG? RAG 是啥? RAG 是检索增强生成的缩写,是一种结合了信息检索技术与语言生成…

型号FM152A,FM148R和利时

型号FM152A,FM148R和利时。控制系统的仿真,综合考虑多方面的因素,本文将用MCGS组态软件设计一个仿真实验监控平台来对其进行实时控制.,完成仿真实验监控平台的设计,型号FM152A,FM148R和利时。最终达到对水箱液位实时监控,实验数据采集,报表的输出和数据的同步显示MC…

Live800:深度解析,客户服务如何塑造品牌形象

在当今竞争激烈的市场环境中,品牌形象对于企业的成功至关重要。而客户服务作为品牌与消费者之间最直接的互动方式,不仅影响着消费者的购买决策,更在塑造品牌形象方面发挥着不可替代的作用。本文将深度解析客户服务如何塑造品牌形象&#xff0…

【Unity3D小功能】Unity3D中UGUI-Text实现打字机效果

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 需求要实现Text的打字机效果,一看居然…

机器学习作业6——svm支持向量机

目录 一、理论 概念: 线性可分: 支持向量: 间隔: 目标: 软间隔: 梯度下降法: 别的方法: 拉格朗日函数: SMO算法: 核函数: 二、代码 …

python代码中参数的默认值

python中的函数,可以给形参指定默认值。 带有默认值的参数,可以在调用的时候不传参。 如上图所示,在给函数设定形参的时候可以给函数形参设定默认值,当然默认参数的形参应该在非默认形参的后面。 如果在调用函数的时候&#xff…

Linux云计算架构师涨薪班就业服务有哪些?

学员一站式就业服务:一次学习,薪资翻倍 简历制作与指导 学员在培训期间,人才顾问会提供简历制作和指导服务,帮助学员制作出一份专业、有吸引力的简历。简历是求职者给招聘单位的第一印象,因此非常重要 模拟面试与技巧指导 为了让…

WebGPU 引领前端未来,互动渲染如何驱动小红书业务增长?

在大前端时代,浏览器能力得到显著的增强,为前端开发带来了更多的可能性和挑战。作为一套全新的 Web API 标准,WebGPU 旨在提供高性能的 3D 图形和数据并行计算能力,其在游戏、虚拟现实、机器学习等多个行业和应用场景中展现出潜力…

嵌入式Linux系统编程 — 3.2 stat、fstat 和 lstat 函数查看文件属性

目录 1 文件有哪些属性 2 stat函数 2.1 stat函数简介 2.2 struct stat 结构体 2.3 struct timespec 结构体 2.4 示例程序 3 fstat 和 lstat 函数 3.1 fstat 函数 3.2 lstat 函数 1 文件有哪些属性 Linux文件属性是对文件和目录的元数据描述,包括文件类型…

30-unittest生成测试报告(HTMLTestRunner插件)

批量执行完测试用例后,为了更好的展示测试报告,最好是生成HTML格式的。本文使用第三方HTMLTestRunner插件生成测试报告。 一、导入HTMLTestRunner模块 这个模块下载不能通过pip安装,只能下载后手动导入,下载地址是:ht…

应用广义线性模型一|线性模型

文章目录 一、统计学及思维模式二、未知现象的数学描述三、线性模型(一)线性模型的定义(二)线性模型的参数估计(三)线性模型的应用(四)离散解释变量的设计向量构建方法 四、线性模型…

SpringAOP 常见应用场景

文章目录 SpringAOP1 概念2 常见应用场景3 AOP的几种通知类型分别有什么常见的应用场景4 AOP实现 性能监控4.1 首先,定义一个切面类,用于实现性能监控逻辑:4.2 定义自定义注解4.3 注解修饰监控的方法 5 AOP实现 API调用统计5.1 定义切面类&am…

深度图的方法实现加雾,Synscapes数据集以及D455相机拍摄为例

前言 在次之前,我们已经做了图像加雾的一些研究,这里我们将从深度图的方法实现加雾展开细讲 图像加雾算法的研究与应用_图像加雾 算法-CSDN博客 接下来将要介绍如何使用深度图像生成雾效图像的方法。利用Synscapes数据集,通过读取EXR格式的…

【实盘】第二十期:2024-06月~第一周

一、每周净值 01 CTA投资组合 CTA多品种全覆盖全天候策略2024年2月至2024年5月底实盘总收益12.753%,当前浮动净值为1.1407,当前平仓净值为1.12753。 月度最大本金回撤0.3%(资金曲线为平仓盈亏,总体回撤应加入浮动持仓的盈亏总体计算,实际当前净值见棕色…

各种空气能热泵安装图

空气能热泵安装图 循环式空气能热泵安装图 直热循环式空气能热泵安装图 泳池空气能热泵安装图 循环式水源热泵热安装系统原理图 直热循环式水源热泵安装系统图 空气水源热泵安装图