Skip to content

Instantly share code, notes, and snippets.

@talhahasanzia
Last active July 6, 2017 13:13
Show Gist options
  • Save talhahasanzia/ae937bfd918dcead51058aa6e0713a53 to your computer and use it in GitHub Desktop.
Save talhahasanzia/ae937bfd918dcead51058aa6e0713a53 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mediaplayer">
<uses-permission android:name="android.permission.INTERNET"/>
<permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".MediaPlayerService"
android:enabled="true"
android:exported="true">
</service>
</application>
</manifest>
package com.example.mediaplayer;
import java.io.Serializable;
public class Audio implements Serializable
{
private String data;
private String title;
private String album;
private String artist;
public Audio(String data, String title, String album, String artist) {
this.data = data;
this.title = title;
this.album = album;
this.artist = artist;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAlbum() {
return album;
}
public void setAlbum(String album) {
this.album = album;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
}
package com.example.mediaplayer;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity
{
Button play, pause, stop, toggle;
ArrayList<Audio> audioList;
private MediaPlayerService player;
boolean serviceBound = false;
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
play= (Button) findViewById( R.id.play );
pause= (Button) findViewById( R.id.pause );
stop=(Button) findViewById( R.id.stop );
toggle= (Button) findViewById( R.id.toggle );
play.setOnClickListener( new View.OnClickListener()
{
@Override
public void onClick( View view )
{
playAudio( R.raw.shape_of_you );
}
} );
pause.setOnClickListener( new View.OnClickListener()
{
@Override
public void onClick( View view )
{
if(serviceBound && player.isPlaying() && !player.isStopped())
player.pauseMedia();
}
} );
stop.setOnClickListener( new View.OnClickListener()
{
@Override
public void onClick( View view )
{
if(serviceBound && player.isPlaying() && !player.isStopped() )
player.stopMedia();
}
} );
toggle.setOnClickListener( new View.OnClickListener()
{
@Override
public void onClick( View view )
{
player.setRepeating( !player.isRepeating() );
}
} );
/*loadAudio(this);
//play the first audio in the ArrayList
playAudio(audioList.get(0).getData());*/
}
//Binding this Client to the AudioPlayer Service
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
player = binder.getService();
serviceBound = true;
Toast.makeText(MainActivity.this, "Service Bound", Toast.LENGTH_SHORT).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
private void playAudio(int media) {
//Check is service is active
if (!serviceBound) {
Intent playerIntent = new Intent(this, MediaPlayerService.class);
playerIntent.putExtra("media", media);
playerIntent.putExtra( "play",true );
startService(playerIntent);
bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} else {
//Service is active
//Send media with BroadcastReceiver
if(!player.isStopped())
player.playMedia();
else
{
Intent playerIntent = new Intent(this, MediaPlayerService.class);
playerIntent.putExtra("media", media);
playerIntent.putExtra( "play",true );
startService(playerIntent);
bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean("ServiceState", serviceBound);
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
serviceBound = savedInstanceState.getBoolean("ServiceState");
}
@Override
protected void onDestroy()
{
super.onDestroy();
if ( serviceBound )
{
unbindService( serviceConnection );
//service is active
player.stopSelf();
}
}
private void loadAudio(Context context) {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri, null, selection, null, sortOrder);
if (cursor != null && cursor.getCount() > 0) {
audioList = new ArrayList<>();
while (cursor.moveToNext()) {
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
// Save to audioList
audioList.add(new Audio(data, title, album, artist));
}
}
cursor.close();
}
}
package com.example.mediaplayer;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.IOException;
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnSeekCompleteListener,
MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener
{
// Binder given to clients
private final IBinder iBinder = new LocalBinder();
private AudioManager audioManager;
private MediaPlayer mediaPlayer;
//path to the audio file
private int mediaFile;
private int resumePosition;
//Handle incoming phone calls
private boolean ongoingCall = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private boolean repeating = false;
private boolean playing = false;
private boolean paused = false;
private boolean stopped = false;
private boolean preparing = false;
private boolean playOnInit = false;
boolean wasPlaying =false;
boolean FOCUS=false;
@Override
public int onStartCommand( Intent intent, int flags, int startId )
{
try
{
//An audio file is passed to the service through putExtra();
mediaFile = intent.getExtras().getInt( "media" );
playOnInit = intent.getExtras().getBoolean( "play" );
}
catch ( NullPointerException e )
{
stopSelf();
}
//Request audio focus
if ( requestAudioFocus() == false )
{
//Could not gain focus
stopSelf();
}
if ( mediaFile != -1 && mediaFile != 0 )
{
initMediaPlayer();
}
return super.onStartCommand( intent, flags, startId );
}
@Override
public void onDestroy()
{
super.onDestroy();
if ( mediaPlayer != null )
{
stopMedia();
mediaPlayer.release();
}
removeAudioFocus();
}
@Override
public IBinder onBind( Intent intent )
{
return iBinder;
}
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.setLooping( isRepeating() );
mediaPlayer.setAudioStreamType( AudioManager.STREAM_MUSIC );
// Set the data source to the mediaFile location
AssetFileDescriptor afd = getResources().openRawResourceFd(mediaFile);
try
{
mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
}
catch ( IOException e )
{
e.printStackTrace();
stopSelf();
}
mediaPlayer.prepareAsync();
preparing = true;
}
@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();
playing = false;
paused = false;
stopped = true;
}
//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;
}
@Override
public void onPrepared( MediaPlayer mp )
{
//Invoked when the media source is ready for playback.
preparing = false;
if ( playOnInit )
{
playMedia();
playOnInit = !playOnInit;
}
callStateListener();
}
@Override
public boolean onInfo( MediaPlayer mp, int what, int extra )
{
//Invoked to communicate some info.
return false;
}
@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 )
{
}
else if ( wasPlaying )
{
wasPlaying =false;
if(paused)
playMedia();
}
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();
wasPlaying =true;
}
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 boolean isRepeating()
{
return repeating;
}
public void setRepeating( boolean repeating )
{
this.repeating = repeating;
if ( mediaPlayer != null )
{
mediaPlayer.setLooping( repeating );
}
}
public void playMedia()
{
if ( !mediaPlayer.isPlaying() )
{
mediaPlayer.start();
playing = true;
paused = false;
stopped = false;
wasPlaying =false;
}
}
public void stopMedia()
{
if ( mediaPlayer == null )
{
return;
}
if ( mediaPlayer.isPlaying() )
{
mediaPlayer.stop();
}
playing = false;
paused = false;
stopped = true;
}
public void pauseMedia()
{
if ( mediaPlayer.isPlaying() )
{
mediaPlayer.pause();
resumePosition = mediaPlayer.getCurrentPosition();
playing = false;
paused = true;
stopped = false;
}
}
public void resumeMedia()
{
if ( !mediaPlayer.isPlaying() )
{
mediaPlayer.seekTo( resumePosition );
mediaPlayer.start();
playing = true;
paused = false;
stopped = false;
}
}
//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 );
}
public boolean isPlaying()
{
return playing;
}
public boolean isPaused()
{
return paused;
}
public boolean isStopped()
{
return stopped;
}
public boolean isPreparing()
{
return preparing;
}
public class LocalBinder extends Binder
{
public MediaPlayerService getService()
{
return MediaPlayerService.this;
}
}
}
package com.example.mediaplayer;
import android.content.Context;
/**
* Created by tzia on 06-Jul-17.
*/
public class Utils
{
public static int getFileFromAssetFolder(String fileName, Context context){
return context.getResources().getIdentifier( fileName, "raw", context.getPackageName() );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment