Android Stop Background Music

冷暖自知 提交于 2019-11-27 07:06:31

I'm very happy today, and still have hair :) I've tested this and it works!!!

First, add this to your Manifest:

<uses-permission android:name="android.permission.GET_TASKS"/>

Second, add this to your 'Home/Main' Activity/Class:

  @Override
  protected void onPause() {
    if (this.isFinishing()){ //basically BACK was pressed from this activity
      player.stop();
      Toast.makeText(xYourClassNamex.this, "YOU PRESSED BACK FROM YOUR 'HOME/MAIN' ACTIVITY", Toast.LENGTH_SHORT).show();
    }
    Context context = getApplicationContext();
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    if (!taskInfo.isEmpty()) {
      ComponentName topActivity = taskInfo.get(0).topActivity; 
      if (!topActivity.getPackageName().equals(context.getPackageName())) {
        player.stop();
        Toast.makeText(xYourClassNamex.this, "YOU LEFT YOUR APP", Toast.LENGTH_SHORT).show();
      }
      else {
        Toast.makeText(xYourClassNamex.this, "YOU SWITCHED ACTIVITIES WITHIN YOUR APP", Toast.LENGTH_SHORT).show();
      }
    }
    super.onPause();
  }

And obviously replace xYourClassNamex with, well, Your Class Name :)

Now obviously you do not need the "Toasts" but it will tell you what is going on. The very intersting thind is when you press BACK from your 'Home/Main' activity, you obviously get 2 Toasts, "YOU PRESSED BACK FROM YOUR 'HOME/MAIN' ACTIVITY", and the 2nd Toast is "YOU SWITCHED ACTIVITIES WITHIN YOUR APP". I believe I know why this happens, but it doesn;t matter because I call "player.stop();" from the 2 scenarios that mean my app is no longer being 'used'. Obviously do more work than "player.stop();" if you need to :) And also obvious you dont need the "else" for "YOU SWITCHED ACTIVITIES WITHIN YOUR APP", because there is no reason to "stop/pause" the background music, which is what i needed, but if you DO need to do something when new activities are started, well here you go :)

Hope this helps anyone looking to know when the user "leaves/exits/is done with" the app :)

THANKS FOR ALL OF THE COMMENTS POSTS AND HELP EVERYONE!!! YAY!

EDIT-

This part has to be in EVERY activity's onPause:

Context context = getApplicationContext();
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        if (!taskInfo.isEmpty()) {
          ComponentName topActivity = taskInfo.get(0).topActivity; 
          if (!topActivity.getPackageName().equals(context.getPackageName())) {
            player.stop();
            Toast.makeText(xYourClassNamex.this, "YOU LEFT YOUR APP", Toast.LENGTH_SHORT).show();
          }
        }

so you'll know if the user left your app from ANY of the activities. this is good to know :)

JoxTraex

The way the media player works is that its runs as a service and then is stopped MANUALLY when the user stops it in the application itself.

Example:

When the media player is playing a song and the user hits home, obviously the user still wants to listen to the song as its a background task. After the user is done listening then the user manually stops it by going into the application and stopping (Aka stopping the service that is playing the song) it or if the playlist is done, then stop. Simple.

This is the expected behavior. And it is exactly how the Music App works.

UPDATE

@Override
    protected void onPause() {
        super.onPause();
        if (this.isFinishing()){
            player.stop();
        }
    }

Needs to be changed to

@Override
    protected void onPause() {
        super.onPause();
        if (mediaPlayer != null){
            mediaPlayser.stop();
            if (isFinishing()){
            mediaPlayer.stop();
            mediaPlayer.release();
            }
        }
    }

An explanation:

The reason we are checking for the object not being null is obvious. However; when we enter the pause, we want to ensure that the mediaplayer is stopping. BUT if we are leaving and the song is almost done, then stop it and release it.

UPDATE 2

Check the link here:

https://stackoverflow.com/a/6704844/529691

This can be used to detect if your application has been moved out of the current tip of the application stack.

I faced same problem. I will tell you my solution. I overrided onStop, onStart each activity and counted my started activity with some delay and count reaches zero, I paused music.

how is it about un/register as a listener @ the service in onStart() and onStop() method of your activities and every time a listener is (un)registered your service checks if it's got some listeners left in its ArrayList<Listener>. if the listOfListeners.size() is 0 then your service calls its stopSelf() method and kills itself.

at least that's how I would implement this...

so, the things you would need are:

  • 2 Interfaces (Observer, Observable)

  • implement Observer in Activity, Observable in Service

  • ArrayList<Observer> in Service

  • registerObserver(Observer o) and unregisterObserver(Observer o) in Service

but that's just my point of view...

Why don't you just make a button to stop the music its so much easier and you don't have to force close everytime

Button exit =(Button) findViewById(R.id.exit);

    exit.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v)
            {
                // TODO: Implement this method

                startActivity(new Intent("com.justme.worldexplorer.EXIT"));             
                finish();
                Music I'd.stop();}});}

There you go and so the key hardware button back dosent leave if you press by accident

public boolean onKeyDown(int KeyCode,KeyEvent event){


    return false;
}

And that's it set it up in the manifest and run if any problems let me know

private static HashMap<String, Boolean> focus = new HashMap<String, Boolean>();

public static void check(Context context, boolean hasFocus)
{
    handler.removeMessages(0);
    focus.put(((Activity)context).getLocalClassName(), hasFocus);
    handler.sendEmptyMessageDelayed(0, 500);
}

public static void check(String classname, boolean hasFocus)
{
    handler.removeMessages(0);
    focus.put(classname, hasFocus);
    handler.sendEmptyMessageDelayed(0, 500);
}

private static Handler handler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        Iterator<Boolean> it = focus.values().iterator();
        while(it.hasNext())
        {
            if(it.next())
                return;
        }
        pause();
        super.handleMessage(msg);
    }
};

this is an manager class methods.

each activity implementing like after code

@Override
public void onWindowFocusChanged(boolean hasFocus)
{
    MusicManager.check(this, hasFocus);
    super.onWindowFocusChanged(hasFocus);
}

I'm using this code with my game which is published and working great.

What part of this code is terrible? and where's better solution? I want to know if exist.

Mike, you answered to me my answer is terrible and not working, What's wrong with this?

In each activity, bind to the service in onStart() and unbind from the service in onStop(). When start the service, only bind to it and do not call startService(...).

By calling startService() the service will continue to run until stopService() is called, regardless of the number of activities bound to it. If you don't call start service, then the service will automatically stop once all activities have unbound from it.

So by binding and unbinding on each activity's onStart() and onStop() methods, you will find that the service (music) will continue until you leave your application with the home button, back key, screen timeout, etc.

For those still looking for a solution in lollipop or just without using permission thing, I came up with another solution as last resource. We can measure the time user has been afk. If it was more than X ms, then you can consider he left the application and stop the music.

So I'm using Application child where I store the time afk and BaseActivity to override onPause and onResume of all my activities.

I have encountered the same problem with my development proccess.

I solved this by using onPause and onResume and with pause() and start() methods in the player which I saved on my main container, calling fragments instead of activities.

I kept a flag on a singleton in order to know when the music was turned off by the user.

Another problem I found is that my app (idk if it's part of the android build or not) was running the onResume method right before he got the player back on, so I ran a while loop in order to receive the player not as a null pointer, and it works because it runs on a different thread, therefore enabling the app to run the onResume without crashing and the music alongside it.

I find it better (smaller code to write) and non-permission invasive ;).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!