org.aankor.animenforadio.RadioNotification.java Source code

Java tutorial

Introduction

Here is the source code for org.aankor.animenforadio.RadioNotification.java

Source

/*
 * This file is part of AnimeNfoRadio.
 * Copyright (C) 2014  aankor
 *
 * AnimeNfoRadio is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
    
 * AnimeNfoRadio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
    
 * You should have received a copy of the GNU General Public License
 * along with AnimeNfoRadio.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.aankor.animenforadio;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.widget.RemoteViews;

import org.aankor.animenforadio.api.SongInfo;

public class RadioNotification implements ServiceConnection, AnfoService.OnSongPosChangedListener,
        AnfoService.OnSongChangeListener, AnfoService.OnPlayerStateChangedListener {
    /**
     * The unique identifier for this type of notification.
     */
    private static final String NOTIFICATION_TAG = "AnfoRadio";
    private final Context context;
    private final Service service;
    private final NotificationCompat.Builder builder;
    private RemoteViews views;
    private AnfoService.AnfoInterface anfo;
    private int lastPos;
    private SongInfo currentSong;

    public RadioNotification(final Service s) {
        this.service = s;
        this.context = s.getApplicationContext();
        Intent main = new Intent(context, Main.class);
        main.setFlags(
                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        init();

        builder = new NotificationCompat.Builder(context)
                .setContentIntent(PendingIntent.getActivity(context, 0, main, 0)).setTicker("AnimeNfo Radio Player")
                .setSmallIcon(R.drawable.ic_launcher).setOngoing(true);
    }

    void init() {
        views = new RemoteViews(context.getPackageName(), R.layout.radio_notification);
        // default action
        views.setOnClickPendingIntent(R.id.playStopButton,
                PendingIntent.getBroadcast(context, 0, new Intent(AnfoService.KEY_STOP), 0));
    }

    public void start() {
        lastPos = -200;
        context.bindService(new Intent(context, AnfoService.class), this, Context.BIND_AUTO_CREATE);
    }

    public void stop() {
        // TODO: why am I called when I am not started
        if (anfo != null) {
            anfo.removeOnSongPosChangeListener(this);
            anfo.removeOnSongChangeListener(this);
            anfo.removeOnPlayerStateChangedListener(this);
            context.unbindService(this);
            anfo = null;
        }
        cancel();
    }

    private void show(Notification notification) {
        notification.contentView = views;
        service.startForeground(NOTIFICATION_TAG.hashCode(), notification);
    }

    private void cancel() {
        service.stopForeground(true);
    }

    void updateSong(SongInfo s, long songEndTime) {
        init();
        onPlayerStateChanged(anfo.getCurrentState());
        views.setTextViewText(R.id.songNameView, s.getArtist() + " - " + s.getTitle());
        if (s.getMiniArtBmp() != null)
            views.setImageViewBitmap(R.id.albumMiniArtView, s.getMiniArtBmp());
        else
            views.setImageViewResource(R.id.albumMiniArtView, R.drawable.image_not_found);
    }

    void updateTiming(int songPosTime, String songPosTimeStr, int pos) {
        views.setProgressBar(R.id.progressView, 100, pos, false);
        views.setTextViewText(R.id.progressTextView, songPosTimeStr + " / " + currentSong.getDurationStr());
    }

    @Override
    public void onSongPosChanged(int songPosTime, String songPosTimeStr, double nowPlayingPos) {
        int pos = (int) nowPlayingPos;
        if (pos == lastPos)
            return; // don't notify if nothing is changed
        updateTiming(songPosTime, songPosTimeStr, pos);
        show(builder.build());
    }

    @Override
    public void onFetchingStarted() {

    }

    @Override
    public void onSongChanged(SongInfo s, long songEndTime, int songPosTime, String songPosTimeStr,
            double nowPlayingPos) {
        currentSong = s;
        updateSong(s, songEndTime);
        updateTiming(songPosTime, songPosTimeStr, lastPos = (int) nowPlayingPos);
        show(builder.build());
    }

    @Override
    public void onSongUnknown() {

    }

    @Override
    public void onSongUntracked() {
        init();
        onPlayerStateChanged(anfo.getCurrentState());
        views.setTextViewText(R.id.songNameView, service.getResources().getText(R.string.unknown));
        views.setImageViewResource(R.id.albumMiniArtView, R.drawable.image_not_found);
        views.setProgressBar(R.id.progressView, 100, 0, false);
        views.setTextViewText(R.id.progressTextView, "");
        show(builder.build());
    }

    @Override
    public void onAlbumArtLoaded(Bitmap artBmp, Bitmap minArtBmp) {
        if (minArtBmp != null)
            views.setImageViewBitmap(R.id.albumMiniArtView, minArtBmp);
        else
            views.setImageViewResource(R.id.albumMiniArtView, R.drawable.image_not_found);
        show(builder.build());
    }

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        anfo = (AnfoService.AnfoInterface) iBinder;
        anfo.addOnSongPosChangeListener(this);
        anfo.addOnSongChangeListener(this);
        anfo.addOnPlayerStateChangedListener(this);
        onPlayerStateChanged(anfo.getCurrentState());
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        anfo = null;
    }

    @Override
    public void onPlayerStateChanged(AnfoService.PlayerState state) {
        PendingIntent intent = null;
        views.setBoolean(R.id.playStopButton, "setEnabled", true);
        switch (state) {
        case STOPPED:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_play);
            intent = PendingIntent.getService(context, 0,
                    new Intent(context, AnfoService.class).setAction(AnfoService.START_PLAYBACK_ACTION), 0);
            builder.setOngoing(false);
            break;
        case CACHING:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_caching);
            intent = PendingIntent.getBroadcast(context, 0, new Intent(AnfoService.KEY_STOP), 0);
            builder.setOngoing(true);
            break;
        case PLAYING:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_stop);
            intent = PendingIntent.getBroadcast(context, 0, new Intent(AnfoService.KEY_STOP), 0);
            builder.setOngoing(true);
            break;
        case QUIET:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_stop);
            intent = PendingIntent.getBroadcast(context, 0, new Intent(AnfoService.KEY_STOP), 0);
            builder.setOngoing(true);
            break;
        case NO_AUDIO_FOCUS:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_no_focus);
            intent = PendingIntent.getBroadcast(context, 0, new Intent(AnfoService.KEY_STOP), 0);
            builder.setOngoing(true);
            break;
        case NO_NETWORK:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_play);
            views.setBoolean(R.id.playStopButton, "setEnabled", false);
            builder.setOngoing(false);
            break;
        case HEADSET_REMOVED:
            views.setInt(R.id.playStopButton, "setBackgroundResource", R.drawable.button_no_headset);
            intent = PendingIntent.getService(context, 0,
                    new Intent(context, AnfoService.class).setAction(AnfoService.START_PLAYBACK_ACTION), 0);
            builder.setOngoing(false);
            break;
        }
        views.setOnClickPendingIntent(R.id.playStopButton, intent);
        show(builder.build());
    }
}