The same background music playing in all activities - android

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));

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.

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

Music Background service bug when app killed [duplicate]

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

Android Service with MediaPlayer gets recreated or destroyed

I'm using bound service so that I am able to communicate between an activity and a service.
I'm binding to a service in onStart:
#Override
protected void onStart() {
super.onStart();
Intent bindIntent = new Intent(this, MusicService.class);
bindService(bindIntent, this, BIND_AUTO_CREATE);
}
waiting for service to bind:
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMusicService = ((MusicService.LocalBinder) service).getService();
mMusicService.setCallback(this);
}
handling disconnect from service:
#Override
public void onServiceDisconnected(ComponentName name) {
mMusicService = null;
}
unbinding from service in onDestroy:
#Override
protected void onDestroy() {
super.onDestroy();
if (mMusicService != null && isFinishing()) {
mMusicService.setCallback(null);
unbindService(this);
}
}
My problem is that when app is minimized, onDestroy gets called immediately and then onUnbind in Service gets called and music is stopped.
Here is onUnbind method (where mPlayer is MediaPlayer):
#Override
public boolean onUnbind(Intent intent) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
return super.onUnbind(intent);
}
If I don't implement onUnbind music continues to play (sometimes and sometimes it stops after some time) and when I open the app again (from minimized applications) I am able to play another song and then those two song play at same time.
I've red couple articles about music players and services on android and I thought that this was correct approach (thinking that onDestroy will be called when OS is out of memory).
Any ideas how I can re-implement my app workflow so that I will work as expected?
EDIT
At first I thought that "Don't keep activities" under developer options is a problem, but problem is still there even if I uncheck it.
And if some code from my service is needed please say I will edit my question (there's a lot of code and I'm not sure which part is important for this issue)
SOLUTION:
startForeground(<notification id>, <notification>);
to run service even if app gets killed. And when user dismisses the notification:
stopForeground(true);
stopSelf();
More about startForeground here.
It's not obvious, but you should start a Thread that runs in background and use the service to control it's state.
A service isn't a thread that hold some run state like a thread. Unless it's an IntentService. (Correct me if I'm wrong)
While activity can (and probably will) get destroyed, your app will keep running.
Activity:
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, BackgroundService.class);
startService(intent);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
finishOnPause = true;
}
#Override
protected void onStop() {
super.onStop();
unbindService(mServiceConnection);
}
Service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
ensureServiceThread();
if (intent != null) {
}
return START_NOT_STICKY;
}
private void ensureServiceThread() {
if (service_thread == null) {
service_thread = new ServiceThread(this);
service_thread.start();
}
}
#Override
public void onDestroy() {
stopServiceThread();
super.onDestroy();
}
private void stopServiceThread() {
if (service_thread != null) {
service_thread.interrupt();
service_thread = null;
}
}
And you should do your work inside the Thread.
If you need context, it's your Service.
If you need to do something on Main thread - create a Handler in Service.OnCreate and do a handler.postRunnable inside a worker thread safely.
What I would do is:
- Create a service
- Create a thread
- Create a media player inside a thread (if possible, otherwise on Service creation and pass it to thread)
- Inside a thread - continuously poll media player state
- On song finished send an intent to service that change track
- stop thread/service if needed.

When is a started and bound Service destroyed?

