Domanda

I'm developing a simple game where 3 activities (menu, settings and ranking list) needs one background music that should play smoothly in the background even if for example user leaves menu and goes into settings and then back.

For that I created service which works perfectly. There is only one major problem: when app is closed (user press home button for example), music doesn't stop playing.

I have tried with onDestroy, onStop, onPause but the problem is not solved.

Service:

package com.android.migame;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;

public class Meni_music extends Service implements OnCompletionListener {

    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.menu);
        player.setLooping(true); // Set looping
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        player.start();
        return 1;
    }

    public IBinder onUnBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onDestroy() {
        player.stop();
        player.release();
        stopSelf();
    }

    @Override
    public void onLowMemory() {
    }

    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
    }
}

Menu:

package com.android.migame;

    import android.app.Activity;
    import android.app.ActivityManager;

    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.ImageView;

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;

    public class Meni extends Activity {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            requestWindowFeature(Window.FEATURE_NO_TITLE);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
                    WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            setContentView(R.layout.meni);

            startService(new Intent(Meni.this,Meni_music.class));

        }

        @Override
        protected void onPause() {
            super.onPause();
        }

        @Override
        protected void onResume() {
            super.onResume();
        }

}
È stato utile?

Soluzione 5

Easy solutions:

  1. Just use one activity! Use Fragments for each screen that you are displaying.

  2. Use a static counter. Increment the counter when you call startActivity(). Decrement the counter onPause() of all activities. When an activity pauses, and your counter is 0, then stop the music.

Altri suggerimenti

I think this behavior is most logically addressed by creating your own application class. Register this class in your manifest using:

<application
    android:name="MyApplication"

Let the MyApplication class look something like this:

public class MyApplication extends Application
    implements ActivityLifecycleCallbacks, Runnable
{
    private Handler h;

    @Override public void onCreate()
    {
        h = new Handler();
        registerActivityLifecycleCallbacks(this);
    }

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) { }
    public void onActivityStarted(Activity activity) { }
    public void onActivityStopped(Activity activity) { }
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }
    public void onActivityDestroyed(Activity activity) { }

    public void onActivityResumed(Activity activity)
    {
        h.removeCallbacks(this);
        startService(new Intent(this, Meni_music.class));
    }

    public void onActivityPaused(Activity activity);
    {
        h.postDelayed(this, 500);
    }

    public void run()
    {
        stopService(new Intent(this, Meni_music.class));
    }
}

Try this it will work .Make a ActivityLifecycleCallback class that will check if your application is in background or running.On onActivityStopped call stop your service.

    public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
    private int resumed;
    private int paused;

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    public void onActivityDestroyed(Activity activity) {
    }

    public void onActivityResumed(Activity activity) {
        ++resumed;
    }

    public void onActivityPaused(Activity activity) {
        ++paused
        if(resumed == paused)
        stopService(new Intent(this, Meni_music.class));
    }

    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    public void onActivityStarted(Activity activity) {
    }

    public void onActivityStopped(Activity activity) {

    }

}

register your callback class -

    registerActivityLifecycleCallbacks(new MyLifecycleHandler());

I had a similar requirement, and here's how I solved it:

  • Create a class that implements Application.ActivityLifecycleCallbacks, and have your application register it with registerActivityLifecycleCallbacks in it's onCreate method. This class will be notified every time an activity is paused or resumed.

  • Have this class maintain a count of the number of active activities - start at 0, add one for each resumed activity, and subtract one for each paused activity. In practice, your counter will always be zero or one.

  • In your onActivityPaused method, after decrementing the counter, check to see if the count is zero. Note that there is a short period of time between an Activity being paused and the next one being resumed when you transition between activities, during which the count will be zero. If, after waiting some reasonable amount of time from the onActivityPaused, your count is still zero, then your application has been put completely into the background, and you should stop your service.

This is what you can do,

Create a static helper class, add a static variable msActivityCount in it and add following 2 methods in it.

increaseActivityCount() - increment the msActivityCount value. If msActivityCount == 1 start the service. Call this function from onStart() of each activity.

decreaseActivityCount() - decrement the msActivityCount value. If msActivityCount == 0 stop the service. Call this function from onStop() of each activity.

This should solve your issue without any problems.

Start your service when Menu activity resumes and stop it when the activity stops. So the Menu activity should look like something like this:

package com.android.migame;

    import android.app.Activity;
    import android.app.ActivityManager;

    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
    import android.widget.ImageView;

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;

    public class Meni extends Activity {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            requestWindowFeature(Window.FEATURE_NO_TITLE);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
                    WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
            setContentView(R.layout.meni);
        }

        @Override
        protected void onPause() {
            super.onPause();
            stopService(new Intent(Meni.this,Meni_music.class));
        }

        @Override
        protected void onResume() {
            super.onResume();
            startService(new Intent(Meni.this,Meni_music.class));
        }
}

You declare your Intent outside the function in activity class and stop the service inside this class, call stop or ondestroy like this:

 public class Meni extends Activity {
     private Intent i=new Intent();

  @Override
  protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 requestWindowFeature(Window.FEATURE_NO_TITLE);
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
     WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
     setContentView(R.layout.meni);
     i=new Intent(Meni.this,Meni_music.class);
     startService(i);
 }

  @Override
  protected void onDestroy() {
    stopService(i);
    super.onDestroy();
}

 @Override
 protected void onStop() {
stopService(i);
super.onStop();
 }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top