I'm trying to play an mp3 when app is closed. It works when I'm out of the app but when i swipe it off from task manager the song ends. How can I make the service continue playing after close?
This is my service:
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.d("MusicService", "onTaskRemoved");
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
This is my main activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button)findViewById(R.id.start);
stop = (Button)findViewById(R.id.stop);
mp = MediaPlayer.create(getApplicationContext(),R.raw.gucci);
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startService(new Intent(MainActivity.this,MyService.class));
mp.start();
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mp.pause();
stopService(new Intent(MainActivity.this,MyService.class));
}
});
}
NOTE: Other way may be not usable (ignore if not usable).
Don't give user the option to clear it from recents menu.
Use this manifest attribute for each activity component in your Player app
android:excludeFromRecents
just return START_STICKY in onstartcommand method of your service class . it will run forever in background .
Related
I have a service, which plays background music in all of my app's activities.
In every activity I added:
public void onPause() {
super.onPause();
stopService(new Intent(OpenerPlay.this, MusicDoctorService.class));
}
public void onStop() {
super.onStop();
stopService(new Intent(OpenerPlay.this, MusicDoctorService.class));
}
public void onResume() {
super.onResume();
startService(new Intent(OpenerPlay.this, MusicDoctorService.class));
}
public void onRestart() {
super.onRestart();
startService(new Intent(OpenerPlay.this, MusicDoctorService.class));
}
My purpose was to stop or resume service which plays music when I close the app or turn off the screen. But It also stops when I switch to another activity.
Should I change something in my service's code?
Finally: I would like my service playing music to stop on screen turn off or app closing but not during activities switching.
Service:
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.music);
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() {
}
}
Try this in your Activity's onDestroy Method...
#Override
protected void onDestroy() {
super.onDestroy();
if(isMyServiceRunning(MyService.class))
{
stopService(new Intent(this, MyService.class));
}
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Here when the Activity is finished you should stop the service..
Also in your service you should release the mediaplayer
#Override
protected void onPause() {
super.onPause();
if (mediaPlayer != null){
mediaPlayser.stop();
if (isFinishing()){
mediaPlayer.stop();
mediaPlayer.release();
}
}
}
How to make service (background music) to turn off when I close the app or turn off the screen, but not when I switch to another activity?
Currently Music plays fine, I lasts until the screen turn off or I close the app, but also close when I switch to another activity. It is probably caused by onStop and onPause assigned to every activity. Please help me solve this issue
My service:
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.music;
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() {
}
}
My example activity has this:
public void onPause() {
super.onPause();
stopService(new Intent(a.this, MyService.class));
}
public void onStop() {
super.onStop();
stopService(new Intent(a.this, MyService.class));
}
public void onResume() {
super.onResume();
startService(new Intent(a.this, MyService.class));
}
public void onRestart() {
super.onRestart();
startService(new Intent(a.this, MyService.class));
}
There are two ways i can suggest
1) let it be in onPause(), create a flag/boolean that will set to false by default and will be true in every-case such as new activity startup, on back press etc. so if onPause is called and flag is false you can stop the music.
2) you have background service already, you can keep checking which activity is in foreground, if is homeScreen you can stop the music.
Edit :- to know if your app is not in the foreground
check this link
this is good example
Use this code.
Remove this line:
player.pause();
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.music;
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() {
}
}
i would developing a feature in my app that when click on button on my activity launch a service that start,pause and resume a Chronometer.
But I have a problem how start and stop in my background service.
I created my Activity
public class StartWorkActivity extends ActivityGeneralToolbar {
protected final void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState, R.layout.activity_start_work);
Chronometer chronometer = (Chronometer) findViewById(R.id.chronometer);
}
#Override
protected void onStop() {
super.onStop();
}
public void startWork(View v){
Intent msgIntent = new Intent(StartWorkActivity.this, WorkTimerService.class);
msgIntent.setAction("START_TIMER");
getBaseContext().startService(msgIntent);
}
public void pauseWork(View v){
Intent msgIntent = new Intent(StartWorkActivity.this, WorkTimerService.class);
msgIntent.setAction("PAUSE_TIMER");
}
public void resumeWork(View v){
//call service
Intent msgIntent = new Intent(StartWorkActivity.this, WorkTimerService.class);
msgIntent.setAction("RESUME_TIMER");
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
}
And my WorkTimerService
public class WorkTimerService extends IntentService {
long timeWhenStopped = 0;
Chronometer chronometer;
public WorkTimerService() {
super("SystemService");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
protected void onHandleIntent(Intent intent) {
if(intent.getAction() == "START_TIMER"){
startWork();
}
if(intent.getAction() == "PAUSE_TIMER"){
pauseWork();
}if(intent.getAction() == "RESUME_TIMER"){
resumeWork();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags,startId);
return START_STICKY;
}
public void pauseWork(){
timeWhenStopped = chronometer.getBase() - SystemClock.elapsedRealtime();
chronometer.stop();
}
public void resumeWork(){
chronometer.setBase(SystemClock.elapsedRealtime() + timeWhenStopped);
timeWhenStopped = 0;
chronometer.start();
}
public void startWork(){
chronometer.start();
}
}
But my problem is that Chronometer obviously is null in my service, because I read that is not possible, in the service, interact with the ui.
And so, how i can send, or work with Chronometer in background?
Chronometer is a UI widget (actually a TextView) in Android. So, you can't use it for non-UI purposes. Try to use Timer or CountDownTimer instead.
See this for an example usage of Timer inside Service: https://stackoverflow.com/a/3819721/5250273
I run the code and get the following result, but I hope that the App can run at the order "A" -> "Service OnDestroy" -> "B" -> "C", how can I do ?
In My Way 2 section, I try to place the code into the function new Handler().postDelayed(new Runnable() {}, it's OK , it ran at the order "A" -> "Service OnDestroy" ->"B" ->"C",
I don't konw why the way can success, I don't know if the way is good way!
Result
11-13 10:04:32.137 27947-27947/info.dodata.screenrecorder E/My﹕ A
11-13 10:04:32.147 27947-27947/info.dodata.screenrecorder E/My﹕ B
11-13 10:04:32.157 27947-27947/info.dodata.screenrecorder E/My﹕ C
11-13 10:04:32.157 27947-27947/info.dodata.screenrecorder E/My﹕ Service OnDestroy
UIAbou.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
stopService(intent1);
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
});
}
}
RecordService.cs
public class RecordService extends Service {
private Context mContext;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My","Service OnDestroy");
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
}
=======================My Way 1 ======================================
I set a mark isServiceStoped to monitor if Stop Service is finished, but my app is hang up after disply the result "11-13 11:31:23.107 7599-7599/info.dodata.screenrecorder E/My﹕ A"
New UIAbout.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
while (RecordService.isServiceStoped==false){
//It block
}
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
});
}
}
New RecordService.cs
public class RecordService extends Service {
public static boolean isServiceStoped=true;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My", "Service OnDestroy");
isServiceStoped=true;
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
isServiceStoped=false;
return super.onStartCommand(intent,flags,startId);
}
}
=====================My Way 2==========================================
I try to place the code into the function new Handler().postDelayed(new Runnable() {}, it's OK , it ran at the order "A" -> "Service OnDestroy" ->"B" ->"C",
I don't konw why the way can success, I don't know if the way is good way
The last UIAbout.cs
public class UIAbout extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
new Handler().postDelayed(new Runnable() {
public void run() {
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
}, 1);
}
});
}
}
The last RecordService.cs
public class RecordService extends Service {
private Context mContext;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate(){
}
#Override
public void onDestroy(){
Log.e("My", "Service OnDestroy");
super.onDestroy(); //It seems that the APP is OK if I remove this.
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
}
}
No, you can't stop a service synchronously. stopService() is request to stop the service. It will stop sometime later, as soon as it can.
No, you can't remove super.onDestroy() from your onDestroy() method and still have it work properly.
You can not control the timing to completely stop the running service. Use stopService() and the rest is out of your hands. You can use an handler to monitor is the service has stopped before moving to B although I am not sure why would you do it. Not a good practice.
Yeah you can remove super.onDestroy() in onDestroy but I would not advise you to do so. Your app may run but it will be leaving unwanted resources around.
Here how onDestroy() looks like in the android SDK:
#CallSuper
protected void onDestroy() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onDestroy " + this);
mCalled = true;
// dismiss any dialogs we are managing.
if (mManagedDialogs != null) {
final int numDialogs = mManagedDialogs.size();
for (int i = 0; i < numDialogs; i++) {
final ManagedDialog md = mManagedDialogs.valueAt(i);
if (md.mDialog.isShowing()) {
md.mDialog.dismiss();
}
}
mManagedDialogs = null;
}
// close any cursors we are managing.
synchronized (mManagedCursors) {
int numCursors = mManagedCursors.size();
for (int i = 0; i < numCursors; i++) {
ManagedCursor c = mManagedCursors.get(i);
if (c != null) {
c.mCursor.close();
}
}
mManagedCursors.clear();
}
// Close any open search dialog
if (mSearchManager != null) {
mSearchManager.stopSearch();
}
getApplication().dispatchActivityDestroyed(this);
}
* Sample *
There could be some compile errors, but you will get the idea.
public class UIAbout extends Activity {
private Handler mHandler = new Handler();
private Runnable checkServiceHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_about);
Intent intent1 = new Intent(UIAbout.this,bll.RecordService.class);
startService(intent1);
Button btnReturn = (Button) findViewById(R.id.btnReturn);
btnReturn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("My", "A");
Intent intent1 = new Intent(UIAbout.this, bll.RecordService.class);
stopService(intent1);
checkServiceHandler = new Runnable() {
public void run() {
if(RecordService.isServiceStoped){
mHandler.removeCallbacks(checkServiceHandler );
somemethod();
} else{
mHandler.postDelayed(checkServiceHandler, 500);
}
}
};
mHandler.postDelayed(checkServiceHandler, 500); }
});
}
private void somemethod(){
Log.e("My", "B");
Toast.makeText(getApplicationContext(), "OK", Toast.LENGTH_LONG).show();
Log.e("My", "C");
}
}
You should implement your code in a way that you don't care when exactly your service is destroyed.
Anyway. If you really need the exact moment, you can fire an intent from your service using Android's broadcast system.
In your service:
#Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(CONST_SERVICE_DESTROYED));
}
In your activity:
private BroadcastReceiver receiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
// your B here
// your C here
}
};
And you need to register and unregister your receiver like this:
#Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(receiver, new IntentFilter(CONST_SERVICE_DESTROYED));
}
#Override
protected void onPause()
{
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
}
A good explanation and examples of Android's broadcast system can be found here
I read docs at Android Developer and still cant pause my service and then start it from the paused state (Playing the song).
With my current code, it always restart from the beginning of the song, but I would like to restart where the song was paused (with the stopClick).
Now I understand problem. In the MainActivity using stopService() method fully destroys it.
So how could i say service to wait when i press stop button to pause?
The Service class:
public class BackgroundSoundService extends Service {
MediaPlayer player;
int currentPos;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
final int MAX_VOLUME = 100;
player = MediaPlayer.create(this, R.raw.lightmusic);
player.setLooping(true);
float soundVolume = 77;
final float volume = (float) (1 - (Math.log(MAX_VOLUME - soundVolume) / Math
.log(MAX_VOLUME)));
player.setVolume(volume, volume);
player.seekTo(currentPos);
player.start();
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.seekTo(currentPos);
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
player.seekTo(currentPos);
player.start();
}
#Override
public void onRebind(Intent intent) {
player.seekTo(currentPos);
player.start();
super.onRebind(intent);
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
public void onStop() {
currentPos = player.getCurrentPosition();
player.pause();
}
public void onPause() {
currentPos = player.getCurrentPosition();
player.pause();
}
#Override
public void onDestroy() {
currentPos = player.getCurrentPosition();
player.pause();
//player.release();
}
#Override
public void onLowMemory() {
}
}
And my main Activity:
public class MainActivity extends QuizActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
startService(new Intent(this, BackgroundSoundService.class));
}
public void stopClick(View v) {
stopService(new Intent(this, BackgroundSoundService.class));
}
public void playClick(View v) {
startService(new Intent(this, BackgroundSoundService.class));
}
#Override
protected void onResume() {
super.onResume();
}
}