Android Open Source - PlayerHater Backgrounded Plugin






From Project

Back to project page PlayerHater.

License

The source code is released under:

Apache License

If you think the Android project PlayerHater 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 2013 Chris Rhoden, Rebecca Nesson, Public Radio Exchange
 */*from   w w  w  .  ja  va  2s.  co 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 org.prx.playerhater.plugins;

import android.app.PendingIntent;
import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

import org.prx.playerhater.PlayerHater;
import org.prx.playerhater.PlayerHaterPlugin;
import org.prx.playerhater.Song;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class BackgroundedPlugin extends HandlerThread implements
        PlayerHaterPlugin, Callback {

    private static final int SONG_CHANGED = 0;
    private static final int DURATION_CHANGED = 1;
    private static final int NEXT_TRACK_UNAVAILABLE = 2;
    private static final int NEXT_TRACK_AVAILABLE = 3;
    private static final int ART_CHANGED_URI = 4;
    private static final int ALBUM_CHANGED = 5;
    private static final int ARTIST_CHANGED = 6;
    private static final int TITLE_CHANGED = 7;
    private static final int PLAYBACK_STOPPED = 8;
    private static final int PLAYBACK_STARTED = 9;
    private static final int PLAYBACK_RESUMED = 10;
    private static final int PLAYBACK_PAUSED = 11;
    private static final int AUDIO_LOADING = 12;
    private static final int INTENT_CHANGED = 13;
    private static final int SONG_FINISHED = 14;
    private static final int SERVICE_BOUND = 15;
    private static final int PLAYER_HATER_LOADED = 16;
    private static final int SERVICE_STOPPING = 17;
    private static final int CHANGES_COMPLETE = 18;
    private static final int TRANSPORT_CONTROL_FLAGS_CHANGED = 19;
    private static final int CHANGES_COMPLETE_INTERNAL = -1;
    private static final Integer[] DEFAULT_FOREGROUND_ACTIONS = {
            CHANGES_COMPLETE, SERVICE_BOUND, PLAYER_HATER_LOADED,
            SERVICE_STOPPING};
    private final PlayerHaterPlugin mPlugin;
    private final Set<Integer> mForegroundActions;
    private TargetableHandler mHandler;

    public BackgroundedPlugin(PlayerHaterPlugin plugin) {
        this(plugin, DEFAULT_FOREGROUND_ACTIONS);
    }

    public BackgroundedPlugin(PlayerHaterPlugin plugin,
                              Integer... foregroundActions) {
        this(plugin, Looper.getMainLooper(), foregroundActions);
    }

    public BackgroundedPlugin(PlayerHaterPlugin plugin,
                              Looper foregroundLooper, Integer... foregroundActions) {
        super("BackgroundedPlugin");
        mPlugin = plugin;
        mForegroundActions = new HashSet<Integer>(
                Arrays.asList(foregroundActions));
        start();
        mHandler = new HandlerPair(this, mForegroundActions, foregroundLooper);
    }

    @Override
    public void onPlayerHaterLoaded(Context context, PlayerHater playerHater) {
        if (shouldHandleMessage(PLAYER_HATER_LOADED)) {
            mPlugin.onPlayerHaterLoaded(context, playerHater);
        } else {
            mHandler.obtainTargettedMessage(PLAYER_HATER_LOADED,
                    new LoadedObject(context, playerHater)).sendToTarget();
        }
    }

    @Override
    public void onSongChanged(Song song) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(SONG_CHANGED)) {
            mPlugin.onSongChanged(song);
        } else {
            mHandler.obtainTargettedMessage(SONG_CHANGED, song).sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onDurationChanged(int duration) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(DURATION_CHANGED)) {
            mPlugin.onDurationChanged(duration);
        } else {
            mHandler.obtainTargettedMessage(DURATION_CHANGED, duration)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAudioLoading() {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(AUDIO_LOADING)) {
            mPlugin.onAudioLoading();
        } else {
            mHandler.sendTargettedEmptyMessage(AUDIO_LOADING);
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAudioPaused() {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(PLAYBACK_PAUSED)) {
            mPlugin.onAudioPaused();
        } else {
            mHandler.sendTargettedEmptyMessage(PLAYBACK_PAUSED);
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAudioResumed() {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(PLAYBACK_RESUMED)) {
            mPlugin.onAudioResumed();
        } else {
            mHandler.sendTargettedEmptyMessage(PLAYBACK_RESUMED);
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAudioStarted() {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(PLAYBACK_STARTED)) {
            mPlugin.onAudioStarted();
        } else {
            mHandler.sendTargettedEmptyMessage(PLAYBACK_STARTED);
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAudioStopped() {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(PLAYBACK_STOPPED)) {
            mPlugin.onAudioStopped();
        } else {
            mHandler.sendTargettedEmptyMessage(PLAYBACK_STOPPED);
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onTitleChanged(String title) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(TITLE_CHANGED)) {
            mPlugin.onTitleChanged(title);
        } else {
            mHandler.obtainTargettedMessage(TITLE_CHANGED, title)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAlbumTitleChanged(String title) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(ALBUM_CHANGED)) {
            mPlugin.onAlbumTitleChanged(title);
        } else {
            mHandler.obtainTargettedMessage(ALBUM_CHANGED, title)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onPlayerHaterShutdown() {
        mHandler.removeTargettedMessages(SERVICE_STOPPING);
        if (shouldHandleMessage(SERVICE_STOPPING)) {
            mPlugin.onPlayerHaterShutdown();
        } else {
            mHandler.sendTargettedEmptyMessage(SERVICE_STOPPING);
        }
    }

    @Override
    public void onArtistChanged(String artist) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(ARTIST_CHANGED)) {
            mPlugin.onArtistChanged(artist);
        } else {
            mHandler.obtainTargettedMessage(ARTIST_CHANGED, artist)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onAlbumArtChanged(Uri url) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(ART_CHANGED_URI)) {
            mPlugin.onAlbumArtChanged(url);
        } else {
            mHandler.obtainTargettedMessage(ART_CHANGED_URI, url)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onNextSongAvailable(Song nextTrack) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(NEXT_TRACK_AVAILABLE)) {
            mPlugin.onNextSongAvailable(nextTrack);
        } else {
            mHandler.obtainTargettedMessage(NEXT_TRACK_AVAILABLE, nextTrack)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onNextSongUnavailable() {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(NEXT_TRACK_UNAVAILABLE)) {
            mPlugin.onNextSongUnavailable();
        } else {
            mHandler.sendTargettedEmptyMessage(NEXT_TRACK_UNAVAILABLE);
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onPendingIntentChanged(PendingIntent pending) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(INTENT_CHANGED)) {
            mPlugin.onPendingIntentChanged(pending);
        } else {
            mHandler.obtainTargettedMessage(INTENT_CHANGED, pending)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onSongFinished(Song song, int reason) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(SONG_FINISHED)) {
            mPlugin.onSongFinished(song, reason);
        } else {
            mHandler.obtainTargettedMessage(SONG_FINISHED, reason, 0, song)
                    .sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    @Override
    public void onTransportControlFlagsChanged(int transportControlFlags) {
        mHandler.removeTargettedMessages(CHANGES_COMPLETE_INTERNAL);
        if (shouldHandleMessage(TRANSPORT_CONTROL_FLAGS_CHANGED)) {
            mPlugin.onTransportControlFlagsChanged(transportControlFlags);
        } else {
            mHandler.obtainTargettedMessage(TRANSPORT_CONTROL_FLAGS_CHANGED,
                    transportControlFlags, 0).sendToTarget();
        }
        mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE_INTERNAL);
    }

    private boolean shouldHandleMessage(int messageId) {
        return false;
        // No. return ((Looper.myLooper() == mLooper) &&
        // mForegroundActions.contains(messageId));
    }

    @Override
    public void onChangesComplete() {
        // This is automatically handled by the thing.
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case CHANGES_COMPLETE_INTERNAL:
                if (!mHandler.hasTargettedMessages(CHANGES_COMPLETE)) {
                    mHandler.sendTargettedEmptyMessage(CHANGES_COMPLETE);
                }
                break;
            case SONG_CHANGED:
                mPlugin.onSongChanged((Song) msg.obj);
                break;
            case DURATION_CHANGED:
                mPlugin.onDurationChanged((Integer) msg.obj);
                break;
            case NEXT_TRACK_UNAVAILABLE:
                mPlugin.onNextSongUnavailable();
                break;
            case NEXT_TRACK_AVAILABLE:
                mPlugin.onNextSongAvailable((Song) msg.obj);
                break;
            case ART_CHANGED_URI:
                mPlugin.onAlbumArtChanged((Uri) msg.obj);
                break;
            case ALBUM_CHANGED:
                mPlugin.onAlbumTitleChanged((String) msg.obj);
                break;
            case ARTIST_CHANGED:
                mPlugin.onArtistChanged((String) msg.obj);
                break;
            case TITLE_CHANGED:
                mPlugin.onTitleChanged((String) msg.obj);
                break;
            case PLAYBACK_STOPPED:
                mPlugin.onAudioStopped();
                break;
            case PLAYBACK_STARTED:
                mPlugin.onAudioStarted();
                break;
            case PLAYBACK_RESUMED:
                mPlugin.onAudioResumed();
                break;
            case PLAYBACK_PAUSED:
                mPlugin.onAudioPaused();
                break;
            case AUDIO_LOADING:
                mPlugin.onAudioLoading();
                break;
            case INTENT_CHANGED:
                mPlugin.onPendingIntentChanged((PendingIntent) msg.obj);
                break;
            case SONG_FINISHED:
                mPlugin.onSongFinished((Song) msg.obj, msg.arg1);
                break;
            case PLAYER_HATER_LOADED:
                LoadedObject o = (LoadedObject) msg.obj;
                mPlugin.onPlayerHaterLoaded(o.context, o.playerHater);
                break;
            case TRANSPORT_CONTROL_FLAGS_CHANGED:
                mPlugin.onTransportControlFlagsChanged(msg.arg1);
                break;
            case CHANGES_COMPLETE:
                mPlugin.onChangesComplete();
                break;
            case SERVICE_STOPPING:
                mPlugin.onPlayerHaterShutdown();
                break;
            default:
                return false;
        }
        return true;
    }

    private static class LoadedObject {
        public final Context context;
        public final PlayerHater playerHater;

        public LoadedObject(Context context, PlayerHater playerHater) {
            this.context = context;
            this.playerHater = playerHater;
        }
    }

    private static class TargetableHandler extends Handler {

        public TargetableHandler() {
            super();
        }

        @SuppressWarnings("unused")
        public Message obtainTargettedMessage(int what) {
            return obtainMessage(what);
        }

        public Message obtainTargettedMessage(int what, Object obj) {
            return obtainMessage(what, obj);
        }

        public Message obtainTargettedMessage(int what, int arg1, int arg2) {
            return obtainMessage(what, arg1, arg2);
        }

        public Message obtainTargettedMessage(int what, int arg1, int arg2,
                                              Object obj) {
            return obtainMessage(what, arg1, arg2, obj);
        }

        public boolean sendTargettedEmptyMessage(int what) {
            return sendEmptyMessage(what);
        }

        public void removeTargettedMessages(int what) {
            removeMessages(what);
        }

        public boolean hasTargettedMessages(int what) {
            return hasMessages(what);
        }
    }

    private static class HandlerPair extends TargetableHandler {

        private final Callback mCallback;
        private final OtherHandler mOtherHandler;
        private final Set<Integer> mOtherActions;

        private HandlerPair(Callback callback, Set<Integer> otherLooperActions,
                            Looper otherLooper) {
            super();
            mCallback = callback;

            mOtherActions = otherLooperActions;
            mOtherHandler = new OtherHandler(otherLooper, this);
        }

        @Override
        public Message obtainTargettedMessage(int what) {
            if (mOtherActions.contains(what)) {
                return mOtherHandler.obtainMessage(what);
            }
            return obtainMessage(what);
        }

        @Override
        public Message obtainTargettedMessage(int what, Object obj) {
            if (mOtherActions.contains(what)) {
                return mOtherHandler.obtainMessage(what, obj);
            }
            return obtainMessage(what, obj);
        }

        @Override
        public Message obtainTargettedMessage(int what, int arg1, int arg2) {
            if (mOtherActions.contains(what)) {
                return mOtherHandler.obtainMessage(what, arg1, arg2);
            }
            return obtainMessage(what, arg1, arg2);
        }

        @Override
        public Message obtainTargettedMessage(int what, int arg1, int arg2,
                                              Object obj) {
            if (mOtherActions.contains(what)) {
                return mOtherHandler.obtainMessage(what, arg1, arg2, obj);
            }
            return obtainMessage(what, arg1, arg2, obj);
        }

        @Override
        public boolean sendTargettedEmptyMessage(int what) {
            if (mOtherActions.contains(what)) {
                return mOtherHandler.sendEmptyMessage(what);
            }
            return sendEmptyMessage(what);
        }

        @Override
        public void handleMessage(Message msg) {
            handleMessage(msg, false);
        }

        @Override
        public void removeTargettedMessages(int what) {
            if (mOtherActions.contains(what)) {
                mOtherHandler.removeMessages(what);
            } else {
                removeMessages(what);
            }
        }

        @Override
        public boolean hasTargettedMessages(int what) {
            if (mOtherActions.contains(what)) {
                return mOtherHandler.hasMessages(what);
            }
            return hasMessages(what);
        }

        public void handleMessage(Message msg, boolean inverted) {
            if ((inverted && !mOtherActions.contains(msg.what))
                    || (!inverted && mOtherActions.contains(msg.what))) {
                Message newMessage = obtainTargettedMessage(msg.what);
                newMessage.copyFrom(msg);
                newMessage.sendToTarget();
            } else {
                mCallback.handleMessage(msg);
            }
        }

        static class OtherHandler extends Handler {

            private final HandlerPair mHandler;

            private OtherHandler(Looper looper, HandlerPair handler) {
                super(looper);
                mHandler = handler;
            }

            @Override
            public void handleMessage(Message msg) {
                mHandler.handleMessage(msg, true);
            }

        }
    }
}




Java Source Code List

.AbstractPlugin.java
.AudioFocusPlugin.java
.BackgroundedPlugin.java
.BoundPlayerHater.java
.BroadcastReceiver.java
.ClientPlugin.java
.Config.java
.ExpandableNotificationPlugin.java
.HeadphoneButtonGestureHelper.java
.IPlayerHater.java
.LockScreenControlsPlugin.java
.Log.java
.MediaPlayerPool.java
.NotificationPlugin.java
.OnAudioFocusChangedListener.java
.PebblePlugin.java
.PlaybackService.java
.PlayerHaterClient.java
.PlayerHaterListenerPlugin.java
.PlayerHaterListener.java
.PlayerHaterPlugin.java
.PlayerHaterServer.java
.PlayerHaterService.java
.PlayerHater.java
.PlayerStateWatcher.java
.Player.java
.PlaylistParser.java
.PlaylistSupportingPlayer.java
.PluginCollection.java
.Receiver.java
.RemoteControlButtonReceiver.java
.RemoteSong.java
.ServerPlayerHater.java
.ServicePlayerHater.java
.SongHost.java
.SongQueue.java
.Song.java
.Songs.java
.StatelyPlayer.java
.SynchronousPlayer.java
.ThreadsafePlayerHater.java
.ThreadsafeServicePlayerHater.java
.TouchableNotificationPlugin.java
org.prx.playerhater.BroadcastReceiver.java
org.prx.playerhater.PlaybackService.java
org.prx.playerhater.PlayerHaterListener.java
org.prx.playerhater.PlayerHaterPlugin.java
org.prx.playerhater.PlayerHater.java
org.prx.playerhater.Song.java
org.prx.playerhater.broadcast.HeadphoneButtonGestureHelper.java
org.prx.playerhater.broadcast.OnAudioFocusChangedListener.java
org.prx.playerhater.broadcast.Receiver.java
org.prx.playerhater.broadcast.RemoteControlButtonReceiver.java
org.prx.playerhater.ipc.ClientPlugin.java
org.prx.playerhater.ipc.PlayerHaterClient.java
org.prx.playerhater.ipc.PlayerHaterServer.java
org.prx.playerhater.ipc.ServerPlayerHater.java
org.prx.playerhater.mediaplayer.MediaPlayerPool.java
org.prx.playerhater.mediaplayer.Player.java
org.prx.playerhater.mediaplayer.PlaylistSupportingPlayer.java
org.prx.playerhater.mediaplayer.StatelyPlayer.java
org.prx.playerhater.mediaplayer.SynchronousPlayer.java
org.prx.playerhater.plugins.AbstractPlugin.java
org.prx.playerhater.plugins.AudioFocusPlugin.java
org.prx.playerhater.plugins.BackgroundedPlugin.java
org.prx.playerhater.plugins.ExpandableNotificationPlugin.java
org.prx.playerhater.plugins.LockScreenControlsPlugin.java
org.prx.playerhater.plugins.NotificationPlugin.java
org.prx.playerhater.plugins.PebblePlugin.java
org.prx.playerhater.plugins.PlayerHaterListenerPlugin.java
org.prx.playerhater.plugins.PluginCollection.java
org.prx.playerhater.plugins.ScrubbableLockScreenControlsPlugin.java
org.prx.playerhater.plugins.TouchableNotificationPlugin.java
org.prx.playerhater.service.PlayerHaterService.java
org.prx.playerhater.service.PlayerStateWatcher.java
org.prx.playerhater.songs.RemoteSong.java
org.prx.playerhater.songs.SongHost.java
org.prx.playerhater.songs.SongQueue.java
org.prx.playerhater.songs.Songs.java
org.prx.playerhater.util.Config.java
org.prx.playerhater.util.IPlayerHater.java
org.prx.playerhater.util.Log.java
org.prx.playerhater.util.PlaylistParser.java
org.prx.playerhater.wrappers.BoundPlayerHater.java
org.prx.playerhater.wrappers.ServicePlayerHater.java
org.prx.playerhater.wrappers.ThreadsafePlayerHater.java
org.prx.playerhater.wrappers.ThreadsafeServicePlayerHater.java