1

I want a functionality in my react-native application in which I should be able to trigger an event on pressing a button from my bluetooth headset. I tried some libraries like react-native-keyevent etc which override the onKeyDown() function but I was not able to capture any event from my bluetooth device though it worked for my wiered headset. I also tried overriding dispatchKeyEvent() in MainActivity.class that didnt worked either. So right now I am trying to look into some native alternative which I can later make into a module and use in my application. I am trying to use MediaSession in my application right now but I am not able to capture any event via headsets. Below is my MediaService:

import android.app.Service;
import android.content.Intent;
import android.media.browse.MediaBrowser;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.service.media.MediaBrowserService;
import android.support.v4.media.session.IMediaSession;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import android.view.KeyEvent;
import androidx.media.session.MediaButtonReceiver;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import java.util.List;

public class MediaService extends Service {
    private MediaSessionCompat session;

    @Override
    public void onCreate() {
        Log.d("MediaService", "onCreate");
        session = new MediaSessionCompat(this, "Session");
        Log.d("MediaSession", "" + session);
        session.setCallback(new MediaSessionCompat.Callback() {
            @Override
            public boolean onMediaButtonEvent(final Intent mediaButtonIntent) {
                String action = mediaButtonIntent.getAction();
                Log.d("MediaSession", "Intent Action" + action);
                if (Intent.ACTION_MEDIA_BUTTON.equals(mediaButtonIntent.getAction())) {
                    KeyEvent event = (KeyEvent) mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
                    Log.d("MediaSession", "KeyCode" + event.getKeyCode());
                    return true;
                }
                return super.onMediaButtonEvent(mediaButtonIntent);
            }

            @Override
            public void onPlay() {
                Log.d("MediaSession", "onPlay" );
                super.onPlay();
            }
            @Override
            public void onPause() {
                Log.d("MediaSession", "onPause" );
                super.onPlay();
            }
        });
        PlaybackStateCompat state = new PlaybackStateCompat.Builder()
                .setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_STOP | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS)
                .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0, 0)
                .build();
        session.setPlaybackState(state);
        session.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
        session.setActive(true);
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("MediaService", "onStartCommand");
        MediaButtonReceiver.handleIntent(session, intent);
        return super.onStartCommand(intent, flags, startId);
    }

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

    @Override
    public void onDestroy() {
        session.release();
        super.onDestroy();
    }
}

I just want to handle the media button event without playing any audio I dont know what I am doing wrong here but every time i try pressing media button my last audio activity(generally spotify) starts playing I have also tried android:priority it doesnot work either.

<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
      </activity>
        <receiver android:name="androidx.media.session.MediaButtonReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </receiver>
        <service android:name=".MediaService" android:enabled="true" android:exported="true" android:permission="android.permission.FOREGROUND_SERVICE">
            <intent-filter android:priority="1000">
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </service>
      <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    </application>

I would highly appreciate if anyone can tell me what am I doing wrong or maybe a more suited alternative to what I am trying.

Thomas Meinhart
  • 659
  • 2
  • 7
  • 28

1 Answers1

1

Since Android 8.0, you cannot receive the media button unless you play audio. Just play dummy audio in Walk Around.

How register Broadcast Receiver for media button in Oreo?

  • my before question
    // play dummy audio
    AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
            AudioTrack.getMinBufferSize(48000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT), AudioTrack.MODE_STREAM);
    at.play();

    // a little sleep 
    at.stop();
    at.release();

It doesn't actually play the sound, it just changes the state.

오효민
  • 181
  • 1
  • 4