I was going through the services documentation in android when I noticed two contradicting points:
In the services document it is specified in Managing the Lifecycle of a Service
These two paths are not entirely separate. That is, you can bind to a
service that was already started with startService(). For example, a
background music service could be started 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 like this, stopService() or
stopSelf() does not actually stop the service until all clients
unbind.
But in the document about bound services in Managing the Lifecycle of a Bound Service
However, if you choose to implement the onStartCommand() callback
method, then you must explicitly stop the service, because the service
is now considered to be started. In this case, the service runs until
the service stops itself with stopSelf() or another component calls
stopService(), regardless of whether it is bound to any clients.
It may be me but I think the statements are contradictory.Could anyone please clarify...
Agree that the documentation could be clearer. What they are trying to say is:
If you call startService(), then the service will keep running unless and until you call stopSerivce() (or stopSelf() from within the service)
If you call bindService(), then the service will keep running unless and until you call unbindService()
Therefore, if you call both startService() and bindService(), then the service will keep running until you call both stopService and unbindService(). Neither on its own will stop the service.
Created a very simple Activity and Service and ran the following sequences of start/stop/bind/unbind. I observed that the calls gave the following results.
bind-unbind
bindService() caused:
onCreate()
onBind()
unbindService() caused:
onUnbind()
onDestroy()
start-bind-unbind-stop
startService() caused:
onCreate()
onStartCommand()
bindService() caused:
onBind()
unbindService() caused:
onUnbind()
stopService() caused:
onDestroy()
start-bind-stop-unbind
startService() caused:
onCreate()
onStartCommand()
bindService() caused:
onBind()
stopService() caused:
-- nothing
unbindService() caused:
onUnbind()
onDestroy()
bind-start-stop-unbind
bindService() caused:
onCreate()
onBind()
startService() caused:
onStartCommand()
stopService() caused:
-- nothing -- still running
unbindService() caused:
onUnbind()
onDestroy()
bind-start-unbind-stop
bindService() caused:
onCreate()
onBind()
startService() caused:
onStartCommand()
unbindService() caused:
onUnbind()
stopService() caused:
onDestroy()
As you can see, in each case where both bind and start were called, the service kept running until both unbind and stop were called. The sequence of unbind/stop is not important.
Here is the example code that was called from separate buttons in my simple test app:
public void onBindBtnClick(View view) {
Intent intent = new Intent(MainActivity.this, ExampleService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
public void onUnbindBtnClick(View view) {
if (serviceIsBound) {
unbindService(serviceConnection);
serviceIsBound = false;
}
}
public void onStartBtnClick(View view) {
Intent intent = new Intent(MainActivity.this, ExampleService.class);
startService(intent);
}
public void onStopBtnClick(View view) {
Intent intent = new Intent(MainActivity.this, ExampleService.class);
exampleService.stopService(intent);
}
Actually, both paragraphs complement each other (although their wording might be misguiding), and both paragraphs are consistent with the image from the documentation. Let's have a look:
These two paths are not entirely separate. That is, you can bind to a service that was already started with startService(). For example, a background music service could be started 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 like this, stopService() or stopSelf() does not actually stop the service until all clients unbind.
The quintessence is: If you start a service, then bind a client to it, then try to stop it, the service is not stopped (destroyed) before all clients unbind. The second paragraph does not contradict, it refines this statement.
However, if you choose to implement the onStartCommand() callback method, then you must explicitly stop the service, because the service is now considered to be started. In this case, the service runs until the service stops itself with stopSelf() or another component calls stopService(), regardless of whether it is bound to any clients.
This means: A started and bound service runs even if no clients are bound to it until it is explicitely stopped. Granted, the wording might probably be a bit clearer on this. The lifecycle diagram given in the documentation however shows this (and I am pretty sure I already observed this in "real-life", although I am currently have no direct example on top of my head):
Yep, it works.
I want to complete with a sample code :
I had to make an app with a service started by an activity, the activity have to call some methods in the service, the service have to run in background even if the activity were killed, and when the activity restarts, it haven't to restart the service if it is running. I hope it will help you, you can see how does it work with the Log.
So that is the code :
public class MyActivity extends Activity{
private MyService myService;
private boolean mIsBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
MyService.MyBinder b = (MyService.MyBinder) binder;
myService = b.getService();
mIsBound = true
//Do something
// Here you can call : myService.aFonctionInMyService();
}
public void onServiceDisconnected(ComponentName className) {
// Do something
mIsBound = false;
}
}
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
//Checked if my service is running
if (!isMyServiceRunning()) {
//if not, I start it.
startService(new Intent(this,MyService.class));
}
}
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
if (MyService.class.getName().equals(
service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
doBindService();
}
//Connection to the Service
private void doBindService() {
bindService(new Intent(this,MyService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
// Disconnection from the service
private void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
}
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
doUnbindService();
super.onPause();
}
}
public class MyService extends Service{
public static String Tag = "MyService";
private final IBinder mBinder = new MyBinder();
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.d(Tag, "onCreate()");
}
public class MyBinder extends Binder {
public LocationService getService() {
return LocationService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d(Tag, "onBind()");
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d(Tag, "onUnBind()");
return super.onUnbind(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.d(Tag,"onStartCommand()");
return START_STICKY;
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d(Tag, "onDestroy");
super.onDestroy();
}
public void aFonctionInMyService(){
//Do Something
}
}

Categories

Resources