Created
April 4, 2019 10:23
-
-
Save tchiks1/84b89a58bcb2d541f907242f59868d72 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener, | |
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener, | |
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener, | |
AudioManager.OnAudioFocusChangeListener { | |
public static final String ACTION_PLAY = "com.be.homsi.ACTION_PLAY"; | |
public static final String ACTION_PAUSE = "com.be.homsi.ACTION_PAUSE"; | |
public static final String ACTION_PREVIOUS = "com.be.homsi.ACTION_PREVIOUS"; | |
public static final String ACTION_NEXT = "com.be.homsi.ACTION_NEXT"; | |
public static final String ACTION_STOP = "com.be.homsi.ACTION_STOP"; | |
//MediaSession | |
private MediaSessionManager mediaSessionManager; | |
private MediaSessionCompat mediaSession; | |
private MediaControllerCompat.TransportControls transportControls; | |
//AudioPlayer notification ID | |
private static final int NOTIFICATION_ID = 101; | |
// Binder given to clients | |
private final IBinder iBinder = new LocalBinder(); | |
String newAudio; | |
private SeekBar mSeekBar; | |
private TextView mCurrentPosition; | |
private TextView mTotalDuration; | |
private int mInterval = 1000; | |
//Handle incoming phone calls | |
private boolean ongoingCall = false; | |
private PhoneStateListener phoneStateListener; | |
private TelephonyManager telephonyManager; | |
private AudioManager audioManager; | |
private MediaPlayer mediaPlayer; | |
//path to the audio file | |
private String mediaFile; | |
//Used to pause/resume MediaPlayer | |
private int resumePosition; | |
public static final String Broadcast_BTN_PLAY="com.be.homsi.btnplay"; | |
public static final String Broadcast_BTN_PREVIOUS="com.be.homsi.btnprevious"; | |
public static final String Broadcast_BTN_NEXT="com.be.homsi.btnnext"; | |
@Override | |
public int onStartCommand(Intent intent, int flags, int startId) { | |
try { | |
//An audio file is passed to the service through putExtra(); | |
mediaFile = intent.getExtras().getString("media"); | |
//play button custom notification | |
register_btn_previous(); | |
register_btn_play(); | |
register_btn_next(); | |
} catch (NullPointerException e) { | |
stopSelf(); | |
} | |
//Request audio focus | |
if (requestAudioFocus() == false) { | |
//Could not gain focus | |
stopSelf(); | |
} | |
if (mediaFile != null && mediaFile != "") | |
initMediaPlayer(); | |
return super.onStartCommand(intent, flags, startId); | |
} | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
// Perform one-time setup procedures | |
// Manage incoming phone calls during playback. | |
// Pause MediaPlayer on incoming call, | |
// Resume on hangup. | |
callStateListener(); | |
//ACTION_AUDIO_BECOMING_NOISY -- change in audio outputs -- BroadcastReceiver | |
registerBecomingNoisyReceiver(); | |
//Listen for new Audio to play -- BroadcastReceiver | |
register_playNewAudio(); | |
} | |
//receiver play button custom notification | |
private void register_btn_play() { | |
//Register playNewMedia receiver | |
IntentFilter filter = new IntentFilter(Broadcast_BTN_PLAY); | |
registerReceiver(playbtn, filter); | |
} | |
private void register_btn_previous() { | |
//Register playNewMedia receiver | |
IntentFilter filter = new IntentFilter(Broadcast_BTN_PREVIOUS); | |
registerReceiver(previousbtn, filter); | |
} | |
private void register_btn_next() { | |
//Register playNewMedia receiver | |
IntentFilter filter = new IntentFilter(Broadcast_BTN_NEXT); | |
registerReceiver(nextbtn, filter); | |
} | |
private BroadcastReceiver playbtn = new BroadcastReceiver() { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
if(mediaPlayer.isPlaying()) | |
mediaPlayer.pause(); | |
else{ | |
mediaPlayer.start(); | |
int duration = mediaPlayer.getDuration(); | |
mSeekBar.setMax(duration); | |
mSeekBar.postDelayed(mProgressRunner, mInterval); | |
// Set our duration text view to display total duration in format 0:00 | |
mTotalDuration.setText(String.format("%d:%02d", | |
TimeUnit.MILLISECONDS.toMinutes(duration), | |
TimeUnit.MILLISECONDS.toSeconds(duration) - | |
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)) | |
)); | |
Log.d("playbtns","playbtn"); | |
} | |
} | |
}; | |
private BroadcastReceiver previousbtn = new BroadcastReceiver() { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
if((mediaPlayer.getCurrentPosition() - 5000)>0){ | |
mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() - 5000); | |
}else | |
{ | |
mediaPlayer.seekTo(0); | |
} | |
Log.d("pause","pause"); | |
} | |
}; | |
private BroadcastReceiver nextbtn = new BroadcastReceiver() { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
if((mediaPlayer.getCurrentPosition() + 5000)<=mediaPlayer.getDuration()){ | |
mediaPlayer.seekTo(mediaPlayer.getCurrentPosition() + 5000); | |
}else | |
{ | |
mediaPlayer.seekTo(mediaPlayer.getDuration()-1000); | |
} | |
Log.d("pause","pause"); | |
} | |
}; | |
//Becoming noisy | |
private BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
//pause audio on ACTION_AUDIO_BECOMING_NOISY | |
pauseMedia(); | |
// buildNotification(PlaybackStatus.PAUSED); | |
} | |
}; | |
private BroadcastReceiver playNewAudio = new BroadcastReceiver() { | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
//Get the new media index form SharedPreferences | |
SharedPreferences preferences = context.getSharedPreferences(STORAGE, Context.MODE_PRIVATE); | |
newAudio=preferences.getString("newAudio",null); | |
mediaFile=newAudio; | |
if (newAudio == null ) { | |
stopSelf(); | |
} | |
//A PLAY_NEW_AUDIO action received | |
//reset mediaPlayer to play the new Audio | |
stopMedia(); | |
mediaPlayer.reset(); | |
initMediaPlayer(); | |
//updateMetaData(); | |
// buildNotification(PlaybackStatus.PLAYING); | |
} | |
}; | |
private void register_playNewAudio() { | |
//Register playNewMedia receiver | |
IntentFilter filter = new IntentFilter(Broadcast_PLAY_NEW_AUDIO); | |
registerReceiver(playNewAudio, filter); | |
} | |
private void registerBecomingNoisyReceiver() { | |
//register after getting audio focus | |
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); | |
registerReceiver(becomingNoisyReceiver, intentFilter); | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
if (mediaPlayer != null) { | |
stopMedia(); | |
mediaPlayer.release(); | |
} | |
removeAudioFocus(); | |
//Disable the PhoneStateListener | |
if (phoneStateListener != null) { | |
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); | |
} | |
//removeNotification(); | |
//unregister BroadcastReceivers | |
unregisterReceiver(becomingNoisyReceiver); | |
unregisterReceiver(playNewAudio); | |
SharedPreferences preferences = getSharedPreferences(STORAGE, Context.MODE_PRIVATE); | |
SharedPreferences.Editor editor = preferences.edit(); | |
editor.clear(); | |
editor.apply(); | |
} | |
@Override | |
public void onBufferingUpdate(MediaPlayer mp, int percent) { | |
//Invoked indicating buffering status of | |
//a media resource being streamed over the network. | |
} | |
@Override | |
public void onCompletion(MediaPlayer mp) { | |
//Invoked when playback of a media source has completed. | |
stopMedia(); | |
//stop the service | |
stopSelf(); | |
} | |
//Handle errors | |
@Override | |
public boolean onError(MediaPlayer mp, int what, int extra) { | |
//Invoked when there has been an error during an asynchronous operation | |
switch (what) { | |
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: | |
Log.d("MediaPlayer Error", "MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK " + extra); | |
break; | |
case MediaPlayer.MEDIA_ERROR_SERVER_DIED: | |
Log.d("MediaPlayer Error", "MEDIA ERROR SERVER DIED " + extra); | |
break; | |
case MediaPlayer.MEDIA_ERROR_UNKNOWN: | |
Log.d("MediaPlayer Error", "MEDIA ERROR UNKNOWN " + extra); | |
break; | |
} | |
return false; | |
} | |
// Async thread to update progress bar every second | |
private Runnable mProgressRunner = new Runnable() { | |
@Override | |
public void run() { | |
if (mSeekBar != null) { | |
mSeekBar.setProgress(mediaPlayer.getCurrentPosition()); | |
if(mediaPlayer.isPlaying()) { | |
mSeekBar.postDelayed(mProgressRunner, mInterval); | |
} | |
} | |
} | |
}; | |
@Override | |
public boolean onInfo(MediaPlayer mp, int what, int extra) { | |
//Invoked to communicate some info. | |
return false; | |
} | |
@Override | |
public void onPrepared(MediaPlayer mp) { | |
//Invoked when the media source is ready for playback. | |
playMedia(); | |
} | |
@Override | |
public void onSeekComplete(MediaPlayer mp) { | |
//Invoked indicating the completion of a seek operation. | |
} | |
@Override | |
public void onAudioFocusChange(int focusState) { | |
//Invoked when the audio focus of the system is updated. | |
switch (focusState) { | |
case AudioManager.AUDIOFOCUS_GAIN: | |
// resume playback | |
if (mediaPlayer == null) initMediaPlayer(); | |
else if (!mediaPlayer.isPlaying()) mediaPlayer.start(); | |
mediaPlayer.setVolume(1.0f, 1.0f); | |
break; | |
case AudioManager.AUDIOFOCUS_LOSS: | |
// Lost focus for an unbounded amount of time: stop playback and release media player | |
if (mediaPlayer.isPlaying()) mediaPlayer.stop(); | |
mediaPlayer.release(); | |
mediaPlayer = null; | |
break; | |
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: | |
// Lost focus for a short time, but we have to stop | |
// playback. We don't release the media player because playback | |
// is likely to resume | |
if (mediaPlayer.isPlaying()) mediaPlayer.pause(); | |
break; | |
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: | |
// Lost focus for a short time, but it's ok to keep playing | |
// at an attenuated level | |
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f); | |
break; | |
} | |
} | |
private boolean requestAudioFocus() { | |
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); | |
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); | |
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { | |
//Focus gained | |
return true; | |
} | |
//Could not gain focus | |
return false; | |
} | |
private boolean removeAudioFocus() { | |
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == | |
audioManager.abandonAudioFocus(this); | |
} | |
public int updateseekbar(){ | |
return mediaPlayer.getCurrentPosition(); | |
} | |
public int totalduration(){ | |
return mediaPlayer.getDuration(); | |
} | |
@Override | |
public IBinder onBind(Intent intent) { | |
return iBinder; | |
} | |
public class LocalBinder extends Binder { | |
public MediaPlayerService getService() { | |
return MediaPlayerService.this; | |
} | |
} | |
private void initMediaPlayer() { | |
mediaPlayer = new MediaPlayer(); | |
//Set up MediaPlayer event listeners | |
mediaPlayer.setOnCompletionListener(this); | |
mediaPlayer.setOnErrorListener(this); | |
mediaPlayer.setOnPreparedListener(this); | |
mediaPlayer.setOnBufferingUpdateListener(this); | |
mediaPlayer.setOnSeekCompleteListener(this); | |
mediaPlayer.setOnInfoListener(this); | |
//Reset so that the MediaPlayer is not pointing to another data source | |
mediaPlayer.reset(); | |
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); | |
try { | |
// Set the data source to the mediaFile location | |
mediaPlayer.setDataSource(mediaFile); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
stopSelf(); | |
} | |
mediaPlayer.prepareAsync(); | |
} | |
private void playMedia() { | |
buildNotification(); | |
if (!mediaPlayer.isPlaying()) { | |
mediaPlayer.start(); | |
int duration = mediaPlayer.getDuration(); | |
mSeekBar.setMax(duration); | |
mSeekBar.postDelayed(mProgressRunner, mInterval); | |
// Set our duration text view to display total duration in format 0:00 | |
mTotalDuration.setText(String.format("%d:%02d", | |
TimeUnit.MILLISECONDS.toMinutes(duration), | |
TimeUnit.MILLISECONDS.toSeconds(duration) - | |
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration)) | |
)); | |
} | |
} | |
/** | |
* Sets seekBar to control while playing music | |
* @param seekBar - Seek bar instance that's already on our UI thread | |
*/ | |
public void setUIControls(SeekBar seekBar, TextView currentPosition, TextView totalDuration) { | |
mSeekBar = seekBar; | |
mCurrentPosition = currentPosition; | |
mTotalDuration = totalDuration; | |
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { | |
@Override | |
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { | |
if (fromUser) { | |
// Change current position of the song playback | |
mediaPlayer.seekTo(progress); | |
} | |
// Update our textView to display the correct number of second in format 0:00 | |
mCurrentPosition.setText(String.format("%d:%02d", | |
TimeUnit.MILLISECONDS.toMinutes(progress), | |
TimeUnit.MILLISECONDS.toSeconds(progress) - | |
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(progress)) | |
)); | |
} | |
@Override | |
public void onStartTrackingTouch(SeekBar seekBar) {} | |
@Override | |
public void onStopTrackingTouch(SeekBar seekBar) {} | |
}); | |
} | |
private void stopMedia() { | |
if (mediaPlayer == null) return; | |
if (mediaPlayer.isPlaying()) { | |
mediaPlayer.stop(); | |
} | |
} | |
private void pauseMedia() { | |
if (mediaPlayer.isPlaying()) { | |
mediaPlayer.pause(); | |
resumePosition = mediaPlayer.getCurrentPosition(); | |
} | |
} | |
public Boolean isPlaying(){ | |
Boolean b=false; | |
if(mediaPlayer.isPlaying()){ | |
b=true; | |
} | |
return b; | |
} | |
private void resumeMedia() { | |
if (!mediaPlayer.isPlaying()) { | |
mediaPlayer.seekTo(resumePosition); | |
mediaPlayer.start(); | |
} | |
} | |
//Handle incoming phone calls | |
private void callStateListener() { | |
// Get the telephony manager | |
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); | |
//Starting listening for PhoneState changes | |
phoneStateListener = new PhoneStateListener() { | |
@Override | |
public void onCallStateChanged(int state, String incomingNumber) { | |
switch (state) { | |
//if at least one call exists or the phone is ringing | |
//pause the MediaPlayer | |
case TelephonyManager.CALL_STATE_OFFHOOK: | |
case TelephonyManager.CALL_STATE_RINGING: | |
if (mediaPlayer != null) { | |
pauseMedia(); | |
ongoingCall = true; | |
} | |
break; | |
case TelephonyManager.CALL_STATE_IDLE: | |
// Phone idle. Start playing. | |
if (mediaPlayer != null) { | |
if (ongoingCall) { | |
ongoingCall = false; | |
resumeMedia(); | |
} | |
} | |
break; | |
} | |
} | |
}; | |
// Register the listener with the telephony manager | |
// Listen for changes to the device call state. | |
telephonyManager.listen(phoneStateListener, | |
PhoneStateListener.LISTEN_CALL_STATE); | |
} | |
private void buildNotification(){ | |
RemoteViews expandedViews = new RemoteViews(getPackageName(), R.layout.big_notification); | |
NotificationCompat.Builder nc=new NotificationCompat.Builder(getApplicationContext(),"mediacontrol"); | |
NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); | |
Intent notifyIntent = new Intent(getApplicationContext(), Interpretation.class); | |
//demarrer un intent implicite pour le button play | |
Intent playbutton=new Intent(Broadcast_BTN_PLAY); | |
//sendBroadcast(playbutton); | |
playbutton.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); | |
PendingIntent pendingIntents=PendingIntent.getBroadcast(getApplicationContext(),0,playbutton,0 | |
); | |
expandedViews.setOnClickPendingIntent(R.id.play,pendingIntents); | |
//demarrer un intent implicite pour le button previous | |
Intent pausebutton=new Intent(Broadcast_BTN_PREVIOUS); | |
//sendBroadcast(pausebutton); | |
playbutton.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); | |
PendingIntent pendingpausebutton=PendingIntent.getBroadcast(getApplicationContext(),0,pausebutton,0 | |
); | |
expandedViews.setOnClickPendingIntent(R.id.previous,pendingpausebutton); | |
//demarrer un intent implicite pour le button play | |
Intent nextbutton=new Intent(Broadcast_BTN_NEXT); | |
//sendBroadcast(pausebutton); | |
playbutton.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); | |
PendingIntent pendingnextbutton=PendingIntent.getBroadcast(getApplicationContext(),0,nextbutton,0 | |
); | |
expandedViews.setOnClickPendingIntent(R.id.next,pendingnextbutton); | |
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); | |
PendingIntent pendingIntent=PendingIntent.getActivity(getApplicationContext(),0,notifyIntent,PendingIntent.FLAG_UPDATE_CURRENT); | |
nc.setContentIntent(pendingIntent); | |
nc.setSmallIcon(R.drawable.logo); | |
nc.setAutoCancel(true); | |
nc.setCustomBigContentView(expandedViews); | |
nc.setContentTitle("Homsi"); | |
//nc.getBigContentView().setTextViewText(R.id.nom,"Sainte monique"); | |
nm.notify(NOTIFICATION_ID,nc.build()); | |
} | |
private void removeNotification() { | |
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); | |
notificationManager.cancel(NOTIFICATION_ID); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment