web-dev-qa-db-ja.com

Androidバックグラウンドミュージックを停止する

編集-簡単な5-10ラインソリューションを見つけてください!!!以下の私の回答をご覧ください!!!わーい!!!!!!!!!

私は5時間、何十ものSO投稿、回答なし)を検索しましたが、これは最も単純で明白なおかしなことのようです!!!

編集-ところで、これは音楽プレーヤーアプリではなく、写真やテキストを表示するアプリであり、メニューなどの複数のアクティビティを開き、写真の種類を表示します。写真を見ながらシンプルなバックグラウンドミュージックを再生したいだけですとテキスト、なぜそんなに難しいのですか?

別の編集-主な質問は本当に「ホームボタンを押すとonPauseまたはonStopが呼び出されないのはなぜですか?」 -メディアプレーヤーを停止するタイミングを知ることができますか?そして、私が市場でダウンロードしたゲームはどのようにこれを達成しますか?

ホームアクティビティが始まります

それから

メディアプレーヤーの起動:

_player = MediaPlayer.create(this, R.raw.idil);
player.setLooping(true);
player.setVolume(100,100);
player.start();
_

OnCreateの外部で宣言されたプレーヤー

_MediaPlayer player;
_

他のアクティビティを開くと、バックグラウンドミュージックは中断されずに継続します。これは良いことです。

veryシンプルなアプリ(差分アクティビティで写真とテキストを表示するだけ)が完了したら、[戻る]を複数回クリックしてホーム/元のアクティビティに移動し、さらにもう1つ「終了」する時間、または、私は単に家を押して「終了」するだけです。なぜなら、このアプリを使い終わって、その音楽を聞く必要がなくなったからです。


オプション1

onPauseオーバーライドでplayer.stop();を呼び出します。これはnotです。これは、 'menu'や 'また、美しいアクティビティを「スキップ」したり中断したりしたくないため、新しいアクティビティを開くときに一時停止と再開を使用することもしません。


オプション2

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

これは、バックグラウンドミュージックがアクティビティ間で停止せず、ホームアクティビティから[戻る]を押すと音楽が停止し、安心して静かに自分のAndroid ただし問題は、HOMEボタンを押してアプリを「終了」すると、厄介なバックグラウンドミュージックが再生され続けることです。


奇妙な

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

OnPauseと同じことを行います(実際の違いは理解しています)

編集-また、player.stop();が問題にならないようです。 super.onStop()の上または下しかし、それは私が見ることができない何かに影響を及ぼしますが、解決策はありません:(

ああ

ああ

編集-別のオプション-しかし動作しない

_public void onUserLeaveHint() {
    player.stop();
    super.onUserLeaveHint();
}
_

これは、HOMEを押すと音楽を停止しますが、新しいアクティビティを開始するときにも停止します:(

編集-IVEの周りの非常に一般的な作業は複数の場所を見ましたが、やらなければならないことはばかげているようです:

開閉されたアクティビティの数を本質的にカウントし(onResumeとonPauseが最適ですが、それは無関係なポイントです)、そのカウントが0に達したら、バックグラウンドミュージックを停止します。はい、それは非常に簡単ですが、プログラムでこれを行う必要があるのはなぜですか、実際にはこれに関する最大の質問POST IS:

ホームボタンを押すと、onPauseまたはonStopが呼び出されないのはなぜですか?

OnDestroyは、システムのメモリが少ない場合にのみ呼び出されるか、アプリを強制的に終了する場合にのみ呼び出されるため、onDestroyに配置することはオプションではありません。

私はそれを「不可能」と読み、「非常に眉をひそめている」と読んだので、HOMEボタンを無効にすることもオプションではありません。

SERVICEを作成する必要はないと思います。たとえ作成したとしても、いつサービスを停止しますか。同じ問題が発生するようです。

今ここにIS私の心を完全に吹き飛ばすもの、everyゲームとeveryアプリからダウンロードしたAndroidマーケットには非常に美しいバックグラウンドミュージックがあり、BACKまたはHOMEを押すと、その素敵なゲームをプレイし終わったので音楽は停止します、バックグラウンドでプレイし続けません。

私は非常にイライラしており、何かを逃しているように感じているためだと思いますvery simple。これはアプリの最も基本的なライフサイクルの問題の1つだからです。

開発ガイド、チュートリアル、サンプルプロジェクト、リファレンスセクションの調査など、developer.Android.comのすべてのページを1か月間読んで、このトピックを5時間グーグルで検索しました。

また、6または7 SOスレッドがexact同じ問題であり、notが回答されたすべてのダウンロード可能なアプリ)の理由もわかりません市場では、(バックグラウンドミュージックプレーヤーでない限り)HOMEまたはBACKを押すか、アプリを「終了」して携帯電話で他の操作を行うと、音楽の再生が停止します。

私は何が欠けていますか?

26
Mike

私は今日とても幸せです、そしてまだ髪があります:)私はこれをテストしました、そしてそれは動作します!!!

まず、これをマニフェストに追加します。

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

次に、これを「ホーム/メイン」アクティビティ/クラスに追加します。

  @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();
  }

そして、明らかにxYourClassNamexをあなたのクラス名に置き換えてください:)

これで、明らかに「トースト」は必要ありませんが、何が起こっているかがわかります。非常に興味深いのは、 'Home/Main'アクティビティからBACKを押すと、明らかに2つのトースト、「あなたの 'HOME/MAIN'アクティビティから押し戻されました」、そして2番目のトーストは「あなたのアプリ内で切り替えられたアクティビティ」です「。私はこれがなぜ起こるのか知っていると信じていますが、「player.stop();」と呼ぶので問題ではありません。私のアプリが「使用」されなくなったことを意味する2つのシナリオから。 「player.stop();」よりも明らかに多くの作業を行うバックグラウンドミュージックを「停止/一時停止」する理由がないため、「必要な場合は「アプリ内での切り替えアクティビティ」の「その他」も必要ありません。新しいアクティビティが開始されたら、何かする必要があります。

