I'm trying to extend the functionality of the Wired Mic Remote Button through a Service and Receiver that sits on top of the Google Play Music App and communicates with it through broadcasts. I'm on ICS with a Google Nexus S.
The issue I have is my code works great once the MusicPlaybackService is running, which is not always the case. How do I start this service without showing any UI (without the user knowing). My code has the following definitions:
public static final String SERVICECMD = "com.android.music.musicservicecommand";
public static final String CMDNAME = "command";
public static final String CMDTOGGLEPAUSE = "togglepause";
public static final String TOGGLEPAUSE_ACTION = "com.android.music.musicservicecommand.togglepause";
I have tried the following options:
1) Based off this SO question. I'm not sure whether about SERVICECMD, as the question states I should use "com.android.music.musicservicecommand" though for ICS I believe the package names have changed.
Intent i = new Intent(SERVICECMD);
i.putExtra(CMDNAME, CMDTOGGLEPAUSE);
sendBroadcast(i);
I have also tried replacing SERVICECMD with TOGGLEPAUSE_ACTION.
2) From this android project issue.
Intent musicIntent = new Intent();
musicIntent.setClassName("com.google.android.music", "com.google.android.music.MusicPlaybackService");
musicIntent.setAction(TOGGLEPAUSE_ACTION);
musicIntent.putExtra(CMDNAME, CMDTOGGLEPAUSE); // or "next" or "previous"
sendBroadcast(musicIntent);
3) This code crashes with the error below. I'm not sure how to go further with this option.
Caused by: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.google.android.music/com.google.android.music.MusicPlaybackService}; have you declared this activity in your AndroidManifest.xml?
Intent intent = new Intent();
intent.putExtra(CMDNAME, CMDTOGGLEPAUSE);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClassName("com.google.android.music", "com.google.android.music.MusicPlaybackService");
startActivity(intent);
4) I've noticed that when the headset is removed from my phone, the MusicPlaybackService is started because it is responding to the Intent.ACTION_HEADSET_PLUG broadcast that is picked up by WiredAccessoryObserver. I tried duplicating that broadcast in my code using the values shown in LogCat.
Intent intent = new Intent(Intent.ACTION_HEADSET_PLUG);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra("state", 0);
intent.putExtra("name", "h2w");
intent.putExtra("microphone", 1);
sendBroadcast(intent);
I'm really looking for a method that works all the time that just starts up the Service. I'm open to anything. I still have to try binding to the service that uses IMediaPlaybackService.aidl which is supposed to break randomly, and is not ideal. Thanks in advance for helping out.
EDIT
I tried binding to the service using the code below which threw an error:
Caused by: java.lang.SecurityException: Not allowed to bind to service Intent { cmp=com.google.android.music/.MusicPlaybackService }
In my OnCreate function
if (mPlaybackService == null) {
Intent i = new Intent();
i.setClassName("com.google.android.music","com.google.android.music.MusicPlaybackService" );
bindService(i, connection, Context.BIND_AUTO_CREATE);
}
In my class
IMediaPlaybackService mPlaybackService = null;
ServiceConnection connection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
mPlaybackService = IMediaPlaybackService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
mPlaybackService = null;
}
};
I don't think this is possible. My workaround is to let the apps own broadcastreceiver wake up the service when the button is pressed. I just request audiofocus for my app and wait til it gets lost.