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

2024-06-08 22:20

本文主要是介绍关于音乐播放器与系统功能联动功能梳理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

主要实现功能:

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

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

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

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

通过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.chinasem.cn/article/1043469

相关文章

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

Golang如何用gorm实现分页的功能

《Golang如何用gorm实现分页的功能》:本文主要介绍Golang如何用gorm实现分页的功能方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景go库下载初始化数据【1】建表【2】插入数据【3】查看数据4、代码示例【1】gorm结构体定义【2】分页结构体

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定