【问题标题】:Detecting whether a headset is plugged into an Android device or not.检测耳机是否插入 Android 设备。
【发布时间】:2011-09-09 02:13:45
【问题描述】:

如何确定耳机是否已插入 Android 设备?

【问题讨论】:

  • 我正在开发一个应用程序......而且我需要确定......如果我提示他问题,用户也可以作弊
  • 我编辑了你的问题,如果不是你想问的,请更正。
  • @Mudassir 感谢您的纠正:)

标签: android audio android-intent


【解决方案1】:

您可以使用广播接收器。

因此,您可以在“AndroidManifest.xml”中编写此代码

<receiver android:name="com.juno.brheadset.HeadsetStateReceiver">
    <intent-filter>
        <action android:name="android.intent.action.HEADSET_PLUG"/>
    </intent-filter>
</receiver>-->

但是,这不起作用。当操作系统发送此“HEADSET_PLUG”意图时,操作系统设置标志“Intent.FLAG_RECEIVER_REGISTERED_ONLY”因此,您应该在 Activity 或 Service 类中编写如下代码,而不是“AndroidManifest”。

public class BRHeadsetActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    HeadsetStateReceiver receiver = new HeadsetStateReceiver();
    registerReceiver( receiver, receiverFilter );


}

希望这篇文章对你有所帮助。再见!

这是“HeadsetObserver.java”的一部分,Android SDK Source。

private final void sendIntent(int headset, int headsetState, int prevHeadsetState, String headsetName) {
    if ((headsetState & headset) != (prevHeadsetState & headset)) {
        //  Pack up the values and broadcast them to everyone
        Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);

        **intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);**

        int state = 0;
        int microphone = 0;

        if ((headset & HEADSETS_WITH_MIC) != 0) {
            microphone = 1;
        }
        if ((headsetState & headset) != 0) {
            state = 1;
        }
        intent.putExtra("state", state);
        intent.putExtra("name", headsetName);
        intent.putExtra("microphone", microphone);

        if (LOG) Slog.v(TAG, "Intent.ACTION_HEADSET_PLUG: state: "+state+" name: "+headsetName+" mic: "+microphone);
        // TODO: Should we require a permission?
        ActivityManagerNative.broadcastStickyIntent(intent, null);
    }
}

【讨论】:

  • @Sumit 很抱歉。我现在看到了你的回放。我可以为您解释一下我的代码吗? :)
  • @Sumit 好的。我想你不明白这一点。如果您将“FLAG_RECEIVER_REGISTERED_ONLY”添加到广播意图中,则只有当我对不在“AndroidManifest.xml”上的代码执行“registerReceiver(...)”时,我才能接收到您的广播。
  • 什么是“HeadsetStateReceiver”是SDK类还是自定义类?
  • @shim 这是一个自定义类,它扩展了 BroadcastReceiver 并有一个 onReceive 方法
  • 很好奇,为什么要说再见?
【解决方案2】:

当您说“耳机”时,您的意思是“有线耳机”吗?如果是这样,有一个意图是检测一个是否被插入或拔出:ACTION_HEADSET_PLUG

要检查状态,您可以使用AudioManager.isWiredHeadsetOn(),但如果还有蓝牙耳机,这可能会返回 false,而是将音频路由到该耳机。

【讨论】:

  • 你好 Mike,如果有人使用蓝牙耳机我该怎么办?
  • AudioManager.isWiredHeadsetOn() 似乎总是返回 false(在多个 Gingerbread 设备上测试),无论是否插入耳机。如果您能提供一个工作代码示例,那就太好了。
  • @ChadSchultz 您需要在清单中添加权限 MODIFY_AUDIO_SETTINGS ..然后它才会返回正确的状态。
  • 被弃用的函数 API21
  • 对于蓝牙耳机,请在此处查看 jobbert 的答案:stackoverflow.com/questions/4715865/…
【解决方案3】:

AudioManager.isWiredHeadsetOn() 总是返回false,因为它需要用户权限MODIFY_AUDIO_SETTINGS

我花了几天时间才找到答案。官方文档中没有关于此的信息。而这个bug已经在BugTracker注册了。

