android 如何去控制第三方音乐播放app之控制QQ音乐
最近在做一个需求,要在桌面去控制qq音乐的播放(即,可以播放暂停,上一曲,下一曲显示歌名和歌手名)。接下来一一说下完成这个需求的心路历程。
1.在网上查腾讯有没有针对qq音乐提供SDK接口,结果发现,没有,如果需要控制,得和qq音乐合作,实现qplay 协议。
2.一位前辈和我说,让我试试Android 的MediaSession 是否可行,我也试了下,还是行不通。一般的话只要音乐播放器实现了谷歌提供的MediaSession 框架,然后就可以被第三方应用控制。但是人家qq音乐没实现这个。哈哈哈
3.这下没辙了,另外网上看到了一篇文章,这里也分享下,这里说的就是百度的一个app可以控制很多的第三方音乐播发器,但是这些第三方app基本都是车载的。例如控制qq音乐,需要先在qq音乐里面打开车载功能。这一看,这就是百度和腾讯有合作的莫。具体可以参考这篇文章 我通过了这篇文章中的方法获取我手机中所有实现MediaSession的应用,最后获取到了今日头条,英语流利说等,没有QQ音乐。
4.这下没办法了。然后插上耳机,放了一首音乐冷静冷静。突然,发现耳机线上的两个按钮,咦,这不就能控制qq音乐吗,于是就尝试了下在我的app里面点击模拟发MediaButton 按键,果然,可以正常的控制播放暂停上一首,下一首qq音乐,当然此时系统中必须只有一个音乐播放器。这里就先这样。关于如何模拟发送MediaButton 按键,可以看我这篇文章android 中用代码模拟发送按键
一般MediaButton 有如下几个按键:而且一般的音乐播放器里面都会实现对MediaButton的接收,具体原理是接收广播,有兴趣的可以自行研究。
KeyEvent.KEYCODE_MEDIA_NEXTKeyEvent.KEYCODE_MEDIA_PREVIOUSKeyEvent.KEYCODE_MEDIA_PLAY_PAUSEKeyEvent.KEYCODE_MEDIA_PAUSEKeyEvent.KEYCODE_MEDIA_PLAY
可以控制了,但是音乐名和歌手名还拿不到。不过可以从音乐的通知中获取音乐名和歌手名,一般主流的音乐播放器,播放音乐时,都会发一个通知,即Notification,如下图,这个通知中就带有音乐的播放信息。音乐我这边有系统的源码,故想要在系统中去截取notification中的音乐的信息。但是后来发现,完全不用。谷歌提供了一个notificationListener,来专门监听通知。下面来说下notification 的具体用法
notificationListener 的具体用法
1. 创建一个服务并且继承 NotificationListenerService(这个核心的代码我下面再具体列出来)
2.在AndroidManifest中添加服务
<serviceandroid:name=".service.NotificationListener"android:label="@string/app_name"android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"><intent-filter><action android:name="android.service.notification.NotificationListenerService" /></intent-filter></service>
3.在初次使用时需要申请通知使用的权限
if (!isNotificationServiceEnabled()) { 初次使用时 判断是否获取了通知使用权enableNotificationListenerAlertDialog = buildNotificationServiceAlertDialog();enableNotificationListenerAlertDialog.show();}private boolean isNotificationServiceEnabled() {String pkgName = mActivityView.getContext().getPackageName();final String flat = Settings.Secure.getString(mActivityView.getContext().getContentResolver(),ENABLED_NOTIFICATION_LISTENERS);if (!TextUtils.isEmpty(flat)) {final String[] names = flat.split(":");for (int i = 0; i < names.length; i++) {final ComponentName cn = ComponentName.unflattenFromString(names[i]);if (cn != null) {if (TextUtils.equals(pkgName, cn.getPackageName())) {return true;}}}}return false;}private AlertDialog buildNotificationServiceAlertDialog() {AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mActivityView.getContext());alertDialogBuilder.setTitle(R.string.notification_listener_service);alertDialogBuilder.setMessage(R.string.notification_listener_service_explanation);alertDialogBuilder.setPositiveButton(R.string.yes,new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {mActivityView.getContext().startActivity(new Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS)); // 如果没有获取,则跳转到setting 去获取}});alertDialogBuilder.setNegativeButton(R.string.no,new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {// If you choose to not enable the notification listener// the app. will not work as expected}});return (alertDialogBuilder.create());}
申请完权限,接下来就可以来监听接收通知了,
public class MyNotificationListenerService extends NotificationListenerService {@Override
public void onListenerConnected() {//当连接成功时调用,一般在开启监听后会回调一次该方法
}@Override
public void onNotificationPosted(StatusBarNotification sbn) {//当收到一条消息时回调,sbn里面带有这条消息的具体信息
}@Override
public void onNotificationRemoved(StatusBarNotification sbn) {//当移除一条消息的时候回调,sbn是被移除的消息
}
所以一般就是在 onNotificationPosted 方法里面去监听拿到消息的具体信息,如下,一般有如下信息。但是我基本都打印了返回值为String 类型的,但是基本都是空。最后我发现,qq音乐发送上面图中的通知,其实是发了一个自定义的RemoteViews(关于RemoteViews 这里不再多说)
Bundle extras = sbn.getNotification().extras;
String title = extras.getString(Notification.EXTRA_TITLE);
String content = extras.getString(Notification.EXTRA_TEXT);
String packageName = sbn.getPackageName();
所以,我通过 sbn.getNotification().bigContentView 拿到了上图中的view,我有尝试通过windowManager 去将此view 显示出来,发现是可以正常显示的。那么接下来的问题就是解析这个view了。
一般的话android中去分析一个view的结构,可以使用AndroidStudio 中的 Layout Inspector工具。然后通过此工具我发现我需要的歌手名在此view的第二个子view 中的第一个和第二个子view。于是:
if (sbn.getNotification().bigContentView != null) {ViewGroup view = (ViewGroup) sbn.getNotification().bigContentView.apply(this, null);TextView txMusciName = (TextView) ((ViewGroup) view.getChildAt(1)).getChildAt(0);TextView txMusicSinger = (TextView) ((ViewGroup) view.getChildAt(1)).getChildAt(1);String qqMusicName = (String) txMusciName.getText();String qqMuiscSinger = (String) txMusicSinger.getText();// 此处因为这个服务比较特殊,拿到数据之后想要更新UI,则可以通过发广播的方式。Intent intent = new Intent(ControlPresent.MUSIC_ACTION_CHANGE_BROADCAST);intent.putExtra("qqMusicName", qqMusicName);intent.putExtra("qqMuiscSinger", qqMuiscSinger);sendBroadcast(intent);
以上,则可以正常的控制qq音乐了。
android 如何去控制第三方音乐播放app之控制QQ音乐相关推荐
- 【VUE音乐播放器】获取QQ音乐播放源地址
前言:在学习慕课网课程制作企业级音乐app中,发现之前的qq音乐播放地址均不可用了.于是折腾了一下,重新抓包获取地址. 1.获取分类歌单里面的歌曲列表 在之前的代码里,如下红色圆中的歌单-歌曲列表显示 ...
- Android桌面小部件AppWidget:音乐播放器桌面控制部件Widget(3)
Android桌面小部件AppWidget:音乐播放器桌面控制部件Widget(3) Android桌面小部件AppWidget比较常用的场景就是音乐播放器,音乐播放器虽然通常在后台播放,但需要 ...
- 基于百度音乐Api的Android高仿音乐播放App可在线试听下载歌词浏览
基于百度音乐Api的Android高仿音乐播放App可在线试听下载歌词浏览 首先这也是学习过程中开发的一个练手项目,基于百度音乐Api,api在网上搜的,如果想看他的实现,可以下载我的项目来参考.风格 ...
- SwiftUI 音乐和网络大全之网络音乐播放App支持iTunes搜索与播放(教程含源码)
实战需求 SwiftUI 音乐和网络大全之网络音乐播放App支持iTunes搜索与播放(教程含源码) 本文价值与收获 看完本文后,您将能够作出下面的界面 实战代码 import SwiftUIstru ...
- android 音乐播放器ui界面设计音乐播放器毕业设计。Android studio编译,项目有源码和apk
使用Android Studio开发一个简易的音乐播放器 界面图: 视频展示: android 音乐播放器ui界面设计音乐播放器毕业设计.Android studio编译 项目下载: android音 ...
- html音乐播放器换歌,web-audio-api可视化音乐播放器,实现暂停切换歌曲功能,粉色系专场~...
可视化的音乐播放器,可戳我观看效果 了解Web-Audio-Api 基础知识 标签是HTML5的新标签,通过添加src属性实现音乐播放. AudioContext是音频播放环境,原理与canvas的绘 ...
- 开源音乐播放器_使用开源音乐播放器设计生活中的配乐
开源音乐播放器 我们围绕着自己的个人配乐. 我们的音乐让我们想起了人生中最重要的时刻,并帮助我们塑造了自己的感受和看法. 让音乐播放器支持自由选择音乐的播放方式,同时又不影响播放质量非常重要,而且我一 ...
- 单片机音乐播放器课程设计C语言,单片机音乐播放器课程设计中音乐代码怎么弄...
单片机音乐播放器课程设计中音乐代码怎么弄 答案:2 信息版本:手机版 解决时间 2019-10-06 13:16 已解决 2019-10-06 02:07 单片机音乐播放器课程设计中音乐代码怎么弄 ...
- 有自定义皮肤的计算机,QQ音乐怎么自定义皮肤丨QQ音乐自定义皮肤图解
在使用QQ音乐的时候,突然觉得自己的播放器主页面不是那么精彩怎么办,这时候你可以通过皮肤的更换来解决,那么QQ音乐怎么自定义皮肤,为此电脑系统城为你带来一个详细的QQ音乐自定义皮肤方法介绍,让你可以轻 ...
最新文章
- Networkx-cycle
- 2022 AAAI Fellow放榜!SAIL首席科学家颜水成、港科大教授冯雁等10人入选
- Linux如何自动获取IP地址
- pymysql.err.OperationalError: 1136, Column count doesn t match value count at row 1
- 天然气故障代码大全_美的、格力中央空调常见故障代码大全
- java udp发16进制数据_如何通过接口强制发送UDP数据包?
- CImage类的使用
- mooc作业怎么上传附件_产创云操作指南(五):作业系统的使用(学生端)
- 简单的超市会员管理系统
- Java学习——File类
- b560主板怎么样 b560主板支持的cpu
- 虚函数、纯虚函数、虚基类、抽象类、虚函数继承、虚继承
- 青青子佩(朋友写给我的)
- HBuilderX 下载安装教程
- 怎样批量查询顺心捷达单号信息并分析是否延误
- 解决ReliefJet需要激活而不能再使Outlook点X时最小化的问题
- 从键盘接收一百分制成绩python_python第一模块练习
- oracle数据库数据合并,Oracle合并数据
- DOA算法2:ESPRIT算法
- 鼎捷软件即将亮相工博会 与制造业共赢智造未来