Android Open Source - kure-music-player Remote Control Client Compat






From Project

Back to project page kure-music-player.

License

The source code is released under:

GNU General Public License

If you think the Android project kure-music-player listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2011 The Android Open Source Project
 */*from   w  ww.  ja  va 2 s  .  c  o m*/
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.kure.musicplayer.external;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import android.app.PendingIntent;
import android.graphics.Bitmap;
import android.os.Looper;
import android.util.Log;







//NOTE (READ THIS PLEASE):
//
//This file was directly copied from the Android
//sample project "Random Music Player".
//
//I use it to implement the Lock Screen "Widget"
//(control the music player on the lock-screen)
//
//Take a look at my service that plays songs to
//see how I use this class.








/**
 * Sends info to a thing that has remote media
 * controls (such as the Lock-Screen Widget).
 *
 * A remote control client object is associated with a
 * media button event receiver.
 *
 * This event receiver must have been previously registered with
 * `AudioManager#registerMediaButtonEventReceiver` before the
 * `RemoteControlClient` can be registered through
 * `AudioManager#registerRemoteControlClient`.
 *
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class RemoteControlClientCompat {

  // Used for debugging
  private static final String TAG = "RemoteControlCompat";

  private static Class sRemoteControlClientClass;

  // RCC short for RemoteControlClient
  private static Method sRCCEditMetadataMethod;
  private static Method sRCCSetPlayStateMethod;
  private static Method sRCCSetTransportControlFlags;

  private static boolean sHasRemoteControlAPIs = false;

  static {
    try {
      ClassLoader classLoader = RemoteControlClientCompat.class.getClassLoader();

      sRemoteControlClientClass = getActualRemoteControlClientClass(classLoader);

      // dynamically populate the playstate and flag values
      // in case they change in future versions.
      for (Field field : RemoteControlClientCompat.class.getFields()) {
        try {
          Field realField  = sRemoteControlClientClass.getField(field.getName());
          Object realValue = realField.get(null);

          field.set(null, realValue);

        } catch (NoSuchFieldException e) {
          Log.w(TAG, "Could not get real field: " + field.getName());

        } catch (IllegalArgumentException e) {
          Log.w(TAG, "Error trying to pull field value for: " + field.getName()
              + " " + e.getMessage());

        } catch (IllegalAccessException e) {
          Log.w(TAG, "Error trying to pull field value for: " + field.getName()
              + " " + e.getMessage());
        }
      }

      // get the required public methods on RemoteControlClient
      sRCCEditMetadataMethod = sRemoteControlClientClass.getMethod("editMetadata",
          boolean.class);
      sRCCSetPlayStateMethod = sRemoteControlClientClass.getMethod("setPlaybackState",
          int.class);
      sRCCSetTransportControlFlags = sRemoteControlClientClass.getMethod(
          "setTransportControlFlags", int.class);

      sHasRemoteControlAPIs = true;

    } catch (ClassNotFoundException e) {
      // Silently fail when running on an OS before ICS.
    } catch (NoSuchMethodException e) {
      // Silently fail when running on an OS before ICS.
    } catch (IllegalArgumentException e) {
      // Silently fail when running on an OS before ICS.
    } catch (SecurityException e) {
      // Silently fail when running on an OS before ICS.
    }
  }

  public static Class getActualRemoteControlClientClass(ClassLoader classLoader)
      throws ClassNotFoundException {

    return classLoader.loadClass("android.media.RemoteControlClient");
  }

  private Object mActualRemoteControlClient;

  public RemoteControlClientCompat(PendingIntent pendingIntent) {

    if (!sHasRemoteControlAPIs) {
      return;
    }
    try {
      mActualRemoteControlClient =
          sRemoteControlClientClass.getConstructor(PendingIntent.class)
          .newInstance(pendingIntent);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public RemoteControlClientCompat(PendingIntent pendingIntent, Looper looper) {

    if (!sHasRemoteControlAPIs) {
      return;
    }

    try {
      mActualRemoteControlClient =
          sRemoteControlClientClass.getConstructor(PendingIntent.class, Looper.class)
          .newInstance(pendingIntent, looper);
    } catch (Exception e) {
      Log.e(TAG, "Error creating new instance of " + sRemoteControlClientClass.getName(), e);
    }
  }

  /**
   * Class used to modify metadata in a `RemoteControlClient` object.
   *
   * Use `RemoteControlClient#editMetadata` to create an instance of an
   * editor, on which you set the metadata for the `RemoteControlClient` instance.
   *
   * Once all the information has been set, use `#apply()` to make it
   * the new metadata that should be displayed for the associated client.
   *
   * Once the metadata has been "applied", you cannot reuse
   * this instance of the MetadataEditor.
   */
  public class MetadataEditorCompat {

    private Method mPutStringMethod;
    private Method mPutBitmapMethod;
    private Method mPutLongMethod;
    private Method mClearMethod;
    private Method mApplyMethod;

    private Object mActualMetadataEditor;

    /**
     * The metadata key for the content artwork / album art.
     */
    public final static int METADATA_KEY_ARTWORK = 100;

    private MetadataEditorCompat(Object actualMetadataEditor) {
      if (sHasRemoteControlAPIs && actualMetadataEditor == null) {
        throw new IllegalArgumentException("Remote Control API's exist, " +
            "should not be given a null MetadataEditor");
      }
      if (sHasRemoteControlAPIs) {
        Class metadataEditorClass = actualMetadataEditor.getClass();

        try {
          mPutStringMethod = metadataEditorClass.getMethod("putString",
              int.class, String.class);

          mPutBitmapMethod = metadataEditorClass.getMethod("putBitmap",
              int.class, Bitmap.class);

          mPutLongMethod = metadataEditorClass.getMethod("putLong",
              int.class, long.class);

          mClearMethod = metadataEditorClass.getMethod("clear", new Class[]{});
          mApplyMethod = metadataEditorClass.getMethod("apply", new Class[]{});

        } catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
      }
      mActualMetadataEditor = actualMetadataEditor;
    }

    /**
     * Adds textual information to be displayed.
     *
     * Note that none of the information added after {@code apply()}
     * has been called, will be displayed.
     *
     * @param key The identifier of a the metadata field to set. Valid values are
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER}.
     *
     * @param value The text for the given key, or {@code null} to signify
     *        there is no valid information for the field.
     *
     * @return Returns a reference to the same MetadataEditor object,
     *         so you can chain put calls together.
     */
    public MetadataEditorCompat putString(int key, String value) {
      if (sHasRemoteControlAPIs) {
        try {
          mPutStringMethod.invoke(mActualMetadataEditor, key, value);
        } catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
      }
      return this;
    }

    /**
     * Sets the album / artwork picture to be displayed on the remote control.
     *
     * @param key    The identifier of the bitmap to set.
     *               The only valid value is {@link #METADATA_KEY_ARTWORK}
     * @param bitmap The bitmap for the artwork, or null if there isn't any.
     *
     * @return Returns a reference to the same MetadataEditor object,
     *         so you can chain put calls together.
     *
     * @throws IllegalArgumentException
     *
     * @see android.graphics.Bitmap
     */
    public MetadataEditorCompat putBitmap(int key, Bitmap bitmap) {
      if (sHasRemoteControlAPIs) {
        try {
          mPutBitmapMethod.invoke(mActualMetadataEditor, key, bitmap);

        } catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
      }
      return this;
    }

    /**
     * Adds numerical information to be displayed.
     *
     * Note that none of the information added after {@link #apply()} has been called,
     * will be displayed.
     *
     * @param key the identifier of a the metadata field to set. Valid values are
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER},
     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION} (with a value
     *      expressed in milliseconds).
     *
     * @param value The long value for the given key
     * @return Returns a reference to the same MetadataEditor object, so you can chain put
     *      calls together.
     * @throws IllegalArgumentException
     */
    public MetadataEditorCompat putLong(int key, long value) {
      if (sHasRemoteControlAPIs) {
        try {
          mPutLongMethod.invoke(mActualMetadataEditor, key, value);
        } catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
      }
      return this;
    }

    /**
     * Clears all the metadata that has been set since the MetadataEditor instance was
     * created with {@link android.media.RemoteControlClient#editMetadata(boolean)}.
     */
    public void clear() {
      if (sHasRemoteControlAPIs) {
        try {
          mClearMethod.invoke(mActualMetadataEditor, (Object[]) null);
        } catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
      }
    }

    /**
     * Associates all the metadata that has been set since the MetadataEditor instance was
     * created with {@link android.media.RemoteControlClient#editMetadata(boolean)}, or since
     * {@link #clear()} was called, with the RemoteControlClient. Once "applied", this
     * MetadataEditor cannot be reused to edit the RemoteControlClient's metadata.
     */
    public void apply() {
      if (sHasRemoteControlAPIs) {
        try {
          mApplyMethod.invoke(mActualMetadataEditor, (Object[]) null);
        } catch (Exception e) {
          throw new RuntimeException(e.getMessage(), e);
        }
      }
    }
  }

  /**
   * Creates a {@link android.media.RemoteControlClient.MetadataEditor}.
   * @param startEmpty Set to false if you want the MetadataEditor to contain the metadata that
   *     was previously applied to the RemoteControlClient, or true if it is to be created empty.
   * @return a new MetadataEditor instance.
   */
  public MetadataEditorCompat editMetadata(boolean startEmpty) {
    Object metadataEditor;
    if (sHasRemoteControlAPIs) {
      try {
        metadataEditor = sRCCEditMetadataMethod.invoke(mActualRemoteControlClient,
            startEmpty);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    } else {
      metadataEditor = null;
    }
    return new MetadataEditorCompat(metadataEditor);
  }

  /**
   * Sets the current playback state.
   * @param state The current playback state, one of the following values:
   *       {@link android.media.RemoteControlClient#PLAYSTATE_STOPPED},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_PAUSED},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_PLAYING},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_FAST_FORWARDING},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_REWINDING},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_SKIPPING_FORWARDS},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_SKIPPING_BACKWARDS},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_BUFFERING},
   *       {@link android.media.RemoteControlClient#PLAYSTATE_ERROR}.
   */
  public void setPlaybackState(int state) {
    if (sHasRemoteControlAPIs) {
      try {
        sRCCSetPlayStateMethod.invoke(mActualRemoteControlClient, state);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Sets the flags for the media transport control buttons that this client supports.
   * @param transportControlFlags A combination of the following flags:
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PREVIOUS},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_REWIND},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY_PAUSE},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PAUSE},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_STOP},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_FAST_FORWARD},
   *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_NEXT}
   */
  public void setTransportControlFlags(int transportControlFlags) {
    if (sHasRemoteControlAPIs) {
      try {
        sRCCSetTransportControlFlags.invoke(mActualRemoteControlClient,
            transportControlFlags);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  }

  public final Object getActualRemoteControlClientObject() {
    return mActualRemoteControlClient;
  }
}




Java Source Code List

com.kure.musicplayer.MusicController.java
com.kure.musicplayer.NotificationMusic.java
com.kure.musicplayer.NotificationSimple.java
com.kure.musicplayer.Settings.java
com.kure.musicplayer.activities.ActivityListAlbums.java
com.kure.musicplayer.activities.ActivityListSongs.java
com.kure.musicplayer.activities.ActivityMaster.java
com.kure.musicplayer.activities.ActivityMenuAlbum.java
com.kure.musicplayer.activities.ActivityMenuArtist.java
com.kure.musicplayer.activities.ActivityMenuGenre.java
com.kure.musicplayer.activities.ActivityMenuMain.java
com.kure.musicplayer.activities.ActivityMenuMusic.java
com.kure.musicplayer.activities.ActivityMenuPlaylist.java
com.kure.musicplayer.activities.ActivityMenuSettings.java
com.kure.musicplayer.activities.ActivityMenuYear.java
com.kure.musicplayer.activities.ActivityNowPlaying.java
com.kure.musicplayer.activities.ActivityQuit.java
com.kure.musicplayer.activities.XXX.java
com.kure.musicplayer.adapters.AdapterSong.java
com.kure.musicplayer.external.RemoteControlClientCompat.java
com.kure.musicplayer.external.RemoteControlHelper.java
com.kure.musicplayer.helpers.SingleToast.java
com.kure.musicplayer.model.Playlist.java
com.kure.musicplayer.model.SongList.java
com.kure.musicplayer.model.Song.java
com.kure.musicplayer.services.ServicePlayMusic.java
com.kure.musicplayer.services.ServiceScrobbleMusic.java
com.kure.musicplayer.kMP.java