I'm trying to play music with a background service. Firstly, I have a toggle button in MainActivity for playing and pausing music. I also created
BackgroundSoundService just for playing music in all activities and not to play in the background:
public class BackgroundSoundService extends Service {
private static final String TAG = "BackgroundSoundService";
MediaPlayer player;
public IBinder onBind(Intent arg0) {
Log.i(TAG, "onBind()" );
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.vaporv2);
player.setLooping(true); // Set looping
player.setVolume(100,100);
Log.i(TAG, "onCreate() , service started...");
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return Service.START_STICKY;
}
public IBinder onUnBind(Intent arg0) {
Log.i(TAG, "onUnBind()");
return null;
}
public void onStop() {
Log.i(TAG, "onStop()");
}
public void onPause() {
if(player!=null && player.isPlaying()){
player.pause();
}
Log.i(TAG, "onPause()");
}
#Override
public void onDestroy() {
player.stop();
player.release();
Log.i(TAG, "onCreate() , service stopped...");
}
#Override
public void onLowMemory() {
Log.i(TAG, "onLowMemory()");
}
}
and MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MusicButton = (ToggleButton) findViewById(R.id.toggleButton);
MusicButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (MusicButton.isChecked()) {
//mediaPlayer.pause();
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
startService(myService);
} else {
//mediaPlayer.start();
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
stopService(myService);
}
}
});
My problem happens when I pause the music and play it again. The music starts from the beginning when I want it to continue from where it left off. My second problem is that I don't want to play music in the background, I want stop music when the app is in background.
I'm not sure what your onPause() and onStop() are meant to do. However when you start a service for the first time using Context.startService() the onCreate() method of the service is called and then onStartCommand() is called and later when you call startService() again only the onStartCommand() is called. So for whatever reason if you want to play the sound in a service and pause that in the very same service, you need to provide the service an Action that specifies the action you want to do.
So in your activity when you want to tell the service to play the sound:
String action = "PLAY";
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
myService.setAction(action);
startService(myService);
and to pause the sound:
String action = "PAUSE";
Intent myService = new Intent(MainActivity.this, BackgroundSoundService.class);
myService.setAction(action);
startService(myService);
and in the onStartCommand() method in your service:
if (intent.getAction().equals("PLAY")) {
// resume the sound
}
if (intent.getAction().equals("PAUSE")) {
// pause the sound
}
and when you really need to stop the service meaning Destroy the service, call context.stopService() and only then onDestroy() method is called and the service is really destroyed.
To prevent playing in background override on Activity pause then pause you service there and to resume where you left of save the current position in a preference then retrieve it when needed
Related
In my app there is a background music, for what I have a service. It works fine, but it "keeps playing" when either I close the app or turn off the screen.
Should I change something in onPause or onStop?
My code:
public class MyService extends Service {
private final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.id);
player.setLooping(true); // Set looping
player.setVolume(100, 100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
protected void onStop() {
player.pause();
}
public void onPause() {
player.pause();
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
As screen turns off your activity becomes invisible which triggers onPause followed by onStop
Screen on, on the other hand, triggers onStart followed by onResume.
when ever you want to stop service use
stopService(new Intent(ActivityName.this, ServiceClassName.class));
Probably copies of the player are created somehow. Try to make MediaPlayer variable static and then try to deallocate it after pausing onPause(). Anyway it is weird, that you are creating MediaPlayer instance in service.
I am making an android app for my website. It has some videos which are somewhat like podcasts. I want the app to be able to play the audio in the background when the user either locks the screen or is using other applications. To achieve this, I have a WebView in place. To provide the above mentioned functionality, I tried to use a PARTIAL_WAKE_LOCK in the activity. This only continues to play the audio when the screen is locked, but not when the home button is pressed (ie. in the background). Is there a workaround for this issue?
If You want your app to keep running the Audio even if it is in Background, You have to run the Mediaplayer in a Separate Service.
This service will keep on Running even the app goes to background or comes back.
You can even write a sticky service to keep running(with foreground as true) if the app gets killed.
You should use android service to play the music independent of your activity.Please look at this example:
Here is my Android Service class:
class MusicService extends Service implements OnCompletionListener {
MediaPlayer mediaPlayer;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
mediaPlayer = MediaPlayer.create(this, R.raw.s);// raw/s.mp3
mediaPlayer.setOnCompletionListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
return START_STICKY;
}
public void onDestroy() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
}
public void onCompletion(MediaPlayer _mediaPlayer) {
stopSelf();
}
}
Here is Activity:
public class MusicActivity extends Activity implements OnClickListener {
Button startPlaybackButton, stopPlaybackButton;
Intent playbackServiceIntent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startPlaybackButton = (Button) this.findViewById(R.id.StartPlaybackButton);
stopPlaybackButton = (Button) this.findViewById(R.id.StopPlaybackButton);
startPlaybackButton.setOnClickListener(this);
stopPlaybackButton.setOnClickListener(this);
playbackServiceIntent = new Intent(this,MusicService.class);
}
public void onClick(View v) {
if (v == startPlaybackButton) {
startService(playbackServiceIntent);
finish();
} else if (v == stopPlaybackButton) {
stopService(playbackServiceIntent);
finish();
}
}
}
Please do not forget to add the service in your manifest file :
<service android:enabled="true" android:name=".services.MusicService" />
public class BackgroundMusicService extends Service
{
int currentPos;
/** indicates how to behave if the service is killed */
int mStartMode;
/** interface for clients that bind */
IBinder mBinder;
/** indicates whether onRebind should be used */
boolean mAllowRebind;
MediaPlayer player;
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.tornado);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
player.seekTo(currentPos);
player.start();
return 1;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return mAllowRebind;
}
#Override
public void onRebind(Intent intent) {
}
public void onPause()
{
player.pause();
}
#Override
public void onDestroy() {
player.stop();
currentPos = player.getCurrentPosition();
}
}
This is the service that play the background music, how to pause the service when the home button is pressed and resume the service when the program is resume? and here is my MainActivity:
public class MainActivity extends ActionBarActivity
{
int request_code = 1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(getBaseContext(), BackgroundMusicService.class));
}
#Override
protected void onDestroy()
{
super.onDestroy();
stopService(new Intent(getBaseContext(), BackgroundMusicService.class));
}
}
I think need to use onPause() and onResume() function, but how to use it? and it should be use in service class or the activity class?
One more thing need to consider, I used multiple intent, and make sure that when I change to 2nd or others intents, the service is still running, means that changing intent will not stop playing the background music...unless home button is pressed or quit the program(this one I already done).
You have your onPause and onResume methods. You generally don't need to extend the Application class but instead use it in your Activity (esp if your app only has one Activity).
However, why start and stop the service? Why not just pause/unpause the music? You can send an intent to pause/unpause (or even toggle) the music playback.
I'm trying to create an activity with one button in its layout which will pause or resume the music when it's pressed. the problem is that when it's pressed to resume the music it starts the audio file all over again. Any idea how to make it play from the last point it stopped rather than restarting it?
Main activity
public class MainActivity extends Activity implements OnClickListener {
private Boolean isMusicPlaying;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View musicButton = findViewById(R.id.music_button);
musicButton.setOnClickListener(this);
startService(new Intent(getBaseContext(), MusicService.class));
isMusicPlaying = true;
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.music_button)
if (isMusicPlaying) stopService(new Intent(getBaseContext(),
MusicService.class));
else startService(new Intent(getBaseContext(), MusicService.class));
isMusicPlaying = !isMusicPlaying;
}
}
Service class
public class MusicService extends Service {
MediaPlayer player;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.song);
player.setLooping(true); // Set looping
player.setVolume(100, 100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return START_STICKY;
}
#Override
public void onDestroy() {
player.pause();
}
}
It seems like MediaPlayer object in your service is not kept when you stop the service.
You can get the current position of your song using getCurrentPosition() method before you stop your service,
player.pause();
currentPos = player.getCurrentPosition();
and send this value back to activity before it is stopped.
Then, you can use seekTo(int) method to move to specified time position before playing.
player.seekTo(currentPos);
player.start();
For communication between your service and activity, you might register broadcastreceiver and communicate using intent or use a bound service.
UPDATE:
I found following tutorial and you'd better to follow this. It's about using a service with MediaPlayer.
Especially, you are not using prepare method at all when you initialize your MediaPlayer. put these lines:
player.setOnPreparedListener(this);
player.prepareAsync();
and add listener:
public void onPrepared(MediaPlayer player) {
player.start();
}
http://developer.android.com/guide/topics/media/mediaplayer.html#mpandservices
Seeing that the activity is re-started why don't you save the states to Shared Preferences
I need to have background music in all my activities. It should stop when the application is not foreground. As I'm developing for 2.3 I can't use the ActivityLifeCycleCallBacks class. I implemented the solution at Checking if an Android application is running in the background and then decided to make the mediaplayer a singleton and use it in a service.
Everything works fine and if I press home, select quit from the menu or I make the application go background any way the sound stops but... after some random time when I'm doing something else or even when the screen is turned off the music will start again out of the blue. Even if I kill the application from task manager the will start again later again.
This is my first singleton and my first time playing with service so I guess I'm missing something really basic. I think I'm closing the service but apparently I'm not.
Here is the code:
PlayAudio.java
import ...
public class PlayAudio extends Service{
private static final Intent Intent = null;
MediaPlayer objPlayer;
private int length = 0;
boolean mIsPlayerRelease = true;
private static PlayAudio uniqueIstance; //the singleton
static PlayAudio mService;
static boolean mBound = false; // boolean to check if the service containing this singleton is binded to some activity
public static boolean activityVisible; // boolean to check if the activity using the player is foreground or not
//My attempt to make a singleton
public static PlayAudio getUniqueIstance(){
if (uniqueIstance == null) {
uniqueIstance = new PlayAudio();
}
return uniqueIstance;
}
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
static public ServiceConnection mConnection = new ServiceConnection() {// helper for the activity
public void onServiceConnected(ComponentName className,
IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
public static Intent createIntent (Context context) { //helper for the activity using the player
Intent intent = new Intent(context, PlayAudio.class);
return intent;
}
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
PlayAudio getService() {
// Return this instance so clients can call public methods
return PlayAudio.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public void onCreate(){
super.onCreate();
Log.d(LOGCAT, "Service Started!");
objPlayer = MediaPlayer.create(this,R.raw.kickstarterreduced);
objPlayer.setLooping(true);
mIsPlayerRelease = false;
}
public int onStartCommand(Intent intent, int flags, int startId){
objPlayer.start();
Log.d(LOGCAT, "Media Player started!");
if(objPlayer.isLooping() != true){
Log.d(LOGCAT, "Problem in Playing Audio");
}
return 1;
}
public void onStop(){
objPlayer.setLooping(false);
objPlayer.stop();
objPlayer.release();
mIsPlayerRelease = true;
}
public void onPause(){
if(objPlayer.isPlaying())
{
objPlayer.pause();
length=objPlayer.getCurrentPosition(); // save the position in order to be able to resume from here
}
}
public void resumeMusic() // if length is 0 the player just start from zero
{ if (mIsPlayerRelease == true) {
objPlayer = MediaPlayer.create(this,R.raw.kickstarterreduced);
mIsPlayerRelease = false;
}
if(objPlayer.isPlaying()==false )
{
if (length != 0) objPlayer.seekTo(length);
objPlayer.start();
}
}
}
And this are the methods I have implemented in every activity's class
SharedPreferences sharedPrefs;
PlayAudio playerIstanced;
public static boolean activityVisible;
#Override
public void onStart() {
super.onStart();
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
}
#Override
public void onResume() {
super.onResume();
playerIstanced= PlayAudio.getUniqueIstance(); //call singleton
bindService(PlayAudio.createIntent(this), playerIstanced.mConnection, Context.BIND_AUTO_CREATE); // create the service
if (sharedPrefs.getBoolean("sound", true) == true) {// if sound is enabled in option it will start the service
startService(PlayAudio.createIntent(this));
playerIstanced.mService.activityResumed();
if (playerIstanced.mBound == true) {
playerIstanced.mService.resumeMusic();
}
}
}
#Override
public void onPause() {
super.onPause();
playerIstanced.mService.activityPaused();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//If the phone lags when changing activity (between onPause() and the other activity onResume() the music won't stop. If after 500ms onResume() is not called it means the activity went background...Am I messing with service here?
if (playerIstanced.mService.isActivityVisible() != true) {
playerIstanced.mService.onPause();
}
}
}, 500);
}
#Override
public void onStop(){
super.onStop();
// Unbind from the service
if (playerIstanced.mService.mBound) {
playerIstanced.mService.mBound = false;
unbindService(playerIstanced.mService.mConnection);
}
}
}
Stop music automatically when user exit from app
This part has to be in EVERY activity's onPause:
public void onPause(){
super.onPause();
Context context = getApplicationContext();
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
if (!taskInfo.isEmpty()) {
ComponentName topActivity = taskInfo.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
StopPlayer();
Toast.makeText(xYourClassNamex.this, "YOU LEFT YOUR APP. MUSIC STOP", Toast.LENGTH_SHORT).show();
}
}
}
This part has to be in EVERY activity's onResume:
Play music automatically when user resume the app
Public void onResume()
{
super.onResume();
StartPlayer();
}
Hope it helps!!
You can check my answer according to this topic may it will sove your issue.
You need to manually stop the service using Context.stopService() or stopSelf(). See the Service Lifecycle section of http://developer.android.com/reference/android/app/Service.html.
Service Lifecycle
There are two reasons that a service can be run by the system. If someone calls Context.startService() then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call its onStartCommand(Intent, int, int) method with the arguments supplied by the client. The service will at this point continue running until Context.stopService() or stopSelf() is called. Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called; however, services can use their stopSelf(int) method to ensure the service is not stopped until started intents have been processed.
I believe you can simply put playerIstanced.stopSelf() in the onStop() call of each activity.
My understanding is that the service continues to run quietly after your application stops. After a while the system kills the service to free up resources, and then after a while more when resources are available it restarts the service. When the service restarts its onResume() is called and the music begins playing.
it helped me stop the mediaplayer.
Use Handler(getMainLooper()) to start and stop MediaPlayer.
final Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
mediaPlayer.start();
}
});
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
, 30 * 1000);