Reputation: 43
I am trying to implement an Android Foreground Service that play music from a URL. MediaPlayer
starts as normally and play the song, but after a while, it calls onCompletion()
when the song is not finished. I set up an onErrorListener
but it's not called.
What I have done:
The app doesn't crash, MediaPlayer
just call onCompletion
and I don't know what to do. Here you have the Service and Activity code. Thanks in advance:
SERVICE:
public class MusicService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener{
//FILTER FOR BROADCASTS
public final static String ACTION_FILTER = "ACTION_HHGROUPS";
//MEDIA ACTIONS:
public final static String ACTION_PLAY_ONE = "ACTION_PLAY_ONE";
//FOREGROUND:
public static boolean IS_FOREGROUND = false;
public final static int FOREGROUND_SERVICE = 101;
public final static String ACTION_START_FOREGROUND = "ACTION_START_FOREGROUND";
public final static String ACTION_STOP_FOREGROUND = "ACTION_STOP_FOREGROUND";
//EXTRAS:
public final static String EXTRA_URL = "EXTRA_URL";
private MediaPlayer mPlayer;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
switch (intent.getAction()) {
case ACTION_START_FOREGROUND:
Log.v("SERVICIO", "ACTION_START_FOREGROUND");
IS_FOREGROUND = true;
showNotification();
break;
case ACTION_PLAY_ONE:
Log.v("SERVICIO", "ACTION_PLAY_ONE");
initializeMediaPlayer(
intent.getStringExtra(MusicService.EXTRA_URL);
break;
case ACTION_STOP_FOREGROUND:
Log.v("SERVICIO", "ACTION_STOP_FOREGROUND");
IS_FOREGROUND = false;
stopForeground(true);
stopSelf();
break;
}
return Service.START_STICKY;
}
public void initializePlayer(String url) {
if(mPlayer == null) {
mPlayer = new MediaPlayer();
mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
if(url != null && !url.isEmpty()) {
try {
mPlayer.setDataSource(url);
mPlayer.prepareAsync();
} catch (IOException e) {
Log.v("SERVICIO-MEDIA", "IOException");
e.printStackTrace();
}
}
} else {
try {
mPlayer.reset();
mPlayer.setDataSource(url);
mPlayer.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.e("SERVICIO", "OnTaskRemoved");
if(IS_FOREGROUND)
stopForeground(true);
stopSelf();
}
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
Log.v("SERVICIO", "onCompletion");
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
Log.v("SERVICIO-MEDIA", "onPrepared. Duration: " + mediaPlayer.getDuration());
}
@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
Log.v("SERVICIO", "onError");
return true;
}
private void showNotification() {
Intent notificationIntent = new Intent(this, PruebaActivity.class);
notificationIntent.setAction(ACTION_NOTIFICATION_MAIN);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Intent previousIntent = new Intent(this, MusicService.class);
previousIntent.setAction(ACTION_NOTIFICATION_PREV);
PendingIntent ppreviousIntent = PendingIntent.getService(this, 0,
previousIntent, 0);
Intent playIntent = new Intent(this, MusicService.class);
playIntent.setAction(ACTION_NOTIFICATION_PLAY);
PendingIntent pplayIntent = PendingIntent.getService(this, 0,
playIntent, 0);
Intent nextIntent = new Intent(this, MusicService.class);
nextIntent.setAction(ACTION_NOTIFICATION_NEXT);
PendingIntent pnextIntent = PendingIntent.getService(this, 0,
nextIntent, 0);
Intent deleteIntent = new Intent(this, MusicService.class);
PendingIntent pdeleteIntent = PendingIntent.getService(this, 666,deleteIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("Content title")
.setTicker("This is a Ticker...")
.setContentText("Context text")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.setOngoing(true)
.addAction(android.R.drawable.ic_media_previous, "Prev",
ppreviousIntent)
.addAction(android.R.drawable.ic_media_play, "Play",
pplayIntent)
.addAction(android.R.drawable.ic_media_next, "Next",
pnextIntent).build();
startForeground(FOREGROUND_SERVICE, notification);
}
}
ACTIVITY:
public class PruebaActivity extends AppCompatActivity implements View.OnClickListener {
String url = "http://stream.hhgroups.com/1-Ey7w3haY2RtcqiutMX1SylvqnvkP1oFuKo4765uI6Dc-Isusko%20y%20Sbrv%20-%20Marionetas%20(Adelanto)%20-%20www.HHGroups.com/";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prueba);
findViewById(R.id.btnPlaySong).setOnClickListener(this);
Button btnForeground = findViewById(R.id.btnStartForeground);
btnForeground.setOnClickListener(this);
if(MusicService.IS_FOREGROUND)
btnForeground.setText("STOP FOREGROUND");
else
btnForeground.setText("START FOREGROUND");
}
@SuppressLint("SetTextI18n")
@Override
public void onClick(View view) {
switch(view.getId()) {
case R.id.btnStartForeground:
if(MusicService.IS_FOREGROUND) {
Toast.makeText(PruebaActivity.this, "STOPPING FOREGROUND", Toast.LENGTH_SHORT).show();
startService(new Intent(PruebaActivity.this, MusicService.class)
.setAction(MusicService.ACTION_STOP_FOREGROUND));
((Button)view).setText("START FOREGROUND");
} else {
Toast.makeText(PruebaActivity.this, "SETTING FOREGROUND", Toast.LENGTH_SHORT).show();
startService(new Intent(PruebaActivity.this, MusicService.class)
.setAction(MusicService.ACTION_START_FOREGROUND));
((Button)view).setText("STOP FOREGROUND");
}
break;
case R.id.btnPlaySong:
if(MusicService.IS_FOREGROUND) {
Log.v("SERVICIO-ACTIVITY", "btnPlaySong -> Foreground ON");
Toast.makeText(PruebaActivity.this, "PLAYING SONG", Toast.LENGTH_SHORT).show();
startService(new Intent(PruebaActivity.this, MusicService.class)
.setAction(MusicService.ACTION_PLAY_ONE)
.putExtra(MusicService.EXTRA_URL, url));
} else {
Log.v("SERVICIO-ACTIVITY", "btnPlaySong -> Foreground OFF");
Toast.makeText(PruebaActivity.this, "SETTING FOREGROUND", Toast.LENGTH_SHORT).show();
startService(new Intent(PruebaActivity.this, MusicService.class)
.setAction(MusicService.ACTION_START_FOREGROUND));
Toast.makeText(PruebaActivity.this, "PLAYING SONG", Toast.LENGTH_SHORT).show();
startService(new Intent(PruebaActivity.this, MusicService.class)
.setAction(MusicService.ACTION_PLAY_ONE)
.putExtra(MusicService.EXTRA_URL, url));
}
break;
}
}
}
Upvotes: 1
Views: 566
Reputation: 2795
Looks like a server side issue. Your test url has "Content-Disposition:inline;" in response header which means it is download not streaming.
HTTP/1.1 200 OK
Date: Fri, 28 Jul 2017 18:20:20 GMT
Server: Apache
Cache-Control: max-age=2678400
Content-Length: 10562918
Content-Disposition: inline; filename="540b4a08d51bc718f1e7f30313af9526.mp3"
Keep-Alive: timeout=10, max=800
Connection: Keep-Alive
Content-Type: audio/mpeg
Change your test url.
Upvotes: 1