【讨论】:

    【解决方案4】:
    【解决方案5】:

    首先,在清单中创建接收器:

        <receiver android:name="com.yourapplication.BroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.HEADSET_PLUG"/>
            </intent-filter>
        </receiver>
    

    不要忘记根据你的项目名称更改 com.yourapplication

    在活动的头部创建两个变量:

    private  BroadcastReceiver mReceiver  ;
    boolean Microphone_Plugged_in = false;
    

    在你的活动的 onCreate 中定义你的接收器:

            mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                int iii=2;
                if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
                    iii=intent.getIntExtra("state", -1);
                    if(Integer.valueOf(iii)==0){
                        Microphone_Plugged_in = false;
                        Toast.makeText(getApplicationContext(),"microphone not plugged in",Toast.LENGTH_LONG).show();
                    }if(Integer.valueOf(iii)==1){
                        Microphone_Plugged_in = true;
                        Toast.makeText(getApplicationContext(),"microphone plugged in",Toast.LENGTH_LONG).show();
                    }
                }
            }};
            IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
            registerReceiver( mReceiver, receiverFilter );
    

    添加 onResume 和 onStope :

    @Override
      protected void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
        getApplicationContext().registerReceiver(mReceiver, filter);
    }
    
    @Override
    protected void onStop() {
        super.onStop();
        getApplicationContext().unregisterReceiver(mReceiver);
    }
    

    【讨论】:

      【解决方案6】:

      您可以在您的项目中创建这种接收器类(Kotlin with Flow):

      class HeadsetPlugReceiver : BroadcastReceiver() {
      
          private val _isPlugged = MutableStateFlow<Boolean>(false)
          val isPlugged: StateFlow<Boolean> = _isPlugged.asStateFlow()
      
          override fun onReceive(context: Context, intent: Intent) {
              context.appComponent.inject(this)
              val action = intent.action
              Log.i(TAG, "onReceive: $action")
              when (action) {
                  Intent.ACTION_HEADSET_PLUG -> sendEvent(intent)
                  else -> checkStateOff(intent)
              }
          }
      
          private fun checkStateOff(intent: Intent) {
             Log.i(TAG, "onReceive: the local Bluetooth adapter is off")
          }
      
          private fun sendEvent(intent: Intent) {
              val isPlugged = intent.getIntExtra(HEADSET_STATE, 0) == 1
              Log.i(TAG, "sendEvent: $isPlugged")
              _isPlugged.value = isPlugged
          }
      
          private companion object {
      
             private const val TAG = "HeadsetPlugReceiver"
             // Headset constant
             private const val HEADSET_STATE = "state"
          }
      }
      

      然后在带有上下文的某个类中注册这个接收器:

      val headsetReceiver = HeadsetPlugReceiver()
      val headsetFilter = IntentFilter(Intent.ACTION_HEADSET_PLUG)
          context.registerReceiver(headsetReceiver, headsetFilter)
      

      然后收集isPlugged就可以得到你的有线耳机连接状态

      PS:不要忘记在不需要时取消注册您的接收器context.unregisterReceiver(headsetReceiver)

      【讨论】:

        【解决方案7】:

        要添加到其他答案,来自 Android 文档:

        警告:限制您在应用中设置的广播接收器数量。 广播接收器过多会影响应用的性能 以及用户设备的电池寿命。有关更多信息 您可以使用 API 代替 BroadcastReceiver 类进行调度 后台工作,请参阅后台优化。

        https://developer.android.com/guide/topics/manifest/receiver-element

        这意味着您应该尽可能创建少量广播接收器,以防止您的应用出现内存问题。

        我会建议对这个接收器使用单例类。在 Kotlin 中:

        class HeadsetReceiver private constructor(): BroadcastReceiver() {
        
            // instances
            var callback: HeadsetReceiverCallback? = null
        
            //region singleton
            private object HOLDER {
                val INSTANCE = HeadsetReceiver()
            }
        
            companion object {
                val instance: HeadsetReceiver by lazy { HOLDER.INSTANCE }
            }
            //endregion
        
            override fun onReceive(context: Context, intent: Intent) {
                if (intent.action == Intent.ACTION_HEADSET_PLUG) {
                    if(intent.getIntExtra("state", -1) == 0) {
                        callback?.onHeadsetDisconnected()
                    } else {
                        callback?.onHeadsetConnected()
                    }
                }
            }
        
            fun register(context: Context) {
                val receiverFilter = IntentFilter(Intent.ACTION_HEADSET_PLUG)
                context.registerReceiver(this, receiverFilter)
            }
        
            fun unregister(context: Context) {
                context.unregisterReceiver(this)
                callback = null
            }
        
            interface HeadsetReceiverCallback {
                fun onHeadsetConnected()
                fun onHeadsetDisconnected()
            }
        }
        

        注册:

        HeadsetReceiver.instance.register(context)
                HeadsetReceiver.instance.callback = object : HeadsetReceiver.HeadsetReceiverCallback {
                    override fun onHeadsetConnected() {
                        println("connected!")
                    }
        
                    override fun onHeadsetDisconnected() {
                        println("disonnected!")
                    }
                }
        

        注销:

        HeadsetReceiver.instance.unregister(context)
        

        【讨论】:

          猜你喜欢
          • 2012-05-27
          • 2011-04-04
          • 2017-04-24
          • 2011-04-13
          • 1970-01-01
          • 1970-01-01
          • 2020-08-17
          • 2016-02-25
          • 2013-04-17
          相关资源
          最近更新 更多