0

I know it has been explained a hundred times, and I've looked at them all and still can't figure it out. I have experience on BlackBerry 10 QT/C++ but am trying to ride the BlackBerry train into Android and that means learning both Java and the Android way of doing things.

I am following (among other guides) this one

in AndroidManifest.xml

<application

android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

    <activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:enabled="true" android:name=".myService" >
    </service>
    <receiver android:name="android.support.v4.media.session.MediaButtonReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_BUTTON" />
        </intent-filter>
    </receiver>
</application>

I think I have things where they need to be? No?

In myService.java

public class myService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

private MediaSessionCompat.Callback mediaSessionCompatCallBack = new MediaSessionCompat.Callback()
{
    @Override
    public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
        Log.d("MEDIAKEY", "Key Event");

        return super.onMediaButtonEvent(mediaButtonEvent);
    }
};

private MediaSessionCompat mediaSessionCompat;


@Override
public void onCreate() {
    Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
    Log.d("SERVICE", "onCreate");

    mediaSessionCompat = new MediaSessionCompat(this, "MEDIA");


}

@Override
public void onDestroy() {
    Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
    Log.d("SERVICE", "onDestroy");

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
    Log.d("SERVICE_STARTUP", "onStart");

    mediaSessionCompat.setCallback(mediaSessionCompatCallBack);

    mediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);


    MediaButtonReceiver.handleIntent(mediaSessionCompat, intent);

    mediaSessionCompat.setActive(true);


    return START_STICKY;
}

Any help would be great,

Thanks

EDIT: Ok I've changed the onCreate() to:

    context = getApplicationContext();

    mediaSessionCompat = new MediaSessionCompat(context, "MEDIA");

    mediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);

    mediaSessionCompat.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
            Log.d("MEDIA", "event");

            return super.onMediaButtonEvent(mediaButtonEvent);
        }
    });

and onStartCommand() to: MediaButtonReceiver.handleIntent(mediaSessionCompat, intent);

    mediaSessionCompat.setActive(true);

    return super.onStartCommand(intent, flags, startId);

But still no Log.d() on pressing any media keys, I watched the video and it helped me understand it but not getting what the problem is, I'm on API 22 (5.1.1) by the way.

IWIK
  • 11
  • 3

1 Answers1

2

There's a few things in the MediaButtonReceiver documentation you are missing firstly:

  • You need to add the <intent-filter> for android.intent.action.MEDIA_BUTTON to your .myService - without this, MediaButtonReceiver won't know which Service to forward media buttons to
  • You need to call handleIntent() in your onStartCommand()

After that, your Service will be set up correctly, but you still won't receive media buttons. As explained in the Media Playback the Right Way talk, you need to become the preferred media button receiver by calling mediaSessionCompat.setActive(true).

You'll also want to make sure you are calling

mediaSessionCompat.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
  MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mediaSessionCompat.setCallback(mediaSessionCompatCallBack);

This ensures that you say you can handle media buttons and registers your Callback instance with the MediaSessionCompat.

Note that MediaSessionCompat will automatically translate media buttons into the appropriate Callback methods (i.e., play will translate to onPlay() being called, etc) so in many cases you don't need to directly override onMediaButtonEvent().

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • Thanks for your help I have MediaButtonReceiver.handleIntent(mediaSessionCompat, intent); in my onStartCommand() I also have mediaSessionCompat.setActive(true); I added the intent-filter, and the other media transport flag, I do need to overload the buttons because i want some custom stuff going on... Still not getting the Log.d() – IWIK Jan 12 '16 at 00:32
  • Then as long as you are starting your service once and add the ``, it should work. As explained in the talk, generally you can `setActive(true)` when you start media playback. – ianhanniballake Jan 12 '16 at 00:37
  • I edited the original post with the changes I made, This was a lot easier on BlackBerry 10 haha. I'm not sure what I'm missing here... – IWIK Jan 12 '16 at 01:15
  • @IWIK - did you also add the `` to `.myService`? How are you triggering a media button? `MediaButtonReceiver` prints out an error message if it cannot find a service to forward the media button onto. – ianhanniballake Jan 12 '16 at 01:34
  • I'm just hitting the play/pause volume up, volume down. I see I actually do get a Log.d() if i connect a headset and hit the media button there, am I looking in the wrong place for volume and play/pause events? – IWIK Jan 12 '16 at 01:40
  • Haha I've wasted so much time it looks like – IWIK Jan 12 '16 at 01:48
  • Actually [MediaSessionCompat](https://developer.android.com/reference/android/support/v4/media/session/MediaSessionCompat.html) says volume keys too... – IWIK Jan 12 '16 at 01:56
  • Ah, yes volume keys are very different from media buttons: the volume keys automatically adjust the currently playing audio stream (or by default the ringer volume). You can override it by using [setPlaybackToRemote()](https://developer.android.com/reference/android/support/v4/media/session/MediaSessionCompat.html#setPlaybackToRemote(android.support.v4.media.VolumeProviderCompat)), but obviously that disables the user from modifying the local volume and is only appropriate if you are actually adjusting the volume on a remote device (such as with Google Cast devices). – ianhanniballake Jan 12 '16 at 02:39