Music Background service bug when app killed [duplicate] - android

I am using a Service class to play music in the background. While I am displaying the notification bar on top, there is issue in my app. When I kill the app, the music stops for about 1 second and then it starts again. I can't figure out what's the issue.
I was following this tutorial.
public class MyMusicService extends Service {
MediaPlayer mediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public MyMusicService() {
super();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mediaPlayer!= null)
{
mediaPlayer.release();
}
mediaPlayer =MediaPlayer.create(this,R.raw.song);
mediaPlayer.setLooping(true);
mediaPlayer.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
}
}

Use onTaskRemoved on your main activity and release your mediaplayer on this event.

That tutorial shows you how to build a BACKGROUND service, which can get killed by the system. To play music you should use a FOREGROUND service.
https://developer.android.com/guide/components/services.html#Foreground

According to: https://developer.android.com/reference/android/app/Service.html
Change
START_STICKY
to
START_NOT_STICKY
EDIT:
The issue with music stopping for a while is connected with the fact that you run app and service in the same process. And 'killing app' means stopping the whole process bound to it. What you need to do is to run your service in seperate process:
Start a service in a separate process android

Related

why android service is stopped by Android OS?

OK, here is my code, I'm trying to create a running service even when the app is closed.
In main activity, I have created a new button and call startMyService() to start the service as following:
public void startMyService(View view) {
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
}
the Service class is simple :
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("MyService", "service is running");
final Uri uri = Settings.System.DEFAULT_RINGTONE_URI;
final Context x =(Context) MyService.this;
new Thread(new Runnable() {
#Override
public void run() {
MediaPlayer player = MediaPlayer.create(x,uri);
player.setLooping(true);
player.start();
}
}).start();
Toast.makeText(getApplicationContext(), "Service is running", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
Log.e("MyService", "service done");
}
}
Of course, I have added the service to manifest
<service android:name=".MyService" android:exported="false" android:description="#string/service_description" />
Now after running, I pressed the button to start the service, and close the activity, I supposed the music will be playing in the background but it stopped just after closing the activity.
How to solve this issue? How to make the service still running, and how to make it running again after an android OS destroying it?
I know there are too many topics about android services and START_STICKY
However, as you see this is not working in code above, why?
Note: This is not about playing music in the background, I used playing music because it is the simplest way to know when service is stopped, this is about how to make service keeps running in the background as supposed to be, for example, to do some task like tracking data changes from the server.
It's normal behavior when your application target from android O, if you want to remain your Service you should use startForgroundService with Notification. Read here
While an app is in the foreground, it can create and run both foreground and background services freely. When an app goes into the background, it has a window of several minutes in which it is still allowed to create and use services. At the end of that window, the app is considered to be idle. At this time, the system stops the app's background services, just as if the app had called the services' Service.stopSelf() methods.

keeping a service running after shutting down the app

i'm trying to create an app that communicates with my localhost and search in a database.
I already make the connection and find the data, but i need to stay connected and send a notification if there's any changes in the table, but I can't figure it out how to keep the connection even when I close the app, because it closes everything, even the service.
The service doesn't stay open.
This is my Class:
public class SensorService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"Starting",Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
boolean bandera = true;
Toast.makeText(this, "Checking data...", Toast.LENGTH_SHORT).show();
return START_STICKY;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
stopService(new Intent(this,SensorService.class));
startService(new Intent(this,SensorService.class));
}
#Override
public void onDestroy() {
startService(new Intent(this,SensorService.class));
}
}
Every time I close the app, the service execute one more time and no more.
If you want the service to continue running after the app is closed, you need to call the startForeground(int, Notification) method from within the service. Android limits you to running longer running services in the background only as long as a notification is displayed to the user letting them know that a service is running (like a music player or a downloading service).
This is an intentional design constraint to ensure developers do not start services in the background that run indefinitely without the user being aware. Supply your own notification (can be anything) and you should be able to run the service in the background.
For more detailed information on this method, read it at: startForeground(int, Notification)
You can use onTaskRemoved and restart the service if needed.
#Override
public void onTaskRemoved(Intent rootIntent){
super.onTaskRemoved(rootIntent);
//restart your service
}
Please note that if you use onTaskRemoved, start your service as not sticky so it won't be restarted.
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_NOT_STICKY;
}

music pause when app killed when using service

I am using a Service class to play music in the background. While I am displaying the notification bar on top, there is issue in my app. When I kill the app, the music stops for about 1 second and then it starts again. I can't figure out what's the issue.
I was following this tutorial.
public class MyMusicService extends Service {
MediaPlayer mediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public MyMusicService() {
super();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (mediaPlayer!= null)
{
mediaPlayer.release();
}
mediaPlayer =MediaPlayer.create(this,R.raw.song);
mediaPlayer.setLooping(true);
mediaPlayer.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
}
}
Use onTaskRemoved on your main activity and release your mediaplayer on this event.
That tutorial shows you how to build a BACKGROUND service, which can get killed by the system. To play music you should use a FOREGROUND service.
https://developer.android.com/guide/components/services.html#Foreground
According to: https://developer.android.com/reference/android/app/Service.html
Change
START_STICKY
to
START_NOT_STICKY
EDIT:
The issue with music stopping for a while is connected with the fact that you run app and service in the same process. And 'killing app' means stopping the whole process bound to it. What you need to do is to run your service in seperate process:
Start a service in a separate process android

The same background music playing in all activities

