在Android中并没有定义MediaButtonReceive这个广播类,MediaButtonReceive只是作为一种通俗的命名方式来响应

插入耳机后,点击耳机上的按钮(名称:MEDIA_BUTTON)接受该广播事件的类。所有该MEDIA_BUTTON的按下我们就简称

为MEDIA_BUTTON广播吧。

顾名思义:它显然是一个广播接收器类(BroadbcastReceiver),那么它就具备了BroadbcastReceiver类的使用方式,

但是,因为它需要通过AudioManager对象注册,所以它有着自己的独特之处(否则我也不会单独拿出来分析,- -),后面我们

会慢慢的讲解。

点击MEDIA_BUTTON发送的Intent Action 为:

ACTION_MEDIA_BUTTON ="android.intent.action.MEDIA_BUTTON"

Intent 附加值为(Extra)点击MEDIA_BUTTON的按键码:

//获得KeyEvent对象

KeyEvent keyEvent = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);

//获得Action

String intentAction = intent.getAction() ;

AudioManager对象注册MEDIA_BUTTON广播的方法原型为:

public voidregisterMediaButtonEventReceiver(ComponentNameeventReceiver)

Register a component to be thesole receiverof MEDIA_BUTTON intents

Parameters

eventReceiver :identifier of a BroadcastReceiver that will receive the media button intent. This broadcast receiver

must bedeclared in the application manifest.

从注释可知以下两点:

1、在AudioManager对象注册一个MediaoButtonRecevie,使它成为MEDIA_BUTTON的唯一接收器(这很重要,

我们会放在后面讲解) 也就是说只有我能收到,其他的都收不到这个广播了,否则的话大家都收到会照成一定的混乱;

2、 该广播必须在AndroidManifest.xml文件中进行声明,否则就监听不到该MEDIA_BUTTON广播了。

下面我们就简单的写一个MediaButtonReceiver类,并且在AndroidManifest.xml定义

1、 自定义的MediaButtonReceiver 广播类

