diff --git a/library/src/main/java/co/mobiwise/library/radio/IRadioManager.java b/library/src/main/java/co/mobiwise/library/radio/IRadioManager.java index 0a588eb..4ce2886 100755 --- a/library/src/main/java/co/mobiwise/library/radio/IRadioManager.java +++ b/library/src/main/java/co/mobiwise/library/radio/IRadioManager.java @@ -28,4 +28,5 @@ public interface IRadioManager { void updateNotification(String singerName, String songName, int smallArt, Bitmap bigArt); -} + void enableNotification(boolean isEnabled); +} \ No newline at end of file diff --git a/library/src/main/java/co/mobiwise/library/radio/RadioManager.java b/library/src/main/java/co/mobiwise/library/radio/RadioManager.java index 5d8278e..e897f9b 100755 --- a/library/src/main/java/co/mobiwise/library/radio/RadioManager.java +++ b/library/src/main/java/co/mobiwise/library/radio/RadioManager.java @@ -16,202 +16,223 @@ */ public class RadioManager implements IRadioManager { - /** - * Logging enable/disable - */ - private static boolean isLogging = false; - - /** - * Singleton - */ - private static RadioManager instance = null; - - /** - * RadioPlayerService - */ - private static RadioPlayerService mService; - - /** - * Context - */ - private Context mContext; - - /** - * Listeners - */ - private List mRadioListenerQueue; - - /** - * Service connected/Disconnected lock - */ - private boolean isServiceConnected; - - /** - * Private constructor because of Singleton pattern - * @param mContext - */ - private RadioManager(Context mContext) { - this.mContext = mContext; - mRadioListenerQueue = new ArrayList<>(); - isServiceConnected = false; - } - - /** - * Singleton - * @param mContext - * @return - */ - public static RadioManager with(Context mContext) { - if (instance == null) - instance = new RadioManager(mContext); - return instance; - } - - /** - * get current service instance - * @return RadioPlayerService - */ - public static RadioPlayerService getService(){ - return mService; - } - - /** - * Start Radio Streaming - * @param streamURL - */ - @Override - public void startRadio(String streamURL) { - mService.play(streamURL); - } - - /** - * Stop Radio Streaming - */ - @Override - public void stopRadio() { - mService.stop(); - } - - /** - * Check if radio is playing - * @return - */ - @Override - public boolean isPlaying() { - log("IsPlaying : " + mService.isPlaying()); - return mService.isPlaying(); - } - - /** - * Register listener to listen radio service actions - * @param mRadioListener - */ - @Override - public void registerListener(RadioListener mRadioListener) { - if (isServiceConnected) - mService.registerListener(mRadioListener); - else - mRadioListenerQueue.add(mRadioListener); - } - - /** - * Unregister listeners - * @param mRadioListener - */ - @Override - public void unregisterListener(RadioListener mRadioListener) { - log("Register unregistered."); - mService.unregisterListener(mRadioListener); - } + /** + * Logging enable/disable + */ + private static boolean isLogging = false; + + /** + * Singleton + */ + private static RadioManager instance = null; + + /** + * RadioPlayerService + */ + private static RadioPlayerService mService; + + /** + * Context + */ + private Context mContext; + + /** + * Listeners + */ + private List mRadioListenerQueue; + + /** + * Service connected/Disconnected lock + */ + private boolean isServiceConnected; + + /** + * notification enabled/disabled control + */ + private boolean isEnabled = true; + /** + * Connection + */ + private ServiceConnection mServiceConnection = new ServiceConnection() { - /** - * Set/Unset Logging - * @param logging - */ @Override - public void setLogging(boolean logging) { - isLogging = logging; - } + public void onServiceConnected(ComponentName arg0, IBinder binder) { - /** - * Connect radio player service - */ - @Override - public void connect() { - log("Requested to connect service."); - Intent intent = new Intent(mContext, RadioPlayerService.class); - mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); - } + log("Service Connected."); - /** - * Disconnect radio player service - */ - @Override - public void disconnect() { - log("Service Disconnected."); - mContext.unbindService(mServiceConnection); - } + mService = ((RadioPlayerService.LocalBinder) binder).getService(); + mService.setLogging(isLogging); + isServiceConnected = true; + mService.enableNotification(isEnabled); - /** - * Update notification data - * @param singerName - * @param songName - * @param smallArt - * @param bigArt - */ - @Override - public void updateNotification(String singerName, String songName, int smallArt, int bigArt) { - if(mService != null) - mService.updateNotification(singerName, songName, smallArt, bigArt); + if (!mRadioListenerQueue.isEmpty()) { + for (RadioListener mRadioListener : mRadioListenerQueue) { + registerListener(mRadioListener); + mRadioListener.onRadioConnected(); + } + } } - /** - * Update notification data - * @param singerName - * @param songName - * @param smallArt - * @param bigArt - */ @Override - public void updateNotification(String singerName, String songName, int smallArt, Bitmap bigArt) { - if(mService != null) - mService.updateNotification(singerName, songName, smallArt, bigArt); - } - - /** - * Connection - */ - private ServiceConnection mServiceConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName arg0, IBinder binder) { - - log("Service Connected."); - - mService = ((RadioPlayerService.LocalBinder) binder).getService(); - mService.setLogging(isLogging); - isServiceConnected = true; - - if (!mRadioListenerQueue.isEmpty()) { - for (RadioListener mRadioListener : mRadioListenerQueue) { - registerListener(mRadioListener); - mRadioListener.onRadioConnected(); - } - } - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - } - }; - - /** - * Logger - * @param log - */ - private void log(String log) { - if (isLogging) - Log.v("RadioManager", "RadioManagerLog : " + log); + public void onServiceDisconnected(ComponentName arg0) { } + }; + + /** + * Private constructor because of Singleton pattern + * + * @param mContext + */ + private RadioManager(Context mContext) { + this.mContext = mContext; + mRadioListenerQueue = new ArrayList<>(); + isServiceConnected = false; + } + + /** + * Singleton + * + * @param mContext + * @return + */ + public static RadioManager with(Context mContext) { + if (instance == null) + instance = new RadioManager(mContext); + return instance; + } + + /** + * get current service instance + * + * @return RadioPlayerService + */ + public static RadioPlayerService getService() { + return mService; + } + + /** + * Start Radio Streaming + * + * @param streamURL + */ + @Override + public void startRadio(String streamURL) { + mService.play(streamURL); + } + + /** + * Stop Radio Streaming + */ + @Override + public void stopRadio() { + mService.stop(); + } + + /** + * Check if radio is playing + * + * @return + */ + @Override + public boolean isPlaying() { + log("IsPlaying : " + mService.isPlaying()); + return mService.isPlaying(); + } + + /** + * Register listener to listen radio service actions + * + * @param mRadioListener + */ + @Override + public void registerListener(RadioListener mRadioListener) { + if (isServiceConnected) + mService.registerListener(mRadioListener); + else + mRadioListenerQueue.add(mRadioListener); + } + + /** + * Unregister listeners + * + * @param mRadioListener + */ + @Override + public void unregisterListener(RadioListener mRadioListener) { + log("Register unregistered."); + mService.unregisterListener(mRadioListener); + } + + /** + * Set/Unset Logging + * + * @param logging + */ + @Override + public void setLogging(boolean logging) { + isLogging = logging; + } + + /** + * Connect radio player service + */ + @Override + public void connect() { + log("Requested to connect service."); + Intent intent = new Intent(mContext, RadioPlayerService.class); + mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); + } + + /** + * Disconnect radio player service + */ + @Override + public void disconnect() { + log("Service Disconnected."); + mContext.unbindService(mServiceConnection); + } + + /** + * Update notification data + * + * @param singerName + * @param songName + * @param smallArt + * @param bigArt + */ + @Override + public void updateNotification(String singerName, String songName, int smallArt, int bigArt) { + if (mService != null && isEnabled) + mService.updateNotification(singerName, songName, smallArt, bigArt); + } + + /** + * Update notification data + * + * @param singerName + * @param songName + * @param smallArt + * @param bigArt + */ + @Override + public void updateNotification(String singerName, String songName, int smallArt, Bitmap bigArt) { + if (mService != null && isEnabled) + mService.updateNotification(singerName, songName, smallArt, bigArt); + } + + @Override + public void enableNotification(boolean isEnabled) { + this.isEnabled = isEnabled; + } + + /** + * Logger + * + * @param log + */ + private void log(String log) { + if (isLogging) + Log.v("RadioManager", "RadioManagerLog : " + log); + } } diff --git a/library/src/main/java/co/mobiwise/library/radio/RadioPlayerService.java b/library/src/main/java/co/mobiwise/library/radio/RadioPlayerService.java index ca91125..a74bb2f 100755 --- a/library/src/main/java/co/mobiwise/library/radio/RadioPlayerService.java +++ b/library/src/main/java/co/mobiwise/library/radio/RadioPlayerService.java @@ -31,545 +31,542 @@ */ public class RadioPlayerService extends Service implements PlayerCallback { - /** - * Notification action intent strings - */ - private static final String NOTIFICATION_INTENT_PLAY_PAUSE = "co.mobiwise.library.notification.radio.INTENT_PLAYPAUSE"; - - private static final String NOTIFICATION_INTENT_CANCEL = "co.mobiwise.library.notification.radio.INTENT_CANCEL"; - - private static final String NOTIFICATION_INTENT_OPEN_PLAYER = "co.mobiwise.library.notification.radio.INTENT_OPENPLAYER"; + /** + * Stop action. If another mediaplayer will start.It needs + * to send broadcast to stop this service. + */ + public static final String ACTION_MEDIAPLAYER_STOP = "co.mobiwise.library.ACTION_STOP_MEDIAPLAYER"; + /** + * Notification action intent strings + */ + private static final String NOTIFICATION_INTENT_PLAY_PAUSE = "co.mobiwise.library.notification.radio.INTENT_PLAYPAUSE"; + private static final String NOTIFICATION_INTENT_CANCEL = "co.mobiwise.library.notification.radio.INTENT_CANCEL"; + private static final String NOTIFICATION_INTENT_OPEN_PLAYER = "co.mobiwise.library.notification.radio.INTENT_OPENPLAYER"; + /** + * Notification ID + */ + private static final int NOTIFICATION_ID = 001; + /** + * Logging control variable + */ + private static boolean isLogging = false; + /** + * Binder + */ + public final IBinder mLocalBinder = new LocalBinder(); + /** + * Radio buffer and decode capacity(DEFAULT VALUES) + */ + private final int AUDIO_BUFFER_CAPACITY_MS = 800; + private final int AUDIO_DECODE_CAPACITY_MS = 400; + /** + * Stream url suffix + */ + private final String SUFFIX_PLS = ".pls"; + private final String SUFFIX_RAM = ".ram"; + private final String SUFFIX_WAX = ".wax"; + List mListenerList; + /** + * Notification current values + */ + private String singerName = ""; + private String songName = ""; + private int smallImage = R.drawable.default_art; + private Bitmap artImage; + /** + * Radio State + */ + private State mRadioState; + /** + * Current radio URL + */ + private String mRadioUrl; + /** + * AAC Radio Player + */ + private MultiPlayer mRadioPlayer; + + /** + * Will be controlled on incoming calls and stop and start player. + */ + private TelephonyManager mTelephonyManager; + + /** + * While current radio playing, if you give another play command with different + * source, you need to stop it first. This value is responsible for control + * after radio stopped. + */ + private boolean isSwitching; + + /** + * If closed from notification, it will be checked + * on Stop method and notification will not be created + */ + private boolean isClosedFromNotification = false; + + /** + * Incoming calls interrupt radio if it is playing. + * Check if this is true or not after hang up; + */ + private boolean isInterrupted; + + /** + * Notification will be shown if this + * value set true; + */ + private boolean isNotificationEnabled = true; + + /** + * If play method is called repeatedly, AAC Decoder will be failed. + * play and stop methods will be turned mLock = true when they called, + * + * @onRadioStarted and @onRadioStopped methods will be release lock. + */ + private boolean mLock; + PhoneStateListener phoneStateListener = new PhoneStateListener() { + @Override + public void onCallStateChanged(int state, String incomingNumber) { + if (state == TelephonyManager.CALL_STATE_RINGING) { - /** - * Notification current values - */ - private String singerName = ""; - private String songName = ""; - private int smallImage = R.drawable.default_art; - private Bitmap artImage; + /** + * Stop radio and set interrupted if it is playing on incoming call. + */ + if (isPlaying()) { + isInterrupted = true; + stop(); + } - /** - * Notification ID - */ - private static final int NOTIFICATION_ID = 001; + } else if (state == TelephonyManager.CALL_STATE_IDLE) { - /** - * Logging control variable - */ - private static boolean isLogging = false; + /** + * Keep playing if it is interrupted. + */ + if (isInterrupted) + play(mRadioUrl); - /** - * Radio buffer and decode capacity(DEFAULT VALUES) - */ - private final int AUDIO_BUFFER_CAPACITY_MS = 800; - private final int AUDIO_DECODE_CAPACITY_MS = 400; + } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { - /** - * Stream url suffix - */ - private final String SUFFIX_PLS = ".pls"; - private final String SUFFIX_RAM = ".ram"; - private final String SUFFIX_WAX = ".wax"; + /** + * Stop radio and set interrupted if it is playing on outgoing call. + */ + if (isPlaying()) { + isInterrupted = true; + stop(); + } - /** - * State enum for Radio Player state (IDLE, PLAYING, STOPPED, INTERRUPTED) - */ - public enum State { - IDLE, - PLAYING, - STOPPED, + } + super.onCallStateChanged(state, incomingNumber); } - - List mListenerList; - - /** - * Radio State - */ - private State mRadioState; - - /** - * Current radio URL - */ - private String mRadioUrl; - - /** - * Stop action. If another mediaplayer will start.It needs - * to send broadcast to stop this service. - */ - public static final String ACTION_MEDIAPLAYER_STOP = "co.mobiwise.library.ACTION_STOP_MEDIAPLAYER"; - - /** - * AAC Radio Player - */ - private MultiPlayer mRadioPlayer; + }; + /** + * Notification manager + */ + private NotificationManager mNotificationManager; + + @Override + public IBinder onBind(Intent intent) { + return mLocalBinder; + } + + /** + * Service called + * + * @param intent + * @param flags + * @param startId + * @return + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + + String action = intent.getAction(); /** - * Will be controlled on incoming calls and stop and start player. + * If cancel clicked on notification, then set state to + * IDLE, stop player and cancel notification */ - private TelephonyManager mTelephonyManager; - - /** - * While current radio playing, if you give another play command with different - * source, you need to stop it first. This value is responsible for control - * after radio stopped. - */ - private boolean isSwitching; - - /** - * If closed from notification, it will be checked - * on Stop method and notification will not be created - */ - private boolean isClosedFromNotification = false; - - /** - * Incoming calls interrupt radio if it is playing. - * Check if this is true or not after hang up; - */ - private boolean isInterrupted; - - /** - * If play method is called repeatedly, AAC Decoder will be failed. - * play and stop methods will be turned mLock = true when they called, - * - * @onRadioStarted and @onRadioStopped methods will be release lock. - */ - private boolean mLock; - - /** - * Notification manager - */ - private NotificationManager mNotificationManager; - + if (action.equals(NOTIFICATION_INTENT_CANCEL)) { + if (isPlaying()) { + isClosedFromNotification = true; + stop(); + } + if (mNotificationManager != null) + mNotificationManager.cancel(NOTIFICATION_ID); + } /** - * Binder + * If play/pause action clicked on notification, + * Check player state and stop/play streaming. */ - public final IBinder mLocalBinder = new LocalBinder(); + else if (action.equals(NOTIFICATION_INTENT_PLAY_PAUSE)) { + if (isPlaying()) + stop(); + else if (mRadioUrl != null) + play(mRadioUrl); - @Override - public IBinder onBind(Intent intent) { - return mLocalBinder; } - /** - * Binder - */ - public class LocalBinder extends Binder { - public RadioPlayerService getService() { - return RadioPlayerService.this; - } + return START_NOT_STICKY; + } + + @Override + public void onCreate() { + super.onCreate(); + + mListenerList = new ArrayList<>(); + + mRadioState = State.IDLE; + isSwitching = false; + isInterrupted = false; + mLock = false; + getPlayer(); + + mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); + mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + + if (mTelephonyManager != null) + mTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + } + + /** + * Play url if different from previous streaming url. + * + * @param mRadioUrl + */ + public void play(String mRadioUrl) { + + sendBroadcast(new Intent(ACTION_MEDIAPLAYER_STOP)); + + notifyRadioLoading(); + + if (checkSuffix(mRadioUrl)) + decodeStremLink(mRadioUrl); + else { + this.mRadioUrl = mRadioUrl; + isSwitching = false; + + if (isPlaying()) { + log("Switching Radio"); + isSwitching = true; + stop(); + } else if (!mLock) { + log("Play requested."); + mLock = true; + getPlayer().playAsync(mRadioUrl); + } } + } - /** - * Service called - * - * @param intent - * @param flags - * @param startId - * @return - */ - @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public void stop() { + if (!mLock && mRadioState != State.STOPPED) { + log("Stop requested."); + mLock = true; + getPlayer().stop(); + } + } - String action = intent.getAction(); + @Override + public void playerStarted() { + mRadioState = State.PLAYING; + if (isNotificationEnabled) + buildNotification(); + mLock = false; + notifyRadioStarted(); - /** - * If cancel clicked on notification, then set state to - * IDLE, stop player and cancel notification - */ - if (action.equals(NOTIFICATION_INTENT_CANCEL)) { - if (isPlaying()) { - isClosedFromNotification = true; - stop(); - } - if (mNotificationManager != null) - mNotificationManager.cancel(NOTIFICATION_ID); - } - /** - * If play/pause action clicked on notification, - * Check player state and stop/play streaming. - */ - else if (action.equals(NOTIFICATION_INTENT_PLAY_PAUSE)) { - if (isPlaying()) - stop(); - else if (mRadioUrl != null) - play(mRadioUrl); + log("Player started. tate : " + mRadioState); - } + if (isInterrupted) + isInterrupted = false; - return START_NOT_STICKY; - } + } - @Override - public void onCreate() { - super.onCreate(); + public boolean isPlaying() { + if (State.PLAYING == mRadioState) + return true; + return false; + } - mListenerList = new ArrayList<>(); + @Override + public void playerPCMFeedBuffer(boolean b, int i, int i1) { + //Empty + } - mRadioState = State.IDLE; - isSwitching = false; - isInterrupted = false; - mLock = false; - getPlayer(); + @Override + public void playerStopped(int i) { - mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); - mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - - if (mTelephonyManager != null) - mTelephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); - } + mRadioState = State.STOPPED; /** - * Play url if different from previous streaming url. - * - * @param mRadioUrl + * If player stopped from notification then dont + * call buildNotification(). */ - public void play(String mRadioUrl) { - - sendBroadcast(new Intent(ACTION_MEDIAPLAYER_STOP)); - - notifyRadioLoading(); - - if (checkSuffix(mRadioUrl)) - decodeStremLink(mRadioUrl); - else { - this.mRadioUrl = mRadioUrl; - isSwitching = false; - - if (isPlaying()) { - log("Switching Radio"); - isSwitching = true; - stop(); - } else if (!mLock) { - log("Play requested."); - mLock = true; - getPlayer().playAsync(mRadioUrl); - } - } - } - - public void stop() { - if (!mLock && mRadioState != State.STOPPED) { - log("Stop requested."); - mLock = true; - getPlayer().stop(); - } - } - - @Override - public void playerStarted() { - mRadioState = State.PLAYING; + if (!isClosedFromNotification) { + if (isNotificationEnabled) { buildNotification(); - mLock = false; - notifyRadioStarted(); - - log("Player started. tate : " + mRadioState); - - if (isInterrupted) - isInterrupted = false; - + } + } else { + isClosedFromNotification = false; } - public boolean isPlaying() { - if (State.PLAYING == mRadioState) - return true; - return false; - } + mLock = false; + notifyRadioStopped(); + log("Player stopped. State : " + mRadioState); - @Override - public void playerPCMFeedBuffer(boolean b, int i, int i1) { - //Empty - } + if (isSwitching) + play(mRadioUrl); - @Override - public void playerStopped(int i) { - mRadioState = State.STOPPED; + } - /** - * If player stopped from notification then dont - * call buildNotification(). - */ - if (!isClosedFromNotification) - buildNotification(); - else - isClosedFromNotification = false; + @Override + public void playerException(Throwable throwable) { + mLock = false; + mRadioPlayer = null; + getPlayer(); + notifyErrorOccured(); + log("ERROR OCCURED."); + } - mLock = false; - notifyRadioStopped(); - log("Player stopped. State : " + mRadioState); + @Override + public void playerMetadata(String s, String s2) { + notifyMetaDataChanged(s, s2); + } - if (isSwitching) - play(mRadioUrl); + @Override + public void playerAudioTrackCreated(AudioTrack audioTrack) { + //Empty + } + public void registerListener(RadioListener mListener) { + mListenerList.add(mListener); + } - } + public void unregisterListener(RadioListener mListener) { + mListenerList.remove(mListener); + } - @Override - public void playerException(Throwable throwable) { - mLock = false; - mRadioPlayer = null; - getPlayer(); - notifyErrorOccured(); - log("ERROR OCCURED."); + private void notifyRadioStarted() { + for (RadioListener mRadioListener : mListenerList) { + mRadioListener.onRadioStarted(); } + } - @Override - public void playerMetadata(String s, String s2) { - notifyMetaDataChanged(s, s2); - } + private void notifyRadioStopped() { + for (RadioListener mRadioListener : mListenerList) + mRadioListener.onRadioStopped(); + } - @Override - public void playerAudioTrackCreated(AudioTrack audioTrack) { - //Empty - } + private void notifyMetaDataChanged(String s, String s2) { + for (RadioListener mRadioListener : mListenerList) + mRadioListener.onMetaDataReceived(s, s2); + } - public void registerListener(RadioListener mListener) { - mListenerList.add(mListener); + private void notifyRadioLoading() { + for (RadioListener mRadioListener : mListenerList) { + mRadioListener.onRadioLoading(); } + } - public void unregisterListener(RadioListener mListener) { - mListenerList.remove(mListener); + private void notifyErrorOccured() { + for (RadioListener mRadioListener : mListenerList) { + mRadioListener.onError(); } - - private void notifyRadioStarted() { - for (RadioListener mRadioListener : mListenerList) { - mRadioListener.onRadioStarted(); - } - } - - private void notifyRadioStopped() { - for (RadioListener mRadioListener : mListenerList) - mRadioListener.onRadioStopped(); - } - - private void notifyMetaDataChanged(String s, String s2) { - for (RadioListener mRadioListener : mListenerList) - mRadioListener.onMetaDataReceived(s, s2); - } - - private void notifyRadioLoading() { - for (RadioListener mRadioListener : mListenerList) { - mRadioListener.onRadioLoading(); + } + + /** + * Return AAC player. If it is not initialized, creates and returns. + * + * @return MultiPlayer + */ + private MultiPlayer getPlayer() { + try { + + java.net.URL.setURLStreamHandlerFactory(new java.net.URLStreamHandlerFactory() { + + public java.net.URLStreamHandler createURLStreamHandler(String protocol) { + Log.d("LOG", "Asking for stream handler for protocol: '" + protocol + "'"); + if ("icy".equals(protocol)) + return new com.spoledge.aacdecoder.IcyURLStreamHandler(); + return null; } + }); + } catch (Throwable t) { + Log.w("LOG", "Cannot set the ICY URLStreamHandler - maybe already set ? - " + t); } - private void notifyErrorOccured(){ - for (RadioListener mRadioListener : mListenerList) { - mRadioListener.onError(); - } + if (mRadioPlayer == null) { + mRadioPlayer = new MultiPlayer(this, AUDIO_BUFFER_CAPACITY_MS, AUDIO_DECODE_CAPACITY_MS); + mRadioPlayer.setResponseCodeCheckEnabled(false); + mRadioPlayer.setPlayerCallback(this); } - + return mRadioPlayer; + } + + /** + * Check supported suffix + * + * @param streamUrl + * @return + */ + public boolean checkSuffix(String streamUrl) { + if (streamUrl.contains(SUFFIX_PLS) || + streamUrl.contains(SUFFIX_RAM) || + streamUrl.contains(SUFFIX_WAX)) + return true; + else + return false; + } + + /** + * Enable/Disable log + * + * @param logging + */ + public void setLogging(boolean logging) { + isLogging = logging; + } + + /** + * Logger + * + * @param log + */ + private void log(String log) { + if (isLogging) + Log.v("RadioManager", "RadioPlayerService : " + log); + } + + /** + * If stream link is a file, then we + * call stream decoder to get HTTP stream link + * from that file. + * + * @param streamLink + */ + private void decodeStremLink(String streamLink) { + new StreamLinkDecoder(streamLink) { + @Override + protected void onPostExecute(String s) { + super.onPostExecute(s); + play(s); + } + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + + /** + * Build notification + */ + private void buildNotification() { /** - * Return AAC player. If it is not initialized, creates and returns. - * - * @return MultiPlayer + * Intents */ - private MultiPlayer getPlayer() { - try { - - java.net.URL.setURLStreamHandlerFactory(new java.net.URLStreamHandlerFactory() { - - public java.net.URLStreamHandler createURLStreamHandler(String protocol) { - Log.d("LOG", "Asking for stream handler for protocol: '" + protocol + "'"); - if ("icy".equals(protocol)) - return new com.spoledge.aacdecoder.IcyURLStreamHandler(); - return null; - } - }); - } catch (Throwable t) { - Log.w("LOG", "Cannot set the ICY URLStreamHandler - maybe already set ? - " + t); - } - - if (mRadioPlayer == null) { - mRadioPlayer = new MultiPlayer(this, AUDIO_BUFFER_CAPACITY_MS, AUDIO_DECODE_CAPACITY_MS); - mRadioPlayer.setResponseCodeCheckEnabled(false); - mRadioPlayer.setPlayerCallback(this); - } - return mRadioPlayer; - } - - PhoneStateListener phoneStateListener = new PhoneStateListener() { - @Override - public void onCallStateChanged(int state, String incomingNumber) { - if (state == TelephonyManager.CALL_STATE_RINGING) { - - /** - * Stop radio and set interrupted if it is playing on incoming call. - */ - if (isPlaying()) { - isInterrupted = true; - stop(); - } - - } else if (state == TelephonyManager.CALL_STATE_IDLE) { - - /** - * Keep playing if it is interrupted. - */ - if (isInterrupted) - play(mRadioUrl); - - } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { - - /** - * Stop radio and set interrupted if it is playing on outgoing call. - */ - if (isPlaying()) { - isInterrupted = true; - stop(); - } - - } - super.onCallStateChanged(state, incomingNumber); - } - }; + Intent intentPlayPause = new Intent(NOTIFICATION_INTENT_PLAY_PAUSE); + Intent intentOpenPlayer = new Intent(NOTIFICATION_INTENT_OPEN_PLAYER); + Intent intentCancel = new Intent(NOTIFICATION_INTENT_CANCEL); /** - * Check supported suffix - * - * @param streamUrl - * @return + * Pending intents */ - public boolean checkSuffix(String streamUrl) { - if (streamUrl.contains(SUFFIX_PLS) || - streamUrl.contains(SUFFIX_RAM) || - streamUrl.contains(SUFFIX_WAX)) - return true; - else - return false; - } + PendingIntent playPausePending = PendingIntent.getService(this, 0, intentPlayPause, 0); + PendingIntent openPending = PendingIntent.getService(this, 0, intentOpenPlayer, 0); + PendingIntent cancelPending = PendingIntent.getService(this, 0, intentCancel, 0); /** - * Enable/Disable log - * - * @param logging + * Remote view for normal view */ - public void setLogging(boolean logging) { - isLogging = logging; - } - /** - * Logger - * - * @param log - */ - private void log(String log) { - if (isLogging) - Log.v("RadioManager", "RadioPlayerService : " + log); - } + RemoteViews mNotificationTemplate = new RemoteViews(this.getPackageName(), R.layout.notification); + Notification.Builder notificationBuilder = new Notification.Builder(this); /** - * If stream link is a file, then we - * call stream decoder to get HTTP stream link - * from that file. - * - * @param streamLink + * set small notification texts and image */ - private void decodeStremLink(String streamLink) { - new StreamLinkDecoder(streamLink) { - @Override - protected void onPostExecute(String s) { - super.onPostExecute(s); - play(s); - } - }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } + if (artImage == null) + artImage = BitmapFactory.decodeResource(getResources(), R.drawable.default_art); + + mNotificationTemplate.setTextViewText(R.id.notification_line_one, singerName); + mNotificationTemplate.setTextViewText(R.id.notification_line_two, songName); + mNotificationTemplate.setImageViewResource(R.id.notification_play, isPlaying() ? R.drawable.btn_playback_pause : R.drawable.btn_playback_play); + mNotificationTemplate.setImageViewBitmap(R.id.notification_image, artImage); /** - * Build notification + * OnClickPending intent for collapsed notification */ - private void buildNotification() { - - /** - * Intents - */ - Intent intentPlayPause = new Intent(NOTIFICATION_INTENT_PLAY_PAUSE); - Intent intentOpenPlayer = new Intent(NOTIFICATION_INTENT_OPEN_PLAYER); - Intent intentCancel = new Intent(NOTIFICATION_INTENT_CANCEL); - - /** - * Pending intents - */ - PendingIntent playPausePending = PendingIntent.getService(this, 0, intentPlayPause, 0); - PendingIntent openPending = PendingIntent.getService(this, 0, intentOpenPlayer, 0); - PendingIntent cancelPending = PendingIntent.getService(this, 0, intentCancel, 0); - - /** - * Remote view for normal view - */ - - RemoteViews mNotificationTemplate = new RemoteViews(this.getPackageName(), R.layout.notification); - Notification.Builder notificationBuilder = new Notification.Builder(this); - - /** - * set small notification texts and image - */ - if (artImage == null) - artImage = BitmapFactory.decodeResource(getResources(), R.drawable.default_art); - - mNotificationTemplate.setTextViewText(R.id.notification_line_one, singerName); - mNotificationTemplate.setTextViewText(R.id.notification_line_two, songName); - mNotificationTemplate.setImageViewResource(R.id.notification_play, isPlaying() ? R.drawable.btn_playback_pause : R.drawable.btn_playback_play); - mNotificationTemplate.setImageViewBitmap(R.id.notification_image, artImage); - - /** - * OnClickPending intent for collapsed notification - */ - mNotificationTemplate.setOnClickPendingIntent(R.id.notification_collapse, cancelPending); - mNotificationTemplate.setOnClickPendingIntent(R.id.notification_play, playPausePending); - - - /** - * Create notification instance - */ - Notification notification = notificationBuilder - .setSmallIcon(smallImage) - .setContentIntent(openPending) - .setPriority(Notification.PRIORITY_DEFAULT) - .setContent(mNotificationTemplate) - .setUsesChronometer(true) - .build(); - notification.flags = Notification.FLAG_ONGOING_EVENT; + mNotificationTemplate.setOnClickPendingIntent(R.id.notification_collapse, cancelPending); + mNotificationTemplate.setOnClickPendingIntent(R.id.notification_play, playPausePending); - /** - * Expanded notification - */ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - RemoteViews mExpandedView = new RemoteViews(this.getPackageName(), R.layout.notification_expanded); + /** + * Create notification instance + */ + Notification notification = notificationBuilder + .setSmallIcon(smallImage) + .setContentIntent(openPending) + .setPriority(Notification.PRIORITY_DEFAULT) + .setContent(mNotificationTemplate) + .setUsesChronometer(true) + .build(); + notification.flags = Notification.FLAG_ONGOING_EVENT; - mExpandedView.setTextViewText(R.id.notification_line_one, singerName); - mExpandedView.setTextViewText(R.id.notification_line_two, songName); - mExpandedView.setImageViewResource(R.id.notification_expanded_play, isPlaying() ? R.drawable.btn_playback_pause : R.drawable.btn_playback_play); - mExpandedView.setImageViewBitmap(R.id.notification_image, artImage); + /** + * Expanded notification + */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - mExpandedView.setOnClickPendingIntent(R.id.notification_collapse, cancelPending); - mExpandedView.setOnClickPendingIntent(R.id.notification_expanded_play, playPausePending); + RemoteViews mExpandedView = new RemoteViews(this.getPackageName(), R.layout.notification_expanded); - notification.bigContentView = mExpandedView; - } + mExpandedView.setTextViewText(R.id.notification_line_one, singerName); + mExpandedView.setTextViewText(R.id.notification_line_two, songName); + mExpandedView.setImageViewResource(R.id.notification_expanded_play, isPlaying() ? R.drawable.btn_playback_pause : R.drawable.btn_playback_play); + mExpandedView.setImageViewBitmap(R.id.notification_image, artImage); - if (mNotificationManager != null) - mNotificationManager.notify(NOTIFICATION_ID, notification); - } + mExpandedView.setOnClickPendingIntent(R.id.notification_collapse, cancelPending); + mExpandedView.setOnClickPendingIntent(R.id.notification_expanded_play, playPausePending); - public void updateNotification(String singerName, String songName, int smallImage, int artImage) { - this.singerName = singerName; - this.songName = songName; - this.smallImage = smallImage; - this.artImage = BitmapFactory.decodeResource(getResources(), artImage); - buildNotification(); + notification.bigContentView = mExpandedView; } - - public void updateNotification(String singerName, String songName, int smallImage, Bitmap artImage) { - this.singerName = singerName; - this.songName = songName; - this.smallImage = smallImage; - this.artImage = artImage; - buildNotification(); + if (mNotificationManager != null) + mNotificationManager.notify(NOTIFICATION_ID, notification); + } + + public void updateNotification(String singerName, String songName, int smallImage, int artImage) { + this.singerName = singerName; + this.songName = songName; + this.smallImage = smallImage; + this.artImage = BitmapFactory.decodeResource(getResources(), artImage); + if (isNotificationEnabled) + buildNotification(); + } + + public void updateNotification(String singerName, String songName, int smallImage, Bitmap artImage) { + this.singerName = singerName; + this.songName = songName; + this.smallImage = smallImage; + this.artImage = artImage; + if (isNotificationEnabled) + buildNotification(); + } + + public void enableNotification(boolean isEnabled) { + isNotificationEnabled = isEnabled; + } + + /** + * State enum for Radio Player state (IDLE, PLAYING, STOPPED, INTERRUPTED) + */ + public enum State { + IDLE, + PLAYING, + STOPPED, + } + + /** + * Binder + */ + public class LocalBinder extends Binder { + public RadioPlayerService getService() { + return RadioPlayerService.this; } - - -} + } +} \ No newline at end of file