I use services to play background music in all activities and it works. The problem is the music continues playing even if my app is in background (when user exit with home button or back button). How can I solve this?
Services class BackgroundSoundService
public class BackgroundSoundService extends Service {
private static 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.slow_shock);
player.setLooping(true); // Set looping
player.setVolume(100,100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return START_NOT_STICKY;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
}
public void onPause() {
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
Starting with
Intent svc = new Intent(this, BackgroundSoundService.class);
startService(svc);
Android Manifest:
<service android:enabled="true" android:name=".BackgroundSoundService" />
This is happened because the Service is still bounded in the activity. To terminate the service when multiple activity is bound to the service, you need to unbind the service from all of them as in the documentation says:
The service lifecycle—from when it's created to when it's
destroyed—can follow either of these two paths:
A started service
The service is created when another component calls startService().
The service then runs indefinitely and must stop itself by calling
stopSelf(). Another component can also stop the service by calling
stopService(). When the service is stopped, the system destroys it.
A bound service
The service is created when another component (a client) calls
bindService(). The client then communicates with the service through
an IBinder interface. The client can close the connection by calling
unbindService(). Multiple clients can bind to the same service and
when all of them unbind, the system destroys the service. The service
does not need to stop itself.
These two paths are not entirely separate. You can bind to a service
that is already started with startService(). For example, you can
start a background music service by calling startService() with an
Intent that identifies the music to play. Later, possibly when the
user wants to exercise some control over the player or get information
about the current song, an activity can bind to the service by calling
bindService(). In cases such as this, stopService() or stopSelf()
doesn't actually stop the service until all of the clients unbind.
Then call Context.stopService() to stop it:
context.stopService(new Intent(context, BackgroundSoundService.class));

Service and MediaPlayer - Control screen rotation and App exit

SOLVED - See answer.
I'm dealing with an app that uses a service for playing music with the MediaPlayer class.
I'm having problem with screen rotation and when I leave the app. I lose the reference or state of the MediaPlayer object or the service itself. Been working so many hours with this that not really know what is wrong.
I start and bind to the service in Activity's onResume:
#Override
protected void onResume()
{
Intent intent=new Intent(getApplicationContext(), MusicService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
super.onResume();
}
I get the reference to the service with a ServiceConnection:
private ServiceConnection serviceConnection=new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder binder)
{
service=((MusicService.MyBinder)binder).getService();
}
public void onServiceDisconnected(ComponentName className)
{
service=null;
}
};
At this point I can call any method from my service: service.playMusic(); and works fine.
I unbind in onDestroy:
#Override
protected void onDestroy()
{
unbindService(serviceConnection);
super.onDestroy();
}
And this is my Service class:
public class MusicService extends Service
{
private final IBinder binder=new MyBinder();
private MediaPlayer player;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return Service.START_REDELIVER_INTENT;
}
#Override
public IBinder onBind(Intent intent)
{
player=MediaPlayer.create(getApplicationContext(), R.raw.tumbler);
player.setLooping(true);
player.setVolume(80, 80);
return binder;
}
public class MyBinder extends Binder
{
public MusicService getService()
{
return MusicService.this;
}
}
public void play()
{
player.start();
Log.d("MUSIC SERVICE", "play!");
}
}
So, problems are:
When I exit, the service and music keeps playing. I want to stop it. If I enter the app again, same service is launched again and the music is playing twice. I want to stop it.
When I rotate the screen, the MediaPlayer keeps playing (as I want) but I can't call anymore pause(), start() and so on because it state has changed (I get the message ' MediaPlayer﹕ pause called in state 8' and `MediaPlayer﹕ start called in state 0').
Please, need some help with this. Thanks in advance!
#Override
public IBinder onBind(Intent intent) {
player=MediaPlayer.create(getApplicationContext(), R.raw.tumbler);
player.setLooping(true);
player.setVolume(80, 80);
return binder;
}
You're re-initializing the MediaPlayer every time you bind to the service and never stopping the previous instance. Don't start the media in onBind(), wait for a command to the service to start/stop the media player. Services outlive the Activity (that's what they're designed for) so it's no surprise that it keeps playing after the Activity is destroyed. Unless you specifically told it otherwise, that's the expected behavior. If you're wanting a media player that just keeps going while the Activity is open, you might want to look into using a headless Fragment to keep a retained Fragment that can manage the MediaPlayer for you in onCreate()/onDestroy().
Well I think I got it.
I had a mess in my mind (and code) but finally it's working.
If this is not the correct way to do this, please let me know.
The first of my problems was: When the App exits the Service wasn't destroyed and the MediaPlayer was playing until I force-close the App. If I didn't force-close, on App relaunch I had 2 MediaPlayers playing simultaneously and so on.
Cause: I was not terminating my Service manually.
Solution: On Activity's onDestroy(), call unbindService() and stopService():
#Override
protected void onDestroy()
{
super.onDestroy();
unbindService(serviceConnection);
stopService(new Intent(getApplicationContext(), MusicService.class));
}
The second problem was: When the screen was rotated I lost the MediaPlayer's object reference, and music was out of control because I couldn't access the object.
Cause: Bad design. I was setting up the MediaPlayer into Service's onBind() method. Thanks to #kcoppock. He noticed that. So, when the screen was rotated, Activity's onCreate() was called and I have bindService() on it, causing the creation of the new MediaPlayer object without even cleaning up the former instance.
Solution: Just move out that code to another part that is not called automatically, and call it manually once, when the App starts, and not every time that Activity is recreated by configChanges.
So, basically that is how I fixed it, hope it may help to other users.
Cheers.

Categories

Resources