[java] view plain copy print ?
  1. packagecom.qin.mediabutton;
  2. importandroid.content.BroadcastReceiver;
  3. importandroid.content.Context;
  4. importandroid.content.Intent;
  5. importandroid.util.Log;
  6. importandroid.view.KeyEvent;
  7. publicclassMediaButtonReceiverextendsBroadcastReceiver{
  8. privatestaticStringTAG="MediaButtonReceiver";
  9. @Override
  10. publicvoidonReceive(Contextcontext,Intentintent){
  11. //获得Action
  12. StringintentAction=intent.getAction();
  13. //获得KeyEvent对象
  14. KeyEventkeyEvent=(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
  15. Log.i(TAG,"Action---->"+intentAction+"KeyEvent----->"+keyEvent.toString());
  16. if(Intent.ACTION_MEDIA_BUTTON.equals(intentAction)){
  17. //获得按键字节码
  18. intkeyCode=keyEvent.getKeyCode();
  19. //按下/松开按钮
  20. intkeyAction=keyEvent.getAction();
  21. //获得事件的时间
  22. longdowntime=keyEvent.getEventTime();
  23. //获取按键码keyCode
  24. StringBuildersb=newStringBuilder();
  25. //这些都是可能的按键码,打印出来用户按下的键
  26. if(KeyEvent.KEYCODE_MEDIA_NEXT==keyCode){
  27. sb.append("KEYCODE_MEDIA_NEXT");
  28. }
  29. //说明:当我们按下MEDIA_BUTTON中间按钮时,实际出发的是KEYCODE_HEADSETHOOK而不是
  30. //KEYCODE_MEDIA_PLAY_PAUSE
  31. if(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE==keyCode){
  32. sb.append("KEYCODE_MEDIA_PLAY_PAUSE");
  33. }
  34. if(KeyEvent.KEYCODE_HEADSETHOOK==keyCode){
  35. sb.append("KEYCODE_HEADSETHOOK");
  36. }
  37. if(KeyEvent.KEYCODE_MEDIA_PREVIOUS==keyCode){
  38. sb.append("KEYCODE_MEDIA_PREVIOUS");
  39. }
  40. if(KeyEvent.KEYCODE_MEDIA_STOP==keyCode){
  41. sb.append("KEYCODE_MEDIA_STOP");
  42. }
  43. //输出点击的按键码
  44. Log.i(TAG,sb.toString());
  45. }
  46. }
  47. }

2、 在AndroidManifest.xml声明我们定义的广播类。

[java] view plain copy print ?
  1. <receiverandroid:name="MediaButtonReceiver">
  2. <intent-filter>
  3. <actionandroid:name="android.intent.action.MEDIA_BUTTON"></action>
  4. </intent-filter>
  5. </receiver>

在模拟器上,我们可以手动构造MEDA_BUTTON的广播,并且将它发送出去(后面会介绍)。

如果有真机测试的话,按下MEDIA_BUTTON是可以接受到MEDIA_BUTTON广播的,如果没有接受到,请关闭所有应用

程序,在观察效果。

继续我们的下一步分析:

前面我们说明通过registerMediaButtonEventReceiver(eventReceiver)方法注册时使它成为MEDIA_BUTTON的

唯一接收器这个唯一是怎么实现的呢? 我们在源码中,一步步追本溯源,相信一定可以找到答案,知道这“唯一“是

怎么来的。

第一步、 为AudioManager注册一个MediaButtonReceiver() ;

[java] view plain copy print ?
  1. //获得AudioManager对象
  2. AudioManagermAudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
  3. //构造一个ComponentName,指向MediaoButtonReceiver类
  4. //下面为了叙述方便,我直接使用ComponentName类来替代MediaoButtonReceiver类
  5. ComponentNamembCN=newComponentName(getPackageName(),MediaButtonReceiver.class.getName());
  6. //注册一个MedioButtonReceiver广播监听
  7. mAudioManager.registerMediaButtonEventReceiver(mbCN);
  8. //取消注册的方法
  9. mAudioManager.unregisterMediaButtonEventReceiver(mbCN);

MediaButtonReceiver就是我们用来接收MEDIA_BUTTON的广播类,下面为了叙述方便和直观上得体验,我直接使用

ComponentName类来替代真正的MediaoButtonReceiver广播类。

说明 接下来分析的文件路径全部在 frameworks/base/media/java/android/media/ 下

第二步、进入AudioManager.java进行查看 ,发现如下方法:

[java] view plain copy print ?
  1. //注册的方法为:
  2. publicvoidregisterMediaButtonEventReceiver(ComponentNameeventReceiver){
  3. //TODOenforcetheruleaboutthereceiverbeingdeclaredinthemanifest
  4. //我们继续查看getService()方法,看看IAudioService类到底是什么?
  5. IAudioServiceservice=getService();
  6. try{
  7. //只是简单的调用了service的方法来完成注册,继续跟踪
  8. service.registerMediaButtonEventReceiver(eventReceiver);
  9. }catch(RemoteExceptione){
  10. Log.e(TAG,"DeadobjectinregisterMediaButtonEventReceiver"+e);
  11. }
  12. }
  13. //取消注册的方法为
  14. publicvoidunregisterMediaButtonEventReceiver(ComponentNameeventReceiver){
  15. IAudioServiceservice=getService();
  16. try{
  17. //只是简单的调用了service的方法来取消注册,,继续跟踪
  18. service.unregisterMediaButtonEventReceiver(eventReceiver);
  19. }catch(RemoteExceptione){
  20. Log.e(TAG,"DeadobjectinunregisterMediaButtonEventReceiver"+e);
  21. }
  22. }


找到getService()方法,其实现为:

[java] view plain copy print ?
  1. //看看它到底是什么
  2. privatestaticIAudioServicegetService()
  3. {
  4. //单例模式,大家懂得
  5. if(sService!=null){
  6. returnsService;
  7. }
  8. //了解Binder机制以及AIDL文件的使用,就明白了这不过是通过AIDL文件定义的Java层Binder机制
  9. //b为IBinder基类接口
  10. IBinderb=ServiceManager.getService(Context.AUDIO_SERVICE);
  11. //强制转换后,sService不过是一个客户端对象,IAudioService就是aidl文件定义的接口了
  12. sService=IAudioService.Stub.asInterface(b);
  13. returnsService;
  14. }
  15. //sService对象的声明
  16. privatestaticIAudioServicesService;//单例模式,不足为奇了


我们知道了AudiaoManager只不过是一个傀儡,所有的方法都是由IAudioService 对象去实现的,通过它的构造方式,

可以知道它应该是有AIDL文件形成的Binder机制,sService只是客户端对象,那么它的服务端对象在什么地方呢?

也就是继承了IAudioService.Stub桩的类。

第三步、接下来我们需要找到该IAudioService.aidl文件和真正的服务端对象

IAudioService.aidl定义如下:

[java] view plain copy print ?
  1. packageandroid.media;
  2. importandroid.content.ComponentName;
  3. importandroid.media.IAudioFocusDispatcher;
  4. /**
  5. *{@hide}
  6. */
  7. interfaceIAudioService{
  8. voidadjustVolume(intdirection,intflags);
  9. voidadjustSuggestedStreamVolume(intdirection,intsuggestedStreamType,intflags);
  10. voidadjustStreamVolume(intstreamType,intdirection,intflags);
  11. voidsetStreamVolume(intstreamType,intindex,intflags);
  12. voidsetStreamSolo(intstreamType,booleanstate,IBindercb);
  13. voidsetStreamMute(intstreamType,booleanstate,IBindercb);
  14. intgetStreamVolume(intstreamType);
  15. intgetStreamMaxVolume(intstreamType);
  16. voidsetRingerMode(intringerMode);
  17. intgetRingerMode();
  18. voidsetVibrateSetting(intvibrateType,intvibrateSetting);
  19. intgetVibrateSetting(intvibrateType);
  20. booleanshouldVibrate(intvibrateType);
  21. voidsetMode(intmode,IBindercb);
  22. intgetMode();
  23. onewayvoidplaySoundEffect(inteffectType);
  24. onewayvoidplaySoundEffectVolume(inteffectType,floatvolume);
  25. booleanloadSoundEffects();
  26. onewayvoidunloadSoundEffects();
  27. onewayvoidreloadAudioSettings();
  28. voidsetSpeakerphoneOn(booleanon);
  29. booleanisSpeakerphoneOn();
  30. voidsetBluetoothScoOn(booleanon);
  31. booleanisBluetoothScoOn();
  32. intrequestAudioFocus(intmainStreamType,intdurationHint,IBindercb,IAudioFocusDispatcherl,StringclientId);
  33. intabandonAudioFocus(IAudioFocusDispatcherl,StringclientId);
  34. voidunregisterAudioFocusClient(StringclientId);
  35. voidregisterMediaButtonEventReceiver(inComponentNameeventReceiver);//这个方法是我们需要弄懂的
  36. voidunregisterMediaButtonEventReceiver(inComponentNameeventReceiver);//这个方法也是是我们需要弄懂的
  37. voidstartBluetoothSco(IBindercb);
  38. voidstopBluetoothSco(IBindercb);
  39. }

真正的服务端对象就是继承了 IAudioService.Stub 桩的类,AudioService就是该服务端对象,其实AudioManager的

所有操作都是由AudioService来实现的,它才是真正的老大。


第五步、 AudioService.java

[java] view plain copy print ?
  1. //AudioService类
  2. publicclassAudioServiceextendsIAudioService.Stub{
  3. //.....
  4. //仅仅列出我们需要的方法
  5. //这儿才是真正的注册MediaButtonReceiver的方法
  6. publicvoidregisterMediaButtonEventReceiver(ComponentNameeventReceiver){
  7. Log.i(TAG,"RemoteControlregisterMediaButtonEventReceiver()for"+eventReceiver);
  8. synchronized(mRCStack){
  9. //调用它去实现注册ComponentName
  10. pushMediaButtonReceiver(eventReceiver);
  11. }
  12. }
  13. //在查看pushMediaButtonReceiver()方法先理解一下两个知识点,很重要的。
  14. //RemoteControlStackEntry内部类不过是对ComponentName类的进一步封装(感觉没必要在加一层进行封装了)
  15. privatestaticclassRemoteControlStackEntry{
  16. publicComponentNamemReceiverComponent;//属性
  17. //TODOimplementregistrationexpiration?
  18. //publicintmRegistrationTime;
  19. publicRemoteControlStackEntry(){
  20. }
  21. publicRemoteControlStackEntry(ComponentNamer){
  22. mReceiverComponent=r;//构造函数赋值给mReceiverComponent对象
  23. }
  24. }
  25. //采用了栈存储结构(先进后出)来保存所有RemoteControlStackEntry对象,也就是保存了ComponentName对象
  26. privateStack<RemoteControlStackEntry>mRCStack=newStack<RemoteControlStackEntry>();
  27. //回到pushMediaButtonReceiver()查看,这下该拨开云雾了吧,继续学习
  28. privatevoidpushMediaButtonReceiver(ComponentNamenewReceiver){
  29. //alreadyattopofstack?
  30. //采用了一个栈(前面我们介绍的知识点)来保存所有注册的ComponentName对象
  31. //如果当前栈不为空并且栈顶的对象与新注册的ComponentName对象一样,不做任何事,直接返回
  32. if(!mRCStack.empty()&&mRCStack.peek().mReceiverComponent.equals(newReceiver)){
  33. return;
  34. }
  35. //获得mRCStack栈的迭代器
  36. Iterator<RemoteControlStackEntry>stackIterator=mRCStack.iterator();
  37. //循环
  38. while(stackIterator.hasNext()){
  39. RemoteControlStackEntryrcse=(RemoteControlStackEntry)stackIterator.next();
  40. //如果当前栈内保存该新注册的ComponentName对象,将它移除,跳出循环
  41. if(rcse.mReceiverComponent.equals(newReceiver)){
  42. mRCStack.remove(rcse);
  43. break;
  44. }
  45. }
  46. //将新注册的ComponentName对象放入栈顶
  47. mRCStack.push(newRemoteControlStackEntry(newReceiver));
  48. }
  49. }

小结一下:


栈(mRCStack)维护了所有CompoentName对象,对每个CompoentName对象,保证它有且仅有一个,

新注册的CompoentName对象永远处于栈顶


我们看下取消注册的方法:

[java] view plain copy print ?
  1. //我们看下取消注册的方法
  2. /**seeAudioManager.unregisterMediaButtonEventReceiver(ComponentNameeventReceiver)*/
  3. publicvoidunregisterMediaButtonEventReceiver(ComponentNameeventReceiver){
  4. Log.i(TAG,"RemoteControlunregisterMediaButtonEventReceiver()for"+eventReceiver);
  5. synchronized(mRCStack){
  6. //调用removeMediaButtonReceiver方法去实现
  7. removeMediaButtonReceiver(eventReceiver);
  8. }
  9. }
  10. privatevoidremoveMediaButtonReceiver(ComponentNamenewReceiver){
  11. Iterator<RemoteControlStackEntry>stackIterator=mRCStack.iterator();
  12. while(stackIterator.hasNext()){
  13. //获得mRCStack栈的迭代器
  14. RemoteControlStackEntryrcse=(RemoteControlStackEntry)stackIterator.next();
  15. //如果存在该对象,则移除,跳出循环
  16. if(rcse.mReceiverComponent.equals(newReceiver)){
  17. mRCStack.remove(rcse);
  18. break;
  19. }
  20. }
  21. }

通过对前面的学习,我们知道了AudioManager内部利用一个栈来管理包括加入和移除ComponentName对象,

新的疑问来了?这个MEDIA_BUTTON广播是如何分发的呢 ?


其实,AudioService.java文件中也存在这么一个MediaoButtonReceiver的广播类,它为系统广播接收器,即用来接收

系统的MEDIA_BUTTON广播,当它接收到了这个MEDIA_BUTTON广播,它会对这个广播进行进一步处理,这个处理过程

就是我们需要的弄清楚。

MediaButtonBroadcastReceiver 内部类如下:

[java] view plain copy print ?
  1. privateclassMediaButtonBroadcastReceiverextendsBroadcastReceiver{
  2. @Override
  3. publicvoidonReceive(Contextcontext,Intentintent){
  4. //获得action,系统MEDIA_BUTTON广播来了
  5. Stringaction=intent.getAction();
  6. //action不正确直接返回
  7. if(!Intent.ACTION_MEDIA_BUTTON.equals(action)){
  8. return;
  9. }
  10. //获得KeyEvent对象
  11. KeyEventevent=(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
  12. if(event!=null){
  13. //ifinacallorringing,donotbreakthecurrentphoneappbehavior
  14. //TODOmodifythistoletthephoneappspecificallygettheRCfocus
  15. //addmodifythephoneapptotakeadvantageofthenewAPI
  16. //来电或通话中,不做处理直接返回
  17. if((getMode()==AudioSystem.MODE_IN_CALL)||(getMode()==AudioSystem.MODE_RINGTONE)){
  18. return;
  19. }
  20. synchronized(mRCStack){
  21. //栈不为空
  22. if(!mRCStack.empty()){
  23. //createanewintentspecificallyaimedatthecurrentregisteredlistener
  24. //构造一个Intent对象,并且赋予Action和KeyEvent
  25. IntenttargetedIntent=newIntent(Intent.ACTION_MEDIA_BUTTON);
  26. targetedIntent.putExtras(intent.getExtras());
  27. //指定该处理Intent的对象为栈顶ComponentName对象的广播类
  28. targetedIntent.setComponent(mRCStack.peek().mReceiverComponent);
  29. //trapthecurrentbroadcast
  30. //终止系统广播
  31. abortBroadcast();
  32. //Log.v(TAG,"Sendingintent"+targetedIntent);
  33. //手动发送该广播至目标对象去处理,该广播不再是系统发送的了
  34. context.sendBroadcast(targetedIntent,null);
  35. }
  36. //假设栈为空,那么所有定义在AndroidManifest.xml的监听MEDIA_BUTTON的广播都会处理,
  37. //在此过程中如果有任何应用程注册了registerMediaButton该广播也会立即终止
  38. }
  39. }
  40. }
  41. }

总结一下MEDIA_BUTTON广播:

AudioManager也就是AudioService服务端对象内部会利用一个栈来管理所有ComponentName对象,所有对象有且仅有一个,

注册的ComponentName总是会位于栈顶。

当系统发送MEDIA_BUTTON,系统MediaButtonBroadcastReceiver 监听到系统广播,它会做如下处理:

1、如果栈为空,则所有注册了该Action的广播都会接受到,因为它是由系统发送的。
2、如果栈不为空,那么只有栈顶的那个广播能接受到MEDIA_BUTTON的广播,手动发送了MEDIA_BUTTON

广播,并且指定了目标对象(栈顶对象)去处理该MEDIA_BUTTON 。

下面分析一下KeyEvent对象里的KeyCode按键,可能的按键码有:


1、KeyEvent.KEYCODE_MEDIA_NEXT
2、KeyEvent.KEYCODE_HEADSETHOOK
3、KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE(已废除,等同于KEYCODE_HEADSETHOOK)
4、KeyEvent.KEYCODE_MEDIA_PREVIOUS
5、KeyEvent.KEYCODE_MEDIA_STOP

PS : 在我的真机测试中,按下MEDIA_BUTTON只有KEYCODE_HEADSETHOOK可以打印出来了。

下面给出一个小DEMO检验一下我们之前所做的一切,看看MEDIA_BUTTON是如何处理分发广播的。

编写两个MediaButtonReceiver类用来监听MEDIA_BUTTON广播:

1 、China_MBReceiver.java

[java] view plain copy print ?
  1. packagecom.qin.mediabutton;
  2. importandroid.content.BroadcastReceiver;
  3. importandroid.content.Context;
  4. importandroid.content.Intent;
  5. importandroid.util.Log;
  6. importandroid.view.KeyEvent;
  7. publicclassChina_MBReceiverextendsBroadcastReceiver{
  8. privatestaticStringTAG="China_MBReceiver";
  9. @Override
  10. publicvoidonReceive(Contextcontext,Intentintent){
  11. //获得Action
  12. StringintentAction=intent.getAction();
  13. //获得KeyEvent对象
  14. KeyEventkeyEvent=(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
  15. Log.i(TAG,"Action---->"+intentAction+"KeyEvent----->"+keyEvent.toString());
  16. if(Intent.ACTION_MEDIA_BUTTON.equals(intentAction)){
  17. //获得按键字节码
  18. intkeyCode=keyEvent.getKeyCode();
  19. //按下/松开按钮
  20. intkeyAction=keyEvent.getAction();
  21. //获得事件的时间
  22. longdowntime=keyEvent.getEventTime();
  23. //获取按键码keyCode
  24. StringBuildersb=newStringBuilder();
  25. //这些都是可能的按键码,打印出来用户按下的键
  26. if(KeyEvent.KEYCODE_MEDIA_NEXT==keyCode){
  27. sb.append("KEYCODE_MEDIA_NEXT");
  28. }
  29. //说明:当我们按下MEDIA_BUTTON中间按钮时,实际出发的是KEYCODE_HEADSETHOOK而不是KEYCODE_MEDIA_PLAY_PAUSE
  30. if(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE==keyCode){
  31. sb.append("KEYCODE_MEDIA_PLAY_PAUSE");
  32. }
  33. if(KeyEvent.KEYCODE_HEADSETHOOK==keyCode){
  34. sb.append("KEYCODE_HEADSETHOOK");
  35. }
  36. if(KeyEvent.KEYCODE_MEDIA_PREVIOUS==keyCode){
  37. sb.append("KEYCODE_MEDIA_PREVIOUS");
  38. }
  39. if(KeyEvent.KEYCODE_MEDIA_STOP==keyCode){
  40. sb.append("KEYCODE_MEDIA_STOP");
  41. }
  42. //输出点击的按键码
  43. Log.i(TAG,sb.toString());
  44. }
  45. }
  46. }

2 、England_MBReceiver.java同于China_MBRreceiver,打印Log TAG= "England_MBReceiver"

3、在AndroidManifest.xml文件定义:

[java] view plain copy print ?
  1. <strong><receiverandroid:name=".China_MBReceiver">
  2. <intent-filter>
  3. <actionandroid:name="android.intent.action.MEDIA_BUTTON"></action>
  4. </intent-filter>
  5. </receiver>
  6. <receiverandroid:name=".Enaland_MBReceiver">
  7. <intent-filter>
  8. <actionandroid:name="android.intent.action.MEDIA_BUTTON"></action>
  9. </intent-filter>
  10. </receiver></strong>


4、MainActivity .java我们通过手动构造一个MEDIA_BUTTON广播去查看我们的MediaButtonReceiver类的打印信息。

[java] view plain copy print ?
  1. packagecom.qin.mediabutton;
  2. importandroid.app.Activity;
  3. importandroid.content.ComponentName;
  4. importandroid.content.Context;
  5. importandroid.content.Intent;
  6. importandroid.media.AudioManager;
  7. importandroid.os.Bundle;
  8. importandroid.view.KeyEvent;
  9. publicclassMainActivityextendsActivity{
  10. /**Calledwhentheactivityisfirstcreated.*/
  11. @Override
  12. publicvoidonCreate(BundlesavedInstanceState){
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.main);
  15. //由于在模拟器上测试,我们手动发送一个MEDIA_BUTTON的广播,有真机更好处理了
  16. IntentmbIntent=newIntent(Intent.ACTION_MEDIA_BUTTON);
  17. //构造一个KeyEvent对象
  18. KeyEventkeyEvent=newKeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_HEADSETHOOK);
  19. //作为附加值添加至mbIntent对象中
  20. mbIntent.putExtra(Intent.EXTRA_KEY_EVENT,keyEvent);
  21. //此时China_MBReceiver和England_MBReceiver都会接收到该广播
  22. sendBroadcast(mbIntent);
  23. AudioManagermAudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
  24. //AudioManager注册一个MediaButton对象
  25. ComponentNamechinaCN=newComponentName(getPackageName(),China_MBReceiver.class.getName());
  26. //只有China_MBReceiver能够接收到了,它是出于栈顶的。
  27. //不过,在模拟上检测不到这个效果,因为这个广播是我们发送的,流程不是我们在上面介绍的。
  28. mAudioManager.registerMediaButtonEventReceiver(chinaCN);
  29. //sendBroadcast(mbIntent,null);
  30. }
  31. //当一个Activity/Service死去时,我们需要取消这个MediaoButtonReceiver的注册,如下
  32. protectedvoidonDestroy(){
  33. super.onDestroy();
  34. AudioManagermAudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
  35. ComponentNamechinaCN=newComponentName(getPackageName(),China_MBReceiver.class.getName());
  36. //取消注册
  37. mAudioManager.unregisterMediaButtonEventReceiver(chinaCN);
  38. }
  39. }

值得注意的一点时,当我们为一个应用程序注册了MediaoButtonReceiver时,在程序离开时,我们需要取消

MediaoButtonReceiver的注册,在onDestroy()调用unregisterMediaButtonEventReceiver()方法就OK,这样应用程序之间

的交互就更具逻辑性了。

感谢原作者,转自:http://blog.csdn.net/qinjuning/article/details/6938436

更多相关文章

  1. [转]五大布局对象---FrameLayout,LinearLayout ,AbsoluteLayout,
  2. Android(安卓)从原型模式看java实例化对象clone和new的区别
  3. 一个轻量级、可插拔的Android消息推送框架。一键集成推送(极光推
  4. android 内存优化详解
  5. 【android】使用Event Bus模式解耦Android(安卓)App组件间通信
  6. 关于Android中使用Handler造成内存泄露的分析和解决
  7. Android(安卓)判定网络连接状态 以及监听网络链接状态的变化
  8. Android中的缓存策略—拉取网络图片,缓存本地
  9. Evenbus思想解决切换网络高级处理(初级篇)

随机推荐

  1. 简单地聊聊统计学
  2. Excel如何分组排序
  3. 数据分析应关注AARRR模型的哪些指标
  4. 如何使用Git入门到熟练
  5. SQL今日一题(4):表连接
  6. 5月小复盘
  7. 如何进行数据图形化?
  8. 2020年Python文章盘点,我选出了个人TOP10
  9. 如何做好描述统计分析
  10. SQL今日一题(5):一题多解