Search code examples
androidaudiosense

Registered ACTION_HEADSET_PLUG Listener triggers only a few times


I want to show a Notification after a the Headset was plugged in and hide it after it has been unplugged. Therefore I register the ACTION_HEADSET_PLUG Intent Listener in a BroadCastReceiver which is triggered at BOOT_COMPLETED. In my case I use HTC Sense (HTC One S) and the notification is only shown when I plug in the headset while Sense is loading (WaitDialog) after that it won't show up anymore.

If I trigger the OnBootListener in app at runtime via 'new OnBootreceiver().onReceive(this, null)' it works perfect.

Manifest:

...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        ...
    </activity>

    <receiver android:name=".OnBootReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
 ...

OnBootReceiver:

public void onReceive(Context context, Intent intent) {
    IntentFilter receiverFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    HeadsetStateReceiver receiver = new HeadsetStateReceiver();
    context.registerReceiver( receiver, receiverFilter );
}

HeadsetStateReceiver:

public void onReceive(Context context, Intent intent) {
    Toast.makeText(context,
            "" + (Integer) (intent.getExtras().get("state")),
            Toast.LENGTH_SHORT).show();
    mNotificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);

    Log.e(this.getClass().toString(), "Intent Headset_plug received "
            + intent);
    if ((Integer) (intent.getExtras().get("state")) != 0) {
        notification.flags = Notification.FLAG_ONGOING_EVENT;
        notification.contentIntent = PendingIntent.getActivity(
                context.getApplicationContext(), 0, new Intent(), 0);
        notification.setLatestEventInfo(context, title, message,
                notification.contentIntent);
        mNotificationManager.notify(0xBEA15, notification);
    } else {
        mNotificationManager.cancelAll();
    }

}

Solution

  • Why do you need BOOT_COMPLETED receiver? Did you try receive ACTION_HEADSET_PLUG using manifest file?

    <application 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" > 
        <activity 
            ... 
        </activity> 
    
        <receiver android:name=".HeadsetStateReceiver" > 
            <intent-filter> 
                <action android:name="android.intent.ACTION_HEADSET_PLUG" /> 
            </intent-filter> 
        </receiver> 
    

    yor code is a bit meessy too:

    public void onReceive(Context context, Intent intent) {
        boolean isConnected = intent.getIntExtra("state",0)==1; // Can also be 2 if headset is attached w/o mic.
    
        Toast.makeText(context, 
                isConnected?"connected":"disconnected"), 
                Toast.LENGTH_SHORT).show(); 
        mNotificationManager = (NotificationManager) context 
            .getSystemService(Context.NOTIFICATION_SERVICE); 
    
        if (isConnected) {
            Log.e(this.getClass().toString(), "Intent Headset_plug connected");
            notification.flags = Notification.FLAG_ONGOING_EVENT; 
            notification.contentIntent = PendingIntent.getActivity( 
                    context.getApplicationContext(), 0, new Intent(), 0); 
            notification.setLatestEventInfo(context, title, message, 
                    notification.contentIntent); 
            mNotificationManager.notify(0xBEA15, notification); 
        } else {
            Log.e(this.getClass().toString(), "Intent Headset_plug disconnected");
            mNotificationManager.cancelAll(); 
        } 
    } 
    


    Ok direct receiver will not work (here is good explanation).

    I thing I know why your receiver stops working after some time. Your application must be cleanup by the system. To make it work you have to do something what will prevent your application from being cleanup. So you have to create a service. In BOOT_COMPLETED start a service and in this service register broadcast receiver for ACTION_HEADSET_PLUG. This should prevent application from been cleanup.