Resume music using Service when we Resume the application - android

I'm developing an application, which plays music in the background by using service.
Music stops when we hit back app will be paused and but, music is not resuming when I get back to the application.
public class backService extends Service implements ComponentCallbacks2 {
private MediaPlayer mp;
SharedPreferences sharedpreferences;
public Boolean musicSwitch;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mp != null){
mp.stop();
mp.release();
}
}
#Override
public void onCreate() {
super.onCreate();
sharedpreferences = getSharedPreferences(mypreference,
Context.MODE_PRIVATE);
musicSwitch = sharedpreferences.getBoolean("music", true);
if(musicSwitch){
mp = MediaPlayer.create(this, R.raw.all);
mp.setLooping(true);
mp.start();
}
}
#Override
public void onTrimMemory(final int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
if(mp != null){
mp.pause();
}
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I want the application to resume music when we get back to the application, I have tried using onResume method, but there is no onResume method in services.
TIA

1) You need to create foreground service to prevent it from killing by OS
How can we prevent a Service from being killed by OS?
2) You can bind service (bindService(serviceIntent)) and use Binder interface
https://developer.android.com/guide/components/bound-services.html#Binder
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
Activity:
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
unbindService(mConnection);
mBound = false;
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
}
}
3) Then, in your activity onResume you can call method from your Binder to control music

Related

I want the instance of the Background service which is running

In this, the service is been create repeated times but I need to get the instance of running service so that I can start the timer task. The object of this service can get from any activity. The basic aim is to start the timer task after the particular button click.
public class MainActivity extends Activity {
MyService mService;
boolean mBound = false;
int b=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_start_timer).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mBound) {
mService.runTimerTask(++b);
}
}
});
}
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, MyService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
unbindService(mConnection);
mBound = false;
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
MyService.LocalBinder binder = (MyService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
You could create a ServiceManager class and route all methods through that and store it in the application:
public class YourApplication extends Application {
...
private ServiceManager serviceManager = ...;
public ServiceManager getServiceManager() {
return serviceManager;
}
}
In MainActivity:
ServiceManager serviceManager = ((YourApplication)getApplication()).getServiceManager();
MyService runningService = serviceManager.getRunningService();
The ServiceManager would handle unbinding etc and all methods that involve the state of the service. So you just ask the ServiceManager for the running service. Where you have ServiceConnection::onServiceConnected doing the work, delegate that work to the ServiceManager so it can keep state and share it with the rest of the application:
public void onServiceConnected(ComponentName className,
IBinder service) {
((YourApplication)getApplication()).getServiceManager().bind(service);
}
It's a general technique for sharing object state across an application but you'd need to tailor it to fit.

Android service binding

I have Problem understanding the Binding to a service
I've created a simple song player, with a service to play the song.
I've created a log to track the binding and unbinding.
the problem is when i exit the app Unbinding log appears but when i go back to the app there is no binding log message ,i'm able to control play and pause of the song though
public class PlayService extends Service {
MediaPlayer mPlayer;
public IBinder mBinder=new LocalBinder();
#Override
public void onCreate() {
super.onCreate();
Log.i("TAG","Create");
mPlayer=MediaPlayer.create(this,R.raw.askme);
}
//since we want the song to be played in the background then we need to start the service
#Override
public int onStartCommand(Intent intent,int flags, int startId) {
Log.i("TAG","Start");
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopSelf();
}
});
return Service.START_NOT_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.i("TAG","Bind");
return mBinder;
}
#Override
public boolean onUnbind(Intent intent) {
Log.i("TAG","Unbind");
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
Log.i("TAG","ReBind");
super.onRebind(intent);
}
#Override
public void onDestroy() {
Log.i("TAG","Destroy");
mPlayer.release();
super.onDestroy();
}
//here are the play and pause methods frm the user
public void playSong(){
mPlayer.start();
}
public void pauseSong(){
mPlayer.pause();
}
public boolean isPlaying(){
return mPlayer.isPlaying();
}
//since Binder already Extends IBinder so
//we can create LocalBinder Class which extends IBinder Interface
public class LocalBinder extends Binder{
//this method for returning an instance of our service in the MainActivity
public PlayService getService(){
return PlayService.this;
}
}
}
and main Activity as following
public class MainActivity extends AppCompatActivity {
public static final String TAG ="TAG" ;
public PlayService mPlayService;
private Button mDownloadButton;
private Button mSongButton;
private boolean mBound=false;
private ServiceConnection mServiceConnection=new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//the iBinder object is the returned value from onBind() method in our service
mBound=true;
//we need to get an instance of our service PlayerService so we can play or Pause the song
PlayService.LocalBinder binder = (PlayService.LocalBinder) iBinder;
//and here finally we are getting an instance of our service
mPlayService= binder.getService();
if (mPlayService.isPlaying()){
mSongButton.setText("Pause");
}
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBound=false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDownloadButton=(Button) findViewById(R.id.download_button);
mSongButton=(Button) findViewById(R.id.song_button);
mDownloadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(MainActivity.this,"downloading",Toast.LENGTH_LONG).show();
for (String song:Playlist.songs){
Intent intent=new Intent(MainActivity.this,StartDownloadService.class);
intent.putExtra(TAG,song);
startService(intent);
}
}
});
mSongButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//here we can play or Pause the song
//but first we need to know if we are already bound to the service
if (mBound){
if (mPlayService.isPlaying()){
mPlayService.pauseSong();
mSongButton.setText("Play");
}else {
//but here we need the service to be started and keep playing in the background
//even if we unbound from the service when we exit the App
Intent intent=new Intent(MainActivity.this,PlayService.class);
startService(intent);
mPlayService.playSong();
mSongButton.setText("Pause");
}
}
}
});
}
#Override
protected void onResume() {
Intent intent=new Intent(this,PlayService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
super.onResume();
}
#Override
protected void onStop() {
super.onStop();
if (mBound){
unbindService(mServiceConnection);
mBound=false;
}
}
}
if someone can explain
You are starting your service twice in your code.
Once as a started service and then as a bind service. Remove the started service code and most probably it should work as intended.
Remove this from your code
Intent intent=new Intent(MainActivity.this,PlayService.class);
startService(intent);
mPlayService.playSong();
mSongButton.setText("Pause");
as you are binding service in on Resume() method.
Intent intent=new Intent(this,PlayService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
You should start and bind your music service like this:
#Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart invoked !");
// Start/Bind to play back service
Intent serviceIntent = new Intent(this, PlayService.class);
if (isMyServiceRunning(PlayService.class)
&& mBound== false) {
this.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
} else {
this.startService(serviceIntent);
this.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
Log.i(TAG, "Media Player service is created new -------------------");
}
}
#Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop invoked !");
if(mBound) {
Log.i(TAG, "unbinding service !");
unbindService(mServiceConnection);
mBound= false;
}
}
To Check service is running or not:
/**
* Utility function to check if a service is running.
*/
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Hope this will help you !
I found the Reason
the system calls your service's onBind() method to retrieve the IBinder only when the first client binds. The system then delivers the same IBinder to any additional clients that bind, without calling onBind() again.
that's why i'm not getting the Log message from onBind() and onUnbind() method, but I've used a log message in onServiceConnected() and i got it when i ran the App again.

Android , communicating with background service

I have background service which started on device boot . I want to get some data from that service in my activity .
I want the data, only when my activity start. so the basic requirement is that when my activity start it make a connection with the background service and get the data from this service and when activity stop then disconnect from the service.
You need to use bindService() to bind with running service and communicate with it.
Reference : http://developer.android.com/guide/components/bound-services.html
For example (from Android Docs),
public class BindingActivity extends Activity {
YourService mService;
boolean mBound = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
#Override
protected void onStart() {
super.onStart();
// Bind to Your Service
Intent intent = new Intent(this, YourService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from your Service.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to the running Service, cast the IBinder and get instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
In your service,
public class LocalService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
Basically, you should use bindService() in your activity onStart() and unbindService() in onStop()

My background music service stops when I load a new activity. Am I connecting or binding wrong?

I'm trying to add background music to my game and I thought I could persist it across activities by starting the service and then just connecting and binding to it in different activities in order to control it. But my music stops playing when I try to establish a connection from my second activity. I'm very new to working with services, so I apologize for any simple mistakes.
From my MusicService class (extends Service)
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public static boolean STOP_ON_DESTROY = true;
// Binder subclass. Allows access from clients to the server
public class ServiceBinder extends Binder {
MusicService getService(){
return MusicService.this;
}
}
public MusicService() {}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate(){
super.onCreate();
}
#Override
public int onStartCommand (Intent intent, int flags, int startId)
{
return START_STICKY;
}
public boolean isPlaying(){
if(mPlayer != null){
return mPlayer.isPlaying();
}
return false;
}
public void stopMusic()
{
if(mPlayer != null){
if(mPlayer.isPlaying()) {
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
System.out.println("stopMusic service fn");
}
}
This is the code I call in both my Main and secondary activities in order to interact with the service. The music stops during the connectToMusicService function in the secondary activity. The Main activity works great.
onCreate(){....
startMusicService();
MusicService.STOP_ON_DESTROY = true;
}
private void startMusicService() {
Intent musicIntent = new Intent();
musicIntent.setClass(getApplicationContext(), MusicService.class);
startService(musicIntent);
}
#Override
public void onStart(){
super.onStart();
// establish connection for binding to the service
connectToMusicService();
// bind to the service
bindToMusicService();
}
private void bindToMusicService() {
Intent intent = new Intent(this, MusicService.class);
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);
MusicService.STOP_ON_DESTROY = true;
}
private void connectToMusicService() {
myServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.ServiceBinder binder = (MusicService.ServiceBinder) service;
mService = binder.getService();
if(!mService.isPlaying())
mService.startMusic();
isServiceBound = true;
}
#Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("Service disconnected from main");
isServiceBound = false;
}
};
}
The only thing I do during my Main activity's onStop is
#Override
public void onStop(){
super.onStop();
if(mService != null) {
if (MusicService.STOP_ON_DESTROY) {
mService.stopMusic();
}
}
}
UPDATE: I got it working. My issue wasn't with service binding at all. It was with static STOP_ON_DESTROY variable I was using to manage whether the music should stop when leaving an activity. I cleaned that up and all is good now. Thanks!
First of all, do you need to bind at all? Or could starting the service be enough? Started services run until you stop them (except if killed by the system when resources are scarce). I am not sure there's any point binding from each of your activities.
Btw if your service should run and play music also when your activities are closed, consider making it a foreground service.

Android, why is background thread stopped?

MainActivity starts my TestService in onCreate and bind in onStart method. AsyncThread is started in TestService onStartCommand. bind and unbind methods are called in correct sequences. All things work perfectly, absolutely no issue :).
Issue starts from here: If MainActivity is terminated then running Async thread is also stopped w/o any interrupt exception but TestService is still running which I can check at Running Application Setting.
Please help me to find out why thread stops working.
PS: I cross checked with Thread/Handler but same result.
MainActivity and Service code are here:
public class MainActivity extends Activity implements IServiceInterface {
boolean mBound = false;
TestService mTestService = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
Intent serviceIntent = new Intent(this, TestService.class);
startService(serviceIntent);
}
#Override
protected void onStart() {
super.onStart();
// Bind to LocalService
NSLogger.i("service binding....");
Intent intent = new Intent(this, TestService.class);
bindService(intent, mBindConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
NSLogger.i("service unbinding....");
unbindService(mBindConnection);
mBound = false;
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mBindConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
NSLogger.i("UI is connected to service");
LocalBinder binder = (LocalBinder) service;
mTestService = binder.getTestService();
mBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
NSLogger.i("UI is disconnected from service");
mBound = false;
mTestService = null;
}
};
}
public class TestService extends Service implements Runnable, Handler.Callback{
// Binder given to inproc clients
private final IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
mUIIsBound = true;
return mBinder;
}
public boolean onUnbind (Intent intent) {
mUIIsBound = false;
NSLogger.i("unbind service");
return true;
}
public class LocalBinder extends Binder {
TestService getTestService() {
return TestService.this;
}
}
public void onDestroy() {
//NEVER CALLED.
}
public int onStartCommand(Intent intent2, int flags, int startId) {
NSLogger.i("TestService start!");
new DownloadConfiguration().execute();
return START_STICKY;
}
private class DownloadConfiguration extends AsyncTask<Void, Integer, Boolean> {
#Override
protected Boolean doInBackground(Void... params) {
try {
NSLogger.i("before sleep");
Thread.sleep(5000);
NSLogger.i("After sleep");
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
}

Categories

Resources