これが、ユーザーがアプリを「離れる/終了する/終了する」ことを知りたい人に役立つことを願っています:)

コメント投稿のすべてに感謝し、みんな助けて!わーい!

編集

この部分は、すべてのアクティビティの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();
          }
        }

そのため、ユーザーがどのアクティビティからでもアプリを離れたかどうかがわかります。これは知っておくと良いです:)

22
Mike

メディアプレーヤーの動作方法は、サービスとして実行され、ユーザーがアプリケーション自体で停止したときに手動で停止することです。

例:

メディアプレーヤーが曲を再生しているときにユーザーが家に着くと、明らかにユーザーはそのバックグラウンドタスクとしてその曲を聞きたいと思っています。ユーザーがリスニングを完了した後、ユーザーはアプリケーションに移動して停止する(別名、曲を再生しているサービスを停止する)ことによって手動で停止するか、プレイリストが完了したら停止します。シンプル。

これは予想される動作です。そして、まさに音楽アプリの仕組みです。

[〜#〜] update [〜#〜]

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

に変更する必要があります

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

説明:

オブジェクトがnullでないことを確認している理由は明らかです。しかしながら;一時停止に入ると、mediaplayerが停止していることを確認する必要があります。 [〜#〜] but [〜#〜]立ち去り、曲がほぼ完成したら、停止してリリースします。

更新2

こちらのリンクを確認してください。

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

これは、アプリケーションがアプリケーションスタックの現在のチップから移動したかどうかを検出するために使用できます。

2
JoxTraex

アクティビティのonStart()およびonStop()メソッドのサービスおよびリスナーが登録(登録解除)されるたびに、サービスがリスナーに登録されているかどうかを確認します。 _ArrayList<Listener>_にリスナーが残っています。 listOfListeners.size()が_0_である場合、サービスはそのstopSelf()メソッドを呼び出して自身を強制終了します。

少なくともそれは私がこれを実装する方法です...

したがって、必要なものは次のとおりです。

  • 2つのインターフェイス(ObserverObservable

  • ObserverActivityを実装し、ObservableServiceを実装します

  • _ArrayList<Observer>_ in Service

  • ServiceregisterObserver(Observer o)およびunregisterObserver(Observer o)

でもそれは私の見方です...

1
herom

簡単に音楽を停止するボタンを作成して、毎回強制的に閉じる必要がないようにしましょう。

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

そこに行くので、誤って押した場合、キーハードウェアボタンが戻ることはありません

public boolean onKeyDown(int KeyCode,KeyEvent event){


    return false;
}

そして、それはマニフェストに設定し、何か問題があれば知らせてくれます

1

同じ問題に直面しました。私の解決策を説明します。 onStop、onStartの各アクティビティをオーバーライドし、開始されたアクティビティを少し遅れてカウントし、カウントがゼロに達したときに音楽を一時停止しました。

1
lulumeya

まだLollipopで解決策を探している人、または許可を使用しない人のために、最後のリソースとして別の解決策を思いつきました。ユーザーがafkしていた時間を測定できます。 Xミリ秒を超えていた場合は、彼がアプリケーションを離れて音楽を停止したと考えることができます。

したがって、すべてのアクティビティのonPauseとonResumeをオーバーライドするために、時間afkとBaseActivityを保存するApplication子を使用しています。

0
Vito Valov
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);
    }
};

これはマネージャークラスのメソッドです。

コードの後に​​likeを実装する各アクティビティ

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

私はこのコードをゲームで使用しており、公開されており、うまく機能しています。

このコードのどの部分がひどいですか?そして、より良い解決策はどこですか?存在するかどうか知りたい。

マイク、私の答えはひどくてうまくいかない、と答えました。これは何が問題なのですか?

0
lulumeya

開発プロセスで同じ問題が発生しました。

これを解決するには、onPauseとonResumeを使用し、メインコンテナーに保存したプレーヤーでpause()メソッドとstart()メソッドを使用して、アクティビティではなくフラグメントを呼び出しました。

ユーザーが音楽をいつオフにしたかを知るために、シングルトンにフラグを付けました。

私が見つけた別の問題は、私のアプリ(Android buildまたはnot)の一部である場合はidk)がプレーヤーを戻す直前にonResumeメソッドを実行していたため、whileループを実行したことです。 nullポインターとしてではなくプレーヤーを受信するための命令であり、異なるスレッドで実行されるため機能します。したがって、アプリはクラッシュせずに音楽と一緒にonResumeを実行できます。

私はそれをより良く(書くためのより小さなコード)そして非許可の侵襲的だと思う;)。

0
user2438341

各アクティビティで、onStart()でサービスにバインドし、onStop()でサービスからバインド解除します。サービスを開始するときは、それにのみバインドし、startService(...)を呼び出さないでください。

StartService()を呼び出すことにより、サービスは、バインドされているアクティビティの数に関係なく、stopService()が呼び出されるまで実行され続けます。開始サービスを呼び出さない場合、すべてのアクティビティのバインドが解除されると、サービスは自動的に停止します。

したがって、各アクティビティのonStart()およびonStop()メソッドをバインドおよびバインド解除することにより、ホームボタン、戻るキー、画面タイムアウトなどでアプリケーションを終了するまでサービス(音楽)が継続することがわかります。

0
TomEverin