I have problem with this code:
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.KITKAT)
public class NotificationRemoteControllerService extends NotificationService implements OnClientUpdateListenerExtended {
private static final String TAG = "NRemoteContollerService";
public static boolean isMusicPlaying = false;
MusicPlaybackState currenTplaybackState;
// REMOTE CONTROLLER
private int currentPlaybackState;
private SimpleMusicMetadata simpleMusicMetadata;
private RemoteController remoteController;
private static String getStringMetadata(RemoteController.MetadataEditor metadataEditor, int key) {
return metadataEditor.getString(key, METADATA_DEFAULT_VALUE);
}
public static boolean isEnabled(Context context) {
ComponentName cn = new ComponentName(context, NotificationRemoteControllerService.class);
String flat = Settings.Secure.getString(context.getContentResolver(), "enabled_notification_listeners");
return flat != null && flat.contains(cn.flattenToString());
}
@Override
public void onCreate() {
super.onCreate();
remoteController = new RemoteController(this, this);
}
RemoteController.OnClientUpdateListener myListener = new RemoteController.OnClientUpdateListener() {
@Override
public void onClientChange(boolean b) {
}
@Override
public void onClientPlaybackStateUpdate(int i) {
}
@Override
public void onClientPlaybackStateUpdate(int i, long l, long l1, float v) {
}
@Override
public void onClientTransportControlUpdate(int i) {
}
@Override
public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) {
}
}
/* ----------------------------------------------------------------------------------------
REMOTE CONTROLLER
---------------------------------------------------------------------------------------- */
@Override
public void onDestroy() {
disableRemoteController();
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int artworkWidth;
int artworkHeight;
if (intent != null) {
artworkWidth = intent.getIntExtra(EXTRA_ALBUM_COVER_WIDTH,
DEFAULT_ATTRIBUTE_ALBUM_COVER_WIDTH);
artworkHeight = intent.getIntExtra(EXTRA_ALBUM_COVER_HEIGHT,
DEFAULT_ATTRIBUTE_ALBUM_COVER_HEIGHT);
} else {
artworkWidth = DEFAULT_ATTRIBUTE_ALBUM_COVER_WIDTH;
artworkHeight = DEFAULT_ATTRIBUTE_ALBUM_COVER_HEIGHT;
}
Log.e(TAG, "isMusicPlaying " + Boolean.toString(isMusicPlaying));
if (simpleMusicMetadata == null) Log.e(TAG, "simpleMusic is Null!!");
if (isMusicPlaying && simpleMusicMetadata != null) {
Log.e(TAG, "onStartCommand: eventbus.get " + simpleMusicMetadata.getTitle());
EventBus.getDefault().post(simpleMusicMetadata);
} else {
remoteController.setArtworkConfiguration(artworkWidth, artworkHeight);
enableRemoteController();
}
if (currenTplaybackState != null) {
Log.e(TAG, "PLAY_STATE" + currenTplaybackState.name());
EventBus.getDefault().post(currenTplaybackState);
}
return START_STICKY;
}
private void postUpdateMetadata(RemoteController.MetadataEditor metadataEditor) {
String title = getStringMetadata(metadataEditor, METADATA_KEY_TITLE);
String artist = getStringMetadata(metadataEditor, METADATA_KEY_ARTIST);
String album = getStringMetadata(metadataEditor, METADATA_KEY_ALBUM);
Bitmap artwork = metadataEditor.getBitmap(MediaMetadataEditor.BITMAP_KEY_ARTWORK, null);
simpleMusicMetadata = new SimpleMusicMetadata(title, artist, album, artwork);
EventBus.getDefault().post(simpleMusicMetadata);
}
private void enableRemoteController() {
if (!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
if (remoteController != null) {
try {
AudioManager manager = ((AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE));
if (!manager.registerRemoteController(remoteController)) {
Log.e(TAG, "Failed to register remoteController.");
}
} catch (Exception e) {
Log.e(TAG, "enableRemoteController EXCEPTION");
Log.e(TAG, e.getLocalizedMessage());
Log.e(TAG, e.getMessage());
}
}
setSynchronizationMode(RemoteController.POSITION_SYNCHRONIZATION_NONE);
currentPlaybackState = PLAYBACK_INVALID_STATE;
}
private void setSynchronizationMode(int sync) {
if ((sync != RemoteController.POSITION_SYNCHRONIZATION_NONE) && (sync != RemoteController.POSITION_SYNCHRONIZATION_CHECK)) {
throw new IllegalArgumentException("Unknown synchronization mode " + sync);
}
Class<?> iRemoteControlDisplayClass;
try {
iRemoteControlDisplayClass = Class.forName("android.media.IRemoteControlDisplay");
} catch (ClassNotFoundException e1) {
throw new RuntimeException("Class IRemoteControlDisplay doesn't exist, can't access it with reflection");
}
Method remoteControlDisplayWantsPlaybackPositionSyncMethod;
try {
remoteControlDisplayWantsPlaybackPositionSyncMethod = AudioManager.class.getDeclaredMethod("remoteControlDisplayWantsPlaybackPositionSync", iRemoteControlDisplayClass, boolean.class);
remoteControlDisplayWantsPlaybackPositionSyncMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() doesn't exist, can't access it with reflection");
}
Object rcDisplay;
Field rcDisplayField;
try {
rcDisplayField = RemoteController.class.getDeclaredField("mRcd");
rcDisplayField.setAccessible(true);
rcDisplay = rcDisplayField.get(remoteController);
} catch (NoSuchFieldException e) {
throw new RuntimeException("Field mRcd doesn't exist, can't access it with reflection");
} catch (IllegalAccessException e) {
throw new RuntimeException("Field mRcd can't be accessed - access denied");
} catch (IllegalArgumentException e) {
throw new RuntimeException("Field mRcd can't be accessed - invalid argument");
}
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
try {
remoteControlDisplayWantsPlaybackPositionSyncMethod.invoke(am, iRemoteControlDisplayClass.cast(rcDisplay), true);
} catch (IllegalAccessException e) {
throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() invocation failure - access denied");
} catch (IllegalArgumentException e) {
throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() invocation failure - invalid arguments");
} catch (InvocationTargetException e) {
throw new RuntimeException("Method remoteControlDisplayWantsPlaybackPositionSync() invocation failure - invalid invocation target");
}
}
private void disableRemoteController() {
EventBus.getDefault().unregister(this);
if (remoteController != null) {
((AudioManager) getApplicationContext().getSystemService(AUDIO_SERVICE))
.unregisterRemoteController(remoteController);
}
}
private boolean sendMediaKeyEvent(int key) {
try {
KeyEvent downKeyEvent = new KeyEvent(KeyEvent.ACTION_DOWN, key);
KeyEvent upKeyEvent = new KeyEvent(KeyEvent.ACTION_UP, key);
boolean downResult = remoteController.sendMediaKeyEvent(downKeyEvent);
boolean upResult = remoteController.sendMediaKeyEvent(upKeyEvent);
return downResult && upResult;
} catch (NullPointerException e) {
Log.e(TAG, "remoteController == null");
return false;
}
}
private boolean sendNextKeyEvent() {
return sendMediaKeyEvent(MUSIC_KEY_NEXT);
}
private boolean sendPreviousKeyEvent() {
return sendMediaKeyEvent(MUSIC_KEY_PREVIOUS);
}
private boolean sendPlayKeyEvent() {
return sendMediaKeyEvent(MUSIC_KEY_PLAY);
}
private boolean sendPauseKeyEvent() {
return sendMediaKeyEvent(MUSIC_KEY_PAUSE);
}
@SuppressWarnings("unused")
public void onEvent(MusicAction action) {
switch (action) {
case PREVIOUS:
sendPreviousKeyEvent();
break;
case NEXT:
sendNextKeyEvent();
break;
case PLAY_PAUSE:
if (isMusicPlaying) {
sendPauseKeyEvent();
} else {
sendPlayKeyEvent();
}
break;
}
}
public static int state;
private void updatePlaybackState(int state) {
MusicPlaybackState playbackState;
if (state == STATE_PLAYING
|| state == STATE_BUFFERING
|| state == STATE_FAST_FORWARDING
|| state == STATE_REWINDING
|| state == STATE_SKIPPING_TO_NEXT) {
isMusicPlaying = true;
playbackState = MusicPlaybackState.PLAYING;
} else if (state == STATE_PAUSED) {
isMusicPlaying = false;
playbackState = MusicPlaybackState.PAUSED;
} else {
isMusicPlaying = false;
playbackState = MusicPlaybackState.STOPPED;
}
Log.e(TAG, "playing state: " + playbackState.name());
EventBus.getDefault().post(playbackState);
currenTplaybackState = playbackState;
currentPlaybackState = state;
}
@Override
public void onClientSessionEvent(String s, Bundle bundle) {
}
@Override
public void onClientChange(boolean noClient) {
Log.e(TAG, "onClientChange: " + Boolean.toString(noClient) + ", " + Boolean.toString(isMusicPlaying));
if (!noClient && isMusicPlaying) {
EventBus.getDefault().post(VisibilityBus.VISIBLE);
} else {
EventBus.getDefault().post(VisibilityBus.GONE);
}
}
@Override
public void onClientPlaybackStateUpdate(int i) {
Log.e(TAG, "onClientPlaybackStateUpdate: " + i);
updatePlaybackState(i);
}
@Override
public void onClientPlaybackStateUpdate(int i, long l, long l1, float v) {
Log.e(TAG, "onClientPlaybackStateUpdate: " + i);
updatePlaybackState(i);
}
@Override
public void onClientTransportControlUpdate(int i) {
}
@Override
public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) {
postUpdateMetadata(metadataEditor);
}
}
problem:
AbstractMethodError: abstract method "void android.media.RemoteController$OnClientUpdateListener.onClientSessionEvent
It occures on some Samsung phones with Android 5.x. I was trying to change to
remoteController = new RemoteController(this, new RemoteController.OnClientUpdateListener() {
public void onClientSessionEvent(String string, Bundle bundle) { }
@Override
public void onClientChange(boolean b) {
}
@Override
public void onClientPlaybackStateUpdate(int i) {
}
@Override
public void onClientPlaybackStateUpdate(int i, long l, long l1, float v) {
}
@Override
public void onClientTransportControlUpdate(int i) {
}
@Override
public void onClientMetadataUpdate(RemoteController.MetadataEditor metadataEditor) {
}
});
}
but then I have "Missing permission to control media". How I have to add this method to make it work?
Add this permission to your AndroidManifest.xml
According to the documentation: