Skip to content
This repository

A wrapper for the StageFright player on Android. Hate the player, not the game.

branch: master
README.md

PlayerHater

PlayerHater is an Android library for playing audio in the background of your app. You can use it for:

  • Podcasts!
  • Music!
  • Radio!

You probably shouldn't use it for:

  • Fart sounds
  • Game sound effects

There's a whole lot that PlayerHater does for you right out of the box and you can add your own functionality through the use of plugins. PlayerHater even ships with plugins that will do the following automatically:

  • Show a regular notification on on Android 2.3 or lower, a notification with player controls on Android 3.0+, and an expandable notification on Android 4.2+!
  • Handle audio focus changes in all of the weird and different ways for pre-2.2 and post-2.2 versions!
  • Add lock screen controls on Android 4.0+!
  • Pebble support!

All of this is configurable if you like, and you can write your own plugins to run alongside these.

But the best thing about PlayerHater is that there are no ServiceConnection callbacks, MediaPlayer state diagrams, or setup and teardown code for you to write. It's all taken care of in the library.

Quick Start

Important, temporary information

Everything's going into Maven Central soon using the new aar format
that's part of the new Android build system that uses Gradle. If
you're not comfortable using the sonatpe OSS snapshot server (or if
you don't know what that is) or you haven't moved to Gradle yet, you
can check out the project repository and use the files in 

legacyLibraryProject/PlayerHater

as if they were a normal android library project. They are, in fact
symlinks.

Note that doing this will require you to add entries to your
AndroidManifest.xml file, while the new build system allows us to
automatically do this for you if you're using Gradle.

Once you've imported the project into your android application and added the Service and BroadcastReceiver to your AndroidManifest.xml file, getting a handle on the player is as easy as:

import org.prx.android.playerhater.PlayerHater;

class MyApplicationActivity extends Activity {

    private PlayerHater mPlayerHater;

    @Override
    public void onResume(Bundle savedInstanceState) {
        super.onResume(savedInstanceState);
        mPlayerHater = PlayerHater.bind(this);
    }

    @Override
    public void onPause() {
        mPlayerHater.release();
    }

}

When you've bound to a PlayerHater, you're ready to start playing stuff - music, podcasts, or whatever new thing the kids are listening to these days.

The PlayerHater API

    abstract void   emptyQueue()
    Removes all songs from the queue.
    abstract int    enqueue(Song song)
    Puts a song on the end of the play queue.
    abstract int    getCurrentPosition()
    Gets the location of the playhead in milliseconds.
    abstract int    getDuration()
    Gets the duration of the currently loaded Song in milliseconds.
    abstract int    getQueueLength()
    Returns the number of items in the queue.
    abstract int    getQueuePosition()
    Returns the number of clips in the queue which are at least partially behind the playhead.
    abstract int    getState()
    Gets the state of the PlayerHater, represented as an int.
    abstract boolean    isLoading()
    Checks to see if the player is currently loading audio.
    abstract boolean    isPlaying()
    Checks to see if the player is currently playing back audio.
    abstract Song   nowPlaying()
    Gets the Song representation of the track that is currently loaded in the player.
    abstract boolean    pause()
    Pauses the player.
    abstract boolean    play(Song song, int startTime)
    Begins playback of song at startTime
    abstract boolean    play(Song song)
    Begins playback of a song at the beginning.
    abstract boolean    play(int startTime)
    Begins playback of the currently loaded Song at startTime in the track.
    abstract boolean    play()
    Begins playback of the currently loaded Song.
    abstract boolean    removeFromQueue(int position)
    Removes the element at position from the play queue.
    abstract boolean    seekTo(int startTime)
    Moves the playhead to startTime
    abstract void   setPendingIntent(PendingIntent intent)
    Sets the intent to be used by the plugins.
    abstract void   setTransportControlFlags(int transportControlFlags)
    Sets the visible buttons for plugins.
    abstract void   skip()
    Moves to the next song in the play queue.
    abstract void   skipBack()
    Moves back in the play queue.
    abstract boolean    skipTo(int position)
    Moves to a new position in the play queue.
    abstract boolean stop()
    Stops the player.

Changelog

v0.3.0

We refactored everything to make more sense and run faster. Large parts of the codebase have been written from scratch using knowledge we gained in versions 0.1.0 and 0.2.0 and many class and method names have been changed to make more sense.

0.3.0 is a breaking upgrade from 0.2.0 and is still considered beta software until a 1.0.0 release.

Highlights

  • The Service is now aggressively bound whenever you are interacting with PlayerHater. It's still released when appropriate so that Android can GC the process automatically and it will not show up in the Android Running Services list.

  • getState() will now return one of PlayerHater.IDLE, PlayerHater.PLAYING, PlayerHater.LOADING, or PlayerHater.PAUSED instead of one of the lower-level MediaPlayer states.

  • public Bundle getExtra() and public String getAlbumTitle() have been added to the Song interface. void onAlbumTitleChanged(String albumTitle) has been added to the PlayerHaterPlugin interface.

  • void onServiceStarted(IPlayerHaterBinder binder) has been removed from the PlayerHaterPlugin interface. If you need access to Service-only methods, check to see if the PlayerHater passed to onPlayerHaterLoaded() is a ServicePlayerHater, cast, and then call the methods needed.

  • Song data is loaded just in time, even across the IPC boundary. This means that if you enqueue a Song and then the return values for the various Song methods change, those changes will be propagated. Please note that if your Activity-side application is terminated the Song data will be serialized at that moment and passed across the barier to permit garbage collection.

v0.2.0

  • No service callbacks to deal with - Service is automatically started as needed when play() is called. You can immediately work with PlayerHater and all commands sent to it will be forwarded to the Service once it is started.

  • It is no longer the developer's responsibility to remember when to and when not to stop the service.

  • The service is now runnable on a separate Android process through the use of AIDL IPC.

  • Too many changes to enumerate. Refer to documentation.

0.2.0 is a breaking upgrade from 0.1.0 and is still considered beta software until a 1.0.0 release.

License

Copyright 2013 Chris Rhoden, Rebecca Nesson, Public Radio Exchange

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.
Something went wrong with that request. Please try again.