19

The RemoteControlClient was introduced in ICS. That's the way the lock screen seems to be integrating with various music players. See the screenshot below for an example of Spotify on the lock screen.

enter image description here

Could one from another app than the lock screen integrate with said players as well?

I find the documentation lacking a bit on the subject, but I think the results, if it's possible, could be interesting.

Edit:

Progress so far: none. What I've found out is that IRemoteControlDisplay likely has some part in it, but my Android/Java skills are a bit lacking to actually understand how to implement it and achieve the same functionality as on the lock screen.

Frans
  • 1,389
  • 2
  • 16
  • 28

6 Answers6

8

While working on my app I've actually found how to implement your own RemoteControlDisplay.

Basically, you extend IRemoteControlDisplay$Stub, which sends messages to special handler, this handler updates metadata and thing. Then you register your own class extended from IRemoteControlDisplay$Stub by calling to AudioManager#registerRemoteControlDisplay().

And then you unregister it by calling AudioManager#unregisterRemoteControlDisplay().

It's fairly complex, but I've wrote an article on how to this. I've published it on XDA, check it here: http://forum.xda-developers.com/showthread.php?p=44513199

  • Fantastic post! Just skimmed it for now, but you seem to have provided excellent guidelines for how to implement this on our own. – Frans Aug 11 '13 at 19:33
  • 2
    Also, you can now use my library, which will make process very simple: http://forum.xda-developers.com/showthread.php?p=45288378 – Alexander Woodblock Sep 07 '13 at 20:12
  • If I ever get my project developed for me, you're totally getting a donation. :) – Frans Sep 08 '13 at 13:52
  • Is this Possible using [mediaPlayer](http://developer.android.com/reference/android/media/MediaPlayer.html)? if yes than please give me reference link or code.?further details of my problem please see [this](http://stackoverflow.com/questions/36283020/music-player-control-while-screen-is-locked) question. – Chirag Solanki Apr 12 '16 at 05:57
6

I believe you can do this. However, the method will use private API (the implication is that it may not work on some later version of Android OS).

I recommend to go and download Android source code (http://source.android.com/) and check directory /frameworks/base/media/java/android/media

It has couple of files which are points of your interest: AudioManager.java

AudioService.java

IRemoteControlClient.aidl

IRemoteControlDisplay.aidl

Audio manager has public method, which isn't documented called registerRemoteControlDisplay. You should be able to access it through reflection.

Using this interface you can register an object which implements IRemoteControlDisplay (another undocumented interface) and you should be able to control player through this object.

Victor Ronin
  • 22,758
  • 18
  • 92
  • 184
  • 1
    Given how little time there is left this'll have to do! Haven't had the time to try it out, but you've certainly given me hope that it's possible. – Frans Sep 07 '12 at 13:05
5

Try this

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);
        Bitmap AlbumArt=BitmapFactory.decodeResource(getResources(), R.drawable.alislahthumbmain);
        mIslahReceiverComponent=new ComponentName(this,AlIslahReceiver.class.getName());
audioManager.registerMediaButtonEventReceiver(mIslahReceiverComponent);
        Intent mediaButtonIntent=new Intent(Intent.ACTION_MEDIA_BUTTON);
        mediaButtonIntent.setComponent(mIslahReceiverComponent);
        PendingIntent mediaPendingIntent=PendingIntent.getBroadcast(getApplicationContext(),
                0,mediaButtonIntent,0);
        RemoteControlClient mRemoteControlClient=new RemoteControlClient(mediaPendingIntent);
        mRemoteControlClient.editMetadata(true)
        .putString(MediaMetadataRetriever.METADATA_KEY_TITLE,AlIslahApplication.getStreamTitle())
        .putBitmap(100,AlbumArt)
        .apply();
        mRemoteControlClient.setPlaybackState(
                RemoteControlClient.PLAYSTATE_PLAYING);
        mRemoteControlClient.setTransportControlFlags(
               RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE|
                RemoteControlClient.FLAG_KEY_MEDIA_STOP);
        audioManager.registerRemoteControlClient(mRemoteControlClient);
Stephan
  • 7,360
  • 37
  • 46
itsmewajid
  • 186
  • 2
  • 9
  • 2
    The question is not how to use the `RemoteControlClient`. – Stephan Sep 06 '12 at 14:40
  • As Stephan said, the question isn't how to implement a RemoteControlClient, it's how to find and control an already existing RemoteControlClient. – Frans Mar 12 '13 at 22:21
3

You can't get the same requests to show the display that the lock screen does, but you can certainly trigger the same events that the buttons on this screen do with Broadcast Intents.

The action in question is ACTION_MEDIA_BUTTON and you should attach a KeyEvent with the appropriate keyCode to do what you want.

Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(
            KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
sendBroadcast(intent);

This will do the same thing as pressing the play/pause button on the lockscreen. You can do this with the other KeyEvent keycodes that make sense (KEYCODE_MEDIA_NEXT, etc...), although you won't know what the currently playing track has registered itself as supporting, while the lockscreen does.

chrisrhoden
  • 464
  • 3
  • 6
  • Actually, I'm not sure this does the same thing. Maybe we could somewhat imitate the results of play/pause, next and maybe previous, but the communication isn't the same. Using this method the commands MIGHT work, but maybe not. Plus, as I understand it this needs to have the specific process to send the intent to, we can't do a system wide broadcast. – Frans Mar 12 '13 at 22:16
  • I am not sure what you're basing your information on, but you're wrong. This is using the same communication protocol as the lockscreen does, which is to say, broadcast intents. – chrisrhoden Mar 22 '13 at 17:13
  • https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/AudioManager.java#L2031 There's the source where the intent is built on registering for lock screen controls. The only thing you don't get is the component name, but again, the transport method is exactly the same. – chrisrhoden Mar 22 '13 at 17:22
  • Would you mind walking me through how it works? The lockscreen is probably an implementation of IRemoteControlDisplay, registered here https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/AudioManager.java#L2166. And for sending the metadata and current play state the media player registers RemoteControlClient through https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/AudioManager.java#L2125. Here's where I've been stuck for a while, I'm not quite sure how to implement this. – Frans Mar 22 '13 at 21:52
  • How does the IRemoteControlDisplay implementation know where to send the intents? If we assume that's how it controls the media player. – Frans Mar 22 '13 at 21:52
  • It uses a PendingIntent of a BroadcastIntent. When an application registers itself as a RemoteControlClient, it passes to the method a BroadcastReceiver that has been registered to receive the MEDIA_BUTTON action. It also registers an intent that points at the specific component. – chrisrhoden Mar 23 '13 at 23:01
  • Since Android 2.2, it has been possible to register a specific BroadcastReceiver at runtime to be the sole recipient of BroadcastIntents carrying the MEDIA_BUTTON action. What that means is that if you send out an intent with the MEDIA_BUTTON action, it will go to the component that has registered as the sole recipient of such intents most recently. RemoteControlClient registration process requires that you have already registered the same BroadcastReceiver component in this way. Look at the 3rd line of the example: http://developer.android.com/reference/android/media/RemoteControlClient.html – chrisrhoden Mar 23 '13 at 23:08
  • You don't need to take my word for it, but don't spread FUD. If you tried it (which I have), you would find that it works. Saying, "Maybe we could somewhat imitate the results of play/pause, next and maybe previous," as though you have some great insight into this might confuse other users. This solution imitates the method that the RemoteControlClient uses. The big problem with what is happening here is that you're treating Android as a black box. The vast majority of the functionality in the OS is written using the same SDK that you have access to. BroadcastIntents are important. Learn 'em. – chrisrhoden Mar 24 '13 at 12:31
  • Thank you for a good walkthrough! I apologize if I'm spreading FUD, not my intention. Yes, I'm treating it as a black box and I'm basing some of my statements on things freelancers have told me. I work as a developer but I'm a novice when it comes to Android, as I haven't had the time to learn it. I suppose I'll have to learn some more about it. – Frans Mar 25 '13 at 09:45
2

For anyone stumbling on this question post KitKat release, you can now use the RemoteController, which connects to RemoteControlClients and allows you to control them.

ter0
  • 992
  • 8
  • 12
0

You would have to implement the IRemoteControl*.aidl interface in your app and the apps (like Spotify) would have to register itself to your app, which is not the case yet. They register themself to the AudioManager. So NO, you're not able to catch those RemoteClient registrations without either modifying the apps (Spotify, etc..) or modifying the Android system so your app could grab the RemoteClients and their data.

chrulri
  • 1,822
  • 14
  • 16
  • Ah, what a pity. Are there any other ways you could generally control a music player? Or does it have to be special solutions for every player? Not thinking about the default music players. – Frans Sep 06 '12 at 15:20