I have a Service which takes in an audio file and plays it with MediaPlayer. This is how I call my Service:
private void playAudio(String url) throws Exception {
Intent music = new Intent(this,MusicService.class);
music.putExtra("paths", path);
startService(music);
}
This is my Service class:
class MusicService extends Service implements OnCompletionListener {
MediaPlayer mediaPlayer;
String musicFile;
#Override
public void onCreate() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
Toast.makeText(getApplicationContext(), "hello", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle e = intent.getExtras();
musicFile= e.getString("paths");
try {
mediaPlayer.prepare();
mediaPlayer.setDataSource(musicFile);
} catch (IllegalArgumentException i) {
// TODO Auto-generated catch block
i.printStackTrace();
} catch (IllegalStateException i) {
// TODO Auto-generated catch block
i.printStackTrace();
} catch (IOException i) {
// TODO Auto-generated catch block
i.printStackTrace();
}
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
return START_STICKY;
}
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
The Service is never getting executed, the Toast is never shown, and the MediaPlayer does not play.
I declare my it in my manifest like this:
<service android:name=".MusicService" android:enabled="true"></service>
I get a force close error, and this IllegalAccessException in my logs:
java.lang.RuntimeException: Unable to instantiate service unjustentertainment.com.MusicService:
java.lang.IllegalAccessException: access to class not allowed
The exception you get is because the system could not init your service (call its constructor) because its not accessible.
As it says here:
...Make sure the class is
declared public...
The class you posted is not public, so make it public.
You need to make your class public.
i.e.
public class MusicService extends Service implements OnCompletionListener {
MediaPlayer mediaPlayer;
String musicFile;
I am trying to make a service that plays in background which is unbounded. I have walked myself through some of the example codes on the internet but I can't get my application to play the radio when I'm calling the service class.
Please have a look at the code and tell me where I am going wrong... When I call MyService class from ArmanFMRadio onClick It toasts "My Service Created" & "My Service Started" but doesnt get to play the audio for the radio stream link. I've checked it otherwise and the link seems fine, so problem lies somewhere in the code to my understanding:
package com.etc.etcc;
public class ArmanFMRadio extends Activity implements OnClickListener {
private ProgressBar playSeekBar;
private Button buttonPlay;
private Button buttonStopPlay;
private MediaPlayer player;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.armanfm);
initializeUIElements();
//initializeMediaPlayer();
}
private void initializeUIElements() {
playSeekBar = (ProgressBar) findViewById(R.id.progressBar1);
playSeekBar.setMax(100);
playSeekBar.setVisibility(View.INVISIBLE);
buttonPlay = (Button) findViewById(R.id.buttonPlay);
buttonPlay.setOnClickListener(this);
buttonStopPlay = (Button) findViewById(R.id.buttonStopPlay);
buttonStopPlay.setEnabled(false);
buttonStopPlay.setOnClickListener(this);
}
private void initializeMediaPlayer() {
player = new MediaPlayer();
try {
player.setDataSource("http://50.117.26.26:3953/Live");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
public void onBufferingUpdate(MediaPlayer mp, int percent) {
playSeekBar.setVisibility(View.VISIBLE);
playSeekBar.setSecondaryProgress(percent);
Log.i("Buffering", "" + percent);
}
});
}
public void onClick(View v) {
switch(v.getId()){
case R.id.buttonPlay:
playSeekBar.setVisibility(View.VISIBLE);
buttonStopPlay.setEnabled(true);
buttonPlay.setEnabled(false);
startService(new Intent(this, MyService.class));
//startPlaying();
break;
case R.id.buttonStopPlay:
stopPlaying();
break;
}
}
private void startPlaying() {
buttonStopPlay.setEnabled(true);
buttonPlay.setEnabled(false);
playSeekBar.setVisibility(View.VISIBLE);
player.prepareAsync();
player.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
private void stopPlaying() {
if (player.isPlaying()) {
player.stop();
player.release();
initializeMediaPlayer();
}
buttonPlay.setEnabled(true);
buttonStopPlay.setEnabled(false);
playSeekBar.setVisibility(View.INVISIBLE);
}
#Override
protected void onPause() {
super.onPause();
if (player.isPlaying()) {
player.stop();
}
}
}
Just look at onClick on the above code, because this class works fine to my thinking.
MyService class:
package com.etc.etcc;
public class MyService extends Service {
private static final String TAG = "MyService";
private MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player = new MediaPlayer();
try {
player.setDataSource("http://50.117.26.26:3953/Live");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
player.prepareAsync();
player.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
}
}
onStart is deprecated method. you should use onStartCommand method.
Debug your code and check weather there is any Exception or something
Also you are using the service so possible that you service will call twice in that case your onStartCommand method will be called twice so there you will have to check the startId which you will get as a parameter. If startId > 1 that means previously your service is started so you can stop media player and again start a media player with latest source or you can just ignore the second request.
If you are not confidence with service you can put your code in the activity and check weather your code is working fine or not after that you can replace this code in the service.
I have a Service which takes in an audio file and plays it with MediaPlayer. This is how I call my Service:
private void playAudio(String url) throws Exception {
Intent music = new Intent(this,MusicService.class);
music.putExtra("paths", path);
startService(music);
}
This is my Service class:
class MusicService extends Service implements OnCompletionListener {
MediaPlayer mediaPlayer;
String musicFile;
#Override
public void onCreate() {
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
Toast.makeText(getApplicationContext(), "hello", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Bundle e = intent.getExtras();
musicFile= e.getString("paths");
try {
mediaPlayer.prepare();
mediaPlayer.setDataSource(musicFile);
} catch (IllegalArgumentException i) {
// TODO Auto-generated catch block
i.printStackTrace();
} catch (IllegalStateException i) {
// TODO Auto-generated catch block
i.printStackTrace();
} catch (IOException i) {
// TODO Auto-generated catch block
i.printStackTrace();
}
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
return START_STICKY;
}
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
The Service is never getting executed, the Toast is never shown, and the MediaPlayer does not play.
I declare my it in my manifest like this:
<service android:name=".MusicService" android:enabled="true"></service>
I get a force close error, and this IllegalAccessException in my logs:
java.lang.RuntimeException: Unable to instantiate service unjustentertainment.com.MusicService:
java.lang.IllegalAccessException: access to class not allowed
The exception you get is because the system could not init your service (call its constructor) because its not accessible.
As it says here:
...Make sure the class is
declared public...
The class you posted is not public, so make it public.
You need to make your class public.
i.e.
public class MusicService extends Service implements OnCompletionListener {
MediaPlayer mediaPlayer;
String musicFile;
public class PlayAudio extends BroadcastReceiver{
private Context mContext;
MediaPlayer mp;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
mIntent = intent;
playSound("sound.mp3");
}
private void playSound(String file){
mp = MediaPlayer.create(mContext, Uri.parse("file://"+file));
if (mp.isPlaying())
{
mp.stop();
}
mp.setLooping(true);
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
}
}
I am getting an error when i check if mp is playing. How can i check if MediaPlayer(mp) is playing so that i can stop it?
First a bit of confusion in the above code
In the above code new instance of media player will get created each time you call playsound() what you need to do is instantiate mp only once in oncreate() of playaudio class and use it repeatedly.
Also if you use create to instantiate mediaplayer you prepare gets called internally you should not call it again.http://developer.android.com/reference/android/media/MediaPlayer.html#create(android.content.Context, android.net.Uri)
Check if mp is null after you do create to verify if mediaplayer instance was created successfully.
Wondering how next songs are played once app is closed as if playing an entire CD or playlist...
The media player only plays one audio track. What media players do, is listen on the onCompletion event and play the next track.
The MediaPlayer is bound to the process, not the activity, so it keeps playing as long as the process runs. The activity might be paused or destroyed, but that won't affect the internal thread that MediaPlayer uses.
I'm building an audio player to learn Android, you can see the service that plays audio files here
edit
regarding the first comment: The service keeps running on the background and keeps running after you "exit" the application, because the lifecycle of the service and Activities are different.
In order to play the next track, the service registers a callback on the MediaPlayer so the service is informed when an audio stream completed. When the audio completes, the service cleans up the resources used by the MediaPlayer, by calling MediaPlayer.release(), and then creates a fresh new media player with the next audio track to play and registers itself to be notified again when that audio track completes, ad infinitum :).
The MediaPlayer class doesn't understand playlists, so the service is responsible for playing a track after the previous track completes.
In the AudioPlayer service I've created, an activity queues tracks in the AudioPlayer and the AudioPlayer is responsible for playing them in order.
I hope it's clear and again, if you have some time, please check the code of AudioPlayer service I've put above. It's not pure beauty, but it does its job.
You can create a Service to keep the MediaPlayer playing after your app either exits or is paused. To get the MediaPlayer to play consecutive tracks you can register an onCompletionListener that will decide which track to play next. Here is a simple example service that does this:
package edu.gvsu.cis.muzak;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.IBinder;
import android.util.Log;
public class MuzakService extends Service {
private static final String DEBUG_TAG = "MuzakService";
private MediaPlayer mp;
private String[] tracks = {
"http://freedownloads.last.fm/download/288181172/Nocturne.mp3",
"http://freedownloads.last.fm/download/367924875/Behemoths%2BSternentanz.mp3",
"http://freedownloads.last.fm/download/185193341/Snowflake%2BImpromptu.mp3",
"http://freedownloads.last.fm/download/305596593/Prel%25C3%25BAdio.mp3",
"http://freedownloads.last.fm/download/142005075/Piano%2BSonata%2B22%2B-%2Bmovement%2B2%2B%2528Beethoven%2529.mp3",
"http://freedownloads.last.fm/download/106179902/Piano%2BSonata%2B%25231%2B-%2Bmovement%2B%25234%2B%2528Brahms%2529.mp3",
};
private int currentTrack = 0;
#Override
public void onCreate() {
super.onCreate();
Log.d(DEBUG_TAG, "In onCreate.");
try {
Uri file = Uri.parse(tracks[this.currentTrack]);
mp = new MediaPlayer();
mp.setDataSource(this, file);
mp.prepare();
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
currentTrack = (currentTrack + 1) % tracks.length;
Uri nextTrack = Uri.parse(tracks[currentTrack]);
try {
mp.setDataSource(MuzakService.this,nextTrack);
mp.prepare();
mp.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
} catch (Exception e) {
Log.e(DEBUG_TAG, "Player failed", e);
}
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d(DEBUG_TAG, "In onDestroy.");
if(mp != null) {
mp.stop();
}
}
#Override
public int onStartCommand(Intent intent,int flags, int startId) {
super.onStart(intent, startId);
Log.d(DEBUG_TAG, "In onStart.");
mp.start();
return Service.START_STICKY_COMPATIBILITY;
}
#Override
public IBinder onBind(Intent intent) {
Log.d(DEBUG_TAG, "In onBind with intent=" + intent.getAction());
return null;
}
}
You can start this Service up in an Activity as follows:
Intent serv = new Intent(this,MuzakService.class);
startService(serv);
and stop it like this:
Intent serv = new Intent(this,MuzakService.class);
stopService(serv);
Please note that Service run in fore ground too.
Please see the official documentation. It explains with a sample code.
Using a Service with MediaPlayer:
http://developer.android.com/guide/topics/media/mediaplayer.html#mpandservices
Running as a foreground service
Services are often used for performing background tasks
But consider the case of a service that is playing music. Clearly this is a service that the user is actively aware of and the experience would be severely affected by any interruptions. Additionally, it's a service that the user will likely wish to interact with during its execution. In this case, the service should run as a "foreground service." A foreground service holds a higher level of importance within the system—the system will almost never kill the service, because it is of immediate importance to the user. When running in the foreground, the service also must provide a status bar notification to ensure that users are aware of the running service and allow them to open an activity that can interact with the service.
In order to turn your service into a foreground service, you must create a Notification for the status bar and call startForeground() from the Service
mediap player should run from the service, here i have passed the arraylist of songs from the activity to service and all the songs are run by reading the arraylist
public class MyService extends Service implements OnCompletionListener,
MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener{
Context context;
private static final String ACTION_PLAY = "PLAY";
private static final String TAG = "SONG SERVICE";
MediaPlayer mediaPlayer;
private int currentTrack = 0;
ArrayList<String> list;
public MyService() {
context=getBaseContext();
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
list = (ArrayList<String>)intent.getSerializableExtra("arraylist");
int count=0;
Log.d(TAG, "total count:"+list.size());
//playing song one by one
for (String string : list) {
//play(string);
count++;
Log.d(TAG, "count:"+list);
}
play(currentTrack);
Log.d(TAG, "count:"+count);
if(count==list.size()){
//stopSelf();
Log.d(TAG, "stoping service");
//mediaPlayer.setOnCompletionListener(this);
}else{
Log.d(TAG, "not stoping service");
}
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
Log.d(TAG, "oncommat");
}
return START_STICKY;
}
#Override
public void onCreate() {
Toast.makeText(this, "Service was Created", Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
// Perform your long running operations here.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
Log.d("service", "destroyed");
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
}
private void play(int id) {
if(mediaPlayer!=null && mediaPlayer.isPlaying()){
Log.d("*****begin*****", "playing");
stopPlaying();
Log.d("*****begin*****", "stoping");
} else{
Log.d("*****begin*****", "nothing");
}
Log.d("*****play count*****", "="+currentTrack);
Log.i("******playing", list.get(currentTrack));
Uri myUri1 = Uri.parse(list.get(id));
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mediaPlayer.setOnPreparedListener(this);
//mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
try {
mediaPlayer.setDataSource(context, myUri1);
Log.i("******playing", myUri1.getPath());
} catch (IllegalArgumentException e) {
Toast.makeText(context, "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (SecurityException e) {
Toast.makeText(context, "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IllegalStateException e) {
Toast.makeText(context, "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
try {
mediaPlayer.prepare();
} catch (IllegalStateException e) {
Toast.makeText(context, "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
Toast.makeText(context, "You might not set the URI correctly!", Toast.LENGTH_LONG).show();
}
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
currentTrack=currentTrack+1;
play(currentTrack);
/* currentTrack = (currentTrack + 1) % list.size();
Uri nextTrack=Uri.parse(list.get(currentTrack));
try {
mediaPlayer.setDataSource(context,nextTrack);
mediaPlayer.prepare();
// mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}*/
}
});
mediaPlayer.start();
}
private void stopPlaying() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
}
The answer is Services in Android as described here: http://developer.android.com/guide/topics/fundamentals.html as
You are going to create a service and when you receive play command from your app, your app will send a message to background service to play the music. Services do not run in foreground, therefore even you put your screen to sleep, it plays the music.
Playing BG Music Across Activities in Android