`
yidongkaifa
  • 浏览: 4038466 次
文章分类
社区版块
存档分类
最新评论

android 耳机按钮监听

 
阅读更多

在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 the sole 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 广播类

  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声明我们定义的广播类。

  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() ;

  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进行查看 ,发现如下方法:

  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()方法,其实现为:

  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定义如下:

  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

  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对象永远处于栈顶


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

  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 内部类如下:

  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

  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文件定义:

  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类的打印信息。

  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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics