android - 如何在 "offline"模式下检测耳机插拔事件

标签 android broadcastreceiver

<分区>

如果我的应用程序正在运行,我知道如何检测耳机插入事件。您必须为 ACTION_HEADSET_PLUG 注册广播接收器。但是您不能使用广播接收器的 list 声明来捕获此操作。因此,捕获耳机插入事件的唯一选择是后台服务。但它会耗尽电池等。

我检查了一些音乐播放器,发现它们无需任何附加服务即可捕获该事件。他们是怎么做到的?有什么想法吗?

最佳答案

三年来,我在商店里有一个应用程序可以同时监控有线耳机和蓝牙状态,而且从来没有人提示电池耗尽。但那是因为我成功地使用单个服务和广播接收器来检测来自两者的事件。这是两个关键类:

public class HeadsetStateBroadcastReceiver extends BroadcastReceiver {

    public static final String[] HEADPHONE_ACTIONS = {
        Intent.ACTION_HEADSET_PLUG,
        "android.bluetooth.headset.action.STATE_CHANGED",
        "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED"
    };

    @Override
    public void onReceive(final Context context, final Intent intent) {

        boolean broadcast = false;

        // Wired headset monitoring
        if (intent.getAction().equals(HEADPHONE_ACTIONS[0]) {
            final int state = intent.getIntExtra("state", 0);
            AudioPreferences.setWiredHeadphoneState(context, state > 0);
            broadcast = true;
        }

        // Bluetooth monitoring
        // Works up to and including Honeycomb
        if (intent.getAction().equals(HEADPHONE_ACTIONS[1])) {
            int state = intent.getIntExtra("android.bluetooth.headset.extra.STATE", 0);
            AudioPreferences.setBluetoothHeadsetState(context, state == 2);
            broadcast = true;
        }

        // Works for Ice Cream Sandwich
        if (intent.getAction().equals(HEADPHONE_ACTIONS[2])) {
            int state = intent.getIntExtra("android.bluetooth.profile.extra.STATE", 0);
            AudioPreferences.setBluetoothHeadsetState(context, state == 2);
            broadcast = true;
        }

        // Used to inform interested activities that the headset state has changed
        if (broadcast) {
            LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("headsetStateChange"));
        }

    }

}

这是我用来注册广播接收器的服务:

public class HeadsetMonitoringService extends Service {

    HeadsetStateBroadcastReceiver headsetStateReceiver;

    @Override
    public void onCreate() {

        headsetStateReceiver = new HeadsetStateBroadcastReceiver();
        final IntentFilter filter = new IntentFilter();
        for (String action: HeadsetStateBroadcastReceiver.HEADPHONE_ACTIONS) {
            filter.addAction(action);
        }

        registerReceiver(headsetStateReceiver, filter);

    }

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(headsetStateReceiver);
    }

    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }

}

这是我的 list 条目:

    <service
        android:name=".services.HeadsetMonitoringService"
        android:enabled="true"
        android:exported="false" >
        <intent-filter>
            <action android:name="initialiseHeadsetService" />
        </intent-filter>
    </service>

其工作原理如下:

我使用启动广播接收器向 HeadsetMonitoringService 发送启动服务消息(您不必以这种方式执行,您可以在应用程序启动时执行此操作)。 HeadsetMonitoringService 依次注册一个广播监听器实例,该监听器监听我感兴趣的所有耳机​​事件 - 它们保存在 HEADPHONE_ACTIONS 数组中。因为服务是粘性的,所以它会一直存在——广播监听器也是如此。但是因为服务和广播监听器都是事件驱动的,所以在耳机状态发生变化之前它们不会消耗任何电量。此外,由于该服务是粘性的,如果它意外死亡,它会被操作系统重新启动。
每当我收到耳机状态更改事件时,我也会触发本地广播,以便感兴趣的 Activity 可以检查新状态并在需要时采取行动。

为了完整起见,我应该指出我使用了另一个类(此处未显示)AudioPreferences 来存储蓝牙和有线耳机状态作为首选项,然后我可以在需要了解耳机状态时访问它。

如果您对蓝牙耳机的状态感兴趣,您的应用程序将需要 android.permission.BLUETOOTH 权限。如果没有,只需从 HEADPHONE_ACTIONS 数组中取出蓝牙相关的操作,并从 onReceive 方法中删除关联的 if block 。

关于android - 如何在 "offline"模式下检测耳机插拔事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16409309/

相关文章:

android - 更改特定风格的应用程序的默认语言

java - 如何在 Dashclock 扩展中维护持久的 BroadcastReceiver?

android - 在android中检测用户接听来电的结束? (未拒绝)

java - 如何通过单击方向按钮来移动 onDraw 形状

android - 关于缺少 Leanback Intent 的 Google Play 警告

android - 如何在 Android Kotlin 中从 Date 获取小时数?

java - 安卓 : Implement Broadcast Receiver for ClipboardManager

android - 当我在另一个函数中等待异常时,如何在Kotlin协程中捕获异常?

android - 短信广播接收器 - 如何在短信被默认消息应用程序读取之前阻止/删除短信

android:屏幕打开和屏幕关闭的广播接收器