问题描述:

手机连接蓝牙耳机(SAMSUNG耳机),无法用耳机切换上一首(只能切换下一首)

重现问题:

这个问题因为重现概率是100%,所以我借了一只蓝牙耳机,从设置的蓝牙进入,点击连接蓝牙耳机,切换下一首,手机能正常插入下一首。点击上一首,问题来了,确实是不能播放上一首,具体的表现是重新播放此首音乐。

初步分析:

根据问题描述,初步分析:

  1. 可能是蓝牙耳机切换下一首按键命令有问题,可能按下切换下一首按键,发出的是重播的命令。
  2. 也有可能是按键命令本身正确,但是处理切换下一首按键的代码逻辑本身的问题

问题解决:

首先,确认蓝牙耳机按键是否正常。

我用自己的小米手机测试了此蓝牙耳机,发现在小米手机上蓝牙耳机的切换上一首和切换下一首功能是正常的,那么基本上排除了第一个蓝牙耳机切换下一首按键命令问题。

下面就只有第二个原因,

我首先查看了log,但是没有发现有效的log信息。
再在网上查了一资料,找到了一个感觉有用的东西:
Android 接收蓝牙耳机按键操作
http://blog.csdn.net/lihongyu65085/article/details/39853669

我选择关键字蓝牙耳机下一首按键来搜索:

KeyEvent.KEYCODE_MEDIA_NEXT

查找到代码:

……/app/Music/src/com/android/music/MediaButtonIntentReceiver.java:91:                case KeyEvent.KEYCODE_MEDIA_NEXT:

好家伙,确实有线索。我们打开此文件:


public void onReceive(Context context, Intent intent) {String intentAction = intent.getAction();if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intentAction)) {Intent i = new Intent(context, MediaPlaybackService.class);i.setAction(MediaPlaybackService.SERVICECMD);i.putExtra(MediaPlaybackService.CMDNAME, MediaPlaybackService.CMDPAUSE);context.startService(i);} else if (Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);if (event == null) {return;}int keycode = event.getKeyCode();int action = event.getAction();long eventtime = event.getEventTime();// single quick press: pause/resume. // double press: next track// long press: start auto-shuffle mode.String command = null;switch (keycode) {case KeyEvent.KEYCODE_MEDIA_STOP:command = MediaPlaybackService.CMDSTOP;break;case KeyEvent.KEYCODE_HEADSETHOOK:case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:command = MediaPlaybackService.CMDTOGGLEPAUSE;break;case KeyEvent.KEYCODE_MEDIA_NEXT:command = MediaPlaybackService.CMDNEXT;break;case KeyEvent.KEYCODE_MEDIA_PREVIOUS:command = MediaPlaybackService.CMDPREVIOUS;break;case KeyEvent.KEYCODE_MEDIA_PAUSE:command = MediaPlaybackService.CMDPAUSE;break;case KeyEvent.KEYCODE_MEDIA_PLAY:command = MediaPlaybackService.CMDPLAY;break;}

此代码,我们可以知道,MediaButtonIntentReceiver主要接受广播AudioManager.ACTION_AUDIO_BECOMING_NOISY和Intent.ACTION_MEDIA_BUTTON。而我们的蓝牙按键就是发送广播Intent.ACTION_MEDIA_BUTTON。并且,我们可以看到我们的按键事件:
KeyEvent.KEYCODE_MEDIA_STOP —停止
KeyEvent.KEYCODE_MEDIA_PAUSE —暂停
KeyEvent.KEYCODE_MEDIA_NEXT —下一首
MediaPlaybackService.CMDPREVIOUS —上一首
KeyEvent.KEYCODE_MEDIA_PLAY —播放

再往下看:

// only consider the first event in a sequence, not the repeat events,
// so that we don't trigger in cases where the first event went to
// a different app (e.g. when the user ends a phone call by
// long pressing the headset button)
// The service may or may not be running, but we need to send it
// a command.
Intent i = new Intent(context, MediaPlaybackService.class);
i.setAction(MediaPlaybackService.SERVICECMD);
if (keycode == KeyEvent.KEYCODE_HEADSETHOOK &&eventtime - mLastClickTime < 300) {i.putExtra(MediaPlaybackService.CMDNAME,      MediaPlaybackService.CMDNEXT);context.startService(i);mLastClickTime = 0;
} else {i.putExtra(MediaPlaybackService.CMDNAME, command);context.startService(i);mLastClickTime = eventtime;
}

从代码,我们可以看出,启动一个服务:MediaPlaybackService,并将按键命令发送过去。

我们再打开MediaPlaybackService:


public int onStartCommand(Intent intent, int flags, int startId) {………..String action = intent.getAction();String cmd = intent.getStringExtra("command");if (CMDNEXT.equals(cmd) || NEXT_ACTION.equals(action)) {gotoNext(true);} else if (CMDPREVIOUS.equals(cmd) || PREVIOUS_ACTION.equals(action)) {if (position() < 2000) {prev();} else {seek(0);play();}

从代码,我们可以看出:当按键命令是上一首时,

                seek(0);play();

这段代码,非常明显,就是导致不能播放上一首的原因所在。

问题找到了,解决就比较简单了:

//JABALCOA-139 prev music by bluetooth headset 20151208 start//seek(0);//play();prev();
//JABALCOA-139 prev music by bluetooth headset 20151208 end

总结:

我们再来看MediaButtonIntentReceiver广播监听器:
其主要监听如下二个广播:

    <receiver android:name="com.android.music.MediaButtonIntentReceiver"><intent-filter><action android:name="android.intent.action.MEDIA_BUTTON" /><action android:name="android.media.AUDIO_BECOMING_NOISY" /></intent-filter></receiver>

监听按键事件有:

KeyEvent.KEYCODE_MEDIA_STOP:
KeyEvent.KEYCODE_HEADSETHOOK:
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
KeyEvent.KEYCODE_MEDIA_NEXT:
KeyEvent.KEYCODE_MEDIA_PREVIOUS:
KeyEvent.KEYCODE_MEDIA_PAUSE:
KeyEvent.KEYCODE_MEDIA_PLAY:

当监听到按键事件后,再启动服务:MediaPlaybackService

    <service android:name="com.android.music.MediaPlaybackService"android:exported="false" />

在onStartCommand方法中判断按键事件,再进行相应的操作。

那些我们解过的bug之蓝牙耳机不能播放上一首歌相关推荐

  1. 一分钟详解initUndistortRectifyMap函数bug修复方法

    本文首发于微信公众号「3D视觉工坊」--一分钟详解initUndistortRectifyMap函数bug修复方法 在上一篇文章OpenCV中initUndistortRectifyMap函数存在bu ...

  2. 解决不了bug的时候看一下:

    解决不了bug的时候看一下: 1.机器是不会出错的,出错的一定是人.只是你还没有意识到哪里出了错. 2.产生bug 的原因想错了,你以为是系统的bug ,那么你肯定就不想着去解决,你也就解决不了. 这 ...

  3. 笔记本电脑连接蓝牙耳机自动断开,或者显示已配对但过几秒自动断开,蓝牙耳机连接不上笔记本电脑

    在使用笔记本时经常连接蓝牙耳机的时候显示了已配对,但耳机没有声音,然后过几秒就自动断开连接了.这时重启电脑才能重新连接语音和音乐,但是每次重启难受的一批. 重启也就是启动蓝牙模块,我们可以做如下步骤实 ...

  4. 为什么纽曼蓝牙耳机连接不上手机

    为什么我蓝牙耳机连接不上手机,长按的时候都是蓝灯亮一下,就不亮了,红灯一直闪烁 您好!耳机确保有电的情况下,在耳机关机的状态下长按开关键,一直按着不要松手的哦,直到指示灯显示红蓝灯交替闪烁的情况下,才 ...

  5. vue调用手机相机相册_详解Vue.js调用手机相机和相册以及上传

    详解Vue.js调用手机相机和相册以及上传 发布于 2020-7-7| 复制链接 摘记: 组件 ```xhtml .. 组件 ```xhtml --> 选中{{imgList.length}}张 ...

  6. 西门子smart200能用C语言吗,【项目详解】200SMART+V20在收卷机械上的应用

    原标题:[项目详解]200SMART+V20在收卷机械上的应用 JZGKCHINA 一.项目介绍 1.行业背景: 目前国内塑料机械企业加大了对新兴市场的开拓,国际知名度进一步扩大,市场竞争力也进一步提 ...

  7. 内存详解-理解 JVM 如何使用 Windows 和 Linux 上的本机内存

    内存详解 理解 JVM 如何使用 Windows 和 Linux 上的本机内存 Java™ 堆耗尽并不是造成 java.lang.OutOfMemoryError 的惟一原因.如果本机内存 耗尽,则会 ...

  8. 入耳式蓝牙耳机哪个牌子好?听歌音质好的蓝牙耳机

    选择蓝牙耳机不仅价位跨度大,便宜的有九块九包邮,而贵的动辄四位数.耳机的品牌也是众多,而且质量层次不齐,要是想从中挑选出合心意的并非易事.下面要给大家带来的就是数码达人鼎力推荐的这几款听歌音质好的蓝牙 ...

  9. 蓝牙耳机无法打开计算机,蓝牙耳机连不上?Win10系统电脑无法连接蓝牙耳机的完美解决方法...

    耳机如果想要摆脱线的困扰,那么无疑会选择蓝牙耳机,而在Windows10系统中可能会遇到断开蓝牙连接后再次连接时有时连接不上的问题,删除设备之后再连也不一定可以在连接上.那么遇到这个问题我们该如何解决 ...

最新文章

  1. java initcause_initCause()是什么意思
  2. Android之Fragment使用简介
  3. 新华社北京4月15日电 题:奋斗应提倡,996当退场
  4. Android•Lottie动画库填坑记
  5. IOS 委托和协议区别和联系 (-)
  6. AtCoder - 4172 Modulo Summation 贪心
  7. -bash: wget: 未找到命令_18个堪称神器的命令行工具,高效运维必备
  8. c1和c2语言水平,为什么驾校不建议考C2,驾驶证C1和C2的区别
  9. 杭州intel服务器维护,服务器应该怎么去维护?
  10. 【Java程序设计】类与对象的基本概念(下)
  11. Codeforce842D Vitya and Strange Lesson
  12. go build不从本地gopath获取_Go语言实战打包和工具链
  13. redux-chunk中间件的安装和使用-(二)
  14. java图书馆抢座系统_JSP+SSM+Mysql实现的图书馆预约占座管理系统
  15. 在Windows下配置svn服务端钩子程序
  16. php扩展 zval_copy_ctor,Zend API:pval/zval 数据结构
  17. 高速公路联网收费二义性路径识别系统原理及开发
  18. HTTP协议详解+经典面试题
  19. 拉勾网认证企业信息采集
  20. 域名解析不生效的原因及排查方法

热门文章

  1. 全体起立!世界第一座自动化立体库的诞生故事与现场生图!
  2. 最小采样频率计算公式_《傅里叶光学(九)》 信号采样与重建
  3. 【EMCC】 12.1.0.5 OEM server agent 安装配置及监控MySQL数据库
  4. ssm+jsp计算机毕业设计艾儿影楼管理系统18llj(程序+LW+源码+远程部署)
  5. php 框架搭建,利用composer搭建一个PHP微框架(API微项目)
  6. win10删除开机密码_电脑要开机时,按什么键才能一键还原?
  7. python flask + js ajax + echarts 53万条招聘信息可视化系统的渣实现
  8. #231 – 使用渐变色作为前景色(You Can Use a Brush for a Control’s Foreground)
  9. android加载字体内存泄露,在Windows GDI中创建和使用字体/避免内存泄漏
  10. java pay是关键字吗_如何使用Bitpay与Java