I have a MediaPlayerService, currently started when the Play/Pause Button on a ListView item is clicked. See code below (CustomListAdapter):
Intent intent = new Intent(v.getContext(),MediaPlayerService.class);
intent.putExtra("StreamLink",audio);
activity.startService(intent);
When this service is started by the code above I want to create a Notification with a Play/Stop button. The user should be able to get out of the app, be able to stop Media Playback e.g. player.stop() and start player.start(). Also when the Notification is clicked it should return the user to the MainActivity.
The code for my MediaPlayerService.java:
public class MediaPlayerService extends Service implements MediaPlayer.OnPreparedListener {
MediaPlayer mMediaPlayer = null;
public String audioStreamLink;
public int onStartCommand(Intent intent, int flags, int startId) {
// Get the Audio Streaming Link from the parsed JSON in the Main Activity
audioStreamLink = intent.getStringExtra("StreamLink");
// Instantiate MediaPlayer, set the Audio Type and acquire a wakelock, set the Media Player Data Source and Prepare.
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mMediaPlayer.setDataSource(audioStreamLink);
} catch (IOException e) {
e.printStackTrace();
}
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.prepareAsync();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
/** Called when MediaPlayer is ready */
#Override
public void onPrepared(MediaPlayer player) {
player.start();
}
#Override
public void onDestroy() {
mMediaPlayer.stop();
mMediaPlayer.reset();
if (mMediaPlayer != null) mMediaPlayer.release();
}
}
The process of getting a notification is completely documented down there in the documents, for example, see this.
To help you go through all this huge documentation these are the points :
You need to create the custom notification using a NotificationCompat.Builder
A typical music player service would start the notification using startForeground()
To add clickable buttons to the notification use addAction() when building the notifications.
Actions in Notifications are defined by PendingIntent, its a kind of normal Intent when it comes to responding to it.
When a button on the notification is clicked, the onStartCommand() is triggered with the intent you specified for that button (if you configure the intent correctly).
Each button's intent should have a different action so that you can identify the intent when it is received.
Inside the onStartCommand() you can play/pause and do other operations based on this intent's action.
Some reference I would suggest you to read :
https://developer.android.com/guide/topics/ui/notifiers/notifications.html
https://developer.android.com/guide/topics/ui/notifiers/notifications.html#Updating
https://developer.android.com/reference/android/app/Service.html#startForeground(int,android.app.Notification)
Things would have been a bit different if you were using a MediaSession to play the media.
Related
I'm developing an Android App in Android Studio and in that a sound has to play on the WebView. But when I close the app, it automatically stops playing the audio. Now I want to know how do I make the audio to play in the background even if I close the app. (Kindly provide the code, I'm new to android development.) Thanks in advance.
I am sorry, I think it's impossible.
To play a sound in background, you need to play the audio in Service.
It's only one way to play background sound.
I will show a code for that:
public class serv extends Service{
MediaPlayer mp;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onCreate()
{
mp = MediaPlayer.create(this, R.raw.b);
mp.setLooping(false);
}
public void onDestroy()
{
mp.stop();
}
public void onStart(Intent intent,int startid){
Log.d(tag, "On start");
mp.start();
}
}
I have a music service that plays music in the background of the app. I want the music to keep playing through all activities of the application but to stop when the app is running in the background (ie when the user goes to another app or presses the home button without removing the app from the running applications)
This is my MusicService code:
public class MusicService extends Service {
public static MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
player= MediaPlayer.create(this,R.raw.music1);
player.start();
player.setLooping(true);
return super.onStartCommand(intent,flags,startId);
}
}
and this is the part of my manifest related to the music service:
<service android:name=".MusicService" android:stopWithTask="true" />
Edit: If anyone knows how to play background music without service also that would be okay as long as the music plays during the whole time the app is open and closes when the home button is pressed.
Basicaly you have to define witch activity is your exit point and then edit your onStartCommand like this
private boolean playing; // use this var to determine if the service is playing
public int onStartCommand(Intent intent, int flags, int startId) {
String action = intent.getAction();
if(action == ACTION_PLAY) {
// No each time your start an activity start the service with ACTION_PLAY but in ACTION_PLAY process check if the player if not already runing
if(!playing) {
player= MediaPlayer.create(this,R.raw.music1);
player.start();
player.setLooping(true);
// here you set playing to true
playing = true;
}
} else if(action.equals(ACTION_STOP) {
// Set playing to false
playing = false;
// This is just an exemple : Now here increase a delay little bit so that the player will not stop automaticaly after leaving activity
new Handler().postDelayed(new Runnable(){
#override
public void run() {
// No before stoping the play service
// check playing if playing dont go further
if(playing) return;
if(player!=null && player.isPlaying()) {
player.stop();
player.release();
player.reset(); // To avoid mediaPlayer has went away with unhandled error warning
player = null;
// And stop the service
stopSelf();
}
}
},2500);
}
return START_STICKY;}
Now if you want to start playing use
Intent intent = new Intent(context,YourService.class);
intent.setAction(YourService.ACTION_PLAY);
And for stopping
Intent intent = new Intent(context,YourService.class);
intent.setAction(YourService.ACTION_STOP);
And dont forget to define the two action contants fields
If you dont want to define your exit point you can define a boolean that determine that your service is in use and therefore wont be stopped by the delayed handler
Now each time one of activity start, start the service with action ACTION_PLAY
and once it stop start the service with ACTION_STOP that will ensure that each activity have the ability to start and stop player
also dont forget to tweak the delay
Hope it help
I think the best solution to this problem is to stop the music in onPause() of each Activity and start the music in onResume() of each Activity. The problem you will run into is that your music will stutter when your application switches from one Activity to another. To combat that problem, you should post a Runnable (that stops the music) to a Handler in onPause(), but post it so that it doesn't run immediately. It should be delayed for about 200 milliseconds. In onResume(), cancel the Runnable so that it does not run. This will prevent the stuttering, but stop the music 200 milliseconds after the user has pressed the HOME button.
Another option is not to use a Service, but just keep the MediaPlayer instance in your Application class. You'll still want to stop and start the music in onPause() and onResume(), but you can do it more directly by just calling some methods on your Application class. You will need to create a custom Application class that extends Application and add that to your manifest.
This question has been asked a few times, but none of the answers have helped me solve my problem so I'm posting my version of it.
I'm creating an app that plays a list of songs through a service. The problem is that I got a null exception error from the mediaPlayer after I rotate the device. As you can see below, I first start and then bind to my service in the onResume method. Likewise, I unbind and stop the service in the onDestroy method.
protected void onResume() {
if (playIntent == null) {
playIntent = new Intent(MainActivity.this, MediaService.class);
// if (n < 0) {
startService(playIntent);
bindService(playIntent, mediaConnection, Context.BIND_AUTO_CREATE);
Log.d("Check", "Started Service");
// }
}
super.onResume();
}
In my service, I set up the mediaPlayer in the service's onCreate method as below. I have a few things in the onStartCommand method (like creating a notification to show in the action bar). I also return Start_sticky in onStartCommand method.
Unfortunately, like I said, when I rotate the device, I get a null exception from the mediaPlayer.
Please help; I've been trying to fix this for days.
static private MediaPlayer player;
private final IBinder musicBind = new MediaBinder();
Notification notification;
private int playbackDuration;
static Uri paths[][] = new Uri[MainActivity.NUMBER_OF_ARTISTS][MainActivity.NUMBER_OF_TRACKS];
public void onCreate() {
// create the service
super.onCreate();
player = new MediaPlayer();
player.reset();
player.setLooping(true);
initMediaPlayer();
Log.d("Check", "In Service's OnCreate method");
I have a working alarm app, but wanted to add a feature where the user gets the choice between "Play alarm continuously till acknowledged" and "play alarm sound once".
I then looked at my alrm ringing code expecting to see some kind of "repeat" flag which I could optionally remove - but there was none. So how do I play the alarm sound just once?
My existing code looks like this:
private void playSound(Context context, Uri alert)
{
mMediaPlayer = new MediaPlayer();
try
{
mMediaPlayer.setDataSource(context, alert);
final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
if (audioManager.getStreamVolume(AudioManager.STREAM_ALARM) != 0)
{
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
mMediaPlayer.prepare();
mMediaPlayer.start();
}
}
catch (IOException e)
{
// oops!
}
}
Actually in each alarm sound there is a FLAG named ANDROID_LOOP which force your sound to loop. Unfortunatly you can't change that flag even using MediaPlayer.setLooping(false).
But you still can manually stop your player after a certain time. For example getDuration will give you the length of your sound.
int duration = mMediaPlayer.getDuration();
Runnable stopSoundRunnable = new Runnable() {
#Override
public void run() {
mMediaPlayer.stop();
}
};
mSoundHanlder.postDelayed(stopSoundRunnable, duration);
Please take a look at my simple three-methods Service class that streams audio and play it directly.
public class StreamService extends Service {
private static final String TAG = "MyService";
String url;
MediaPlayer mp;
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
mp = new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
mp.stop();
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
url = intent.getExtras().getString("url");
try {
mp.setDataSource(url);
mp.prepare();
mp.start();
} catch(Exception e){}
return START_STICKY;
}
}
In my activity, I have two buttons to play/stop the media file:
The playButton execute this:
Intent i = new Intent(this, StreamService.class);
i.putExtra("my_mp3_url_string");
startService(i);
The stopButton execute this:
stopService(new Intent(this, StreamService.class));
Now, I have some questions:
how I can implement the pauseButton? I want to pause the media running in the Service
Does my way of playing/stopping the media/Service correct ? Is there any better way?
How I can (periodically) update my Activity's UI from my Service? do I need to add something?
I would recommend not using the lifetime of the Service as a way to start and stop playback. Using that approach will mean that every time you want to start a new stream, the code will be slowed down even more by having to bring up a new Service. You can save some time by just having the same Service play everything. Though that doesn't mean it should remain running all the time.
To accomplish that (and to be able to pause), you'll need to bind to the Service after it is started. With the bound Service, you'll be able to make calls to it - such as pause, play, stop, etc.
Here are some links that should help you with what you're looking for:
Using a Service with MediaPlayer
Binding to a Service