16

私は Android がMediaPlayer初めてで、オーディオ音楽を再生するために作成する必要があります。アクティビティを開始すると、曲の再生が始まります。しかし、エミュレーター画面の向きを変更すると、画面MediaPlayerが再初期化され、別のオーディオの再生が開始されます。どうすれば回避できますか?

これが私のコードです:

public class Audio_Activity extends Activity {


MediaPlayer mp = null;


    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        if(isLaunched)
        {
            setContentView(R.layout.audio);
        }

        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        length = settings.getInt("TheOffset", 0);
        init();
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        mp = MediaPlayer.create(getApplicationContext(), R.raw.subhanallah);
        playMusic();


        mp.setOnCompletionListener(new OnCompletionListener() 
        {

            @Override
            public void onCompletion(MediaPlayer arg0) 
            {
                // TODO Auto-generated method stub

            }
        });


    }

    private void playMusic() 
    {
        httpGetAsynchTask httpGetAsyncTask = new httpGetAsynchTask();
        httpGetAsyncTask.execute();
    }



    class httpGetAsynchTask extends AsyncTask<String,Integer, Void>
    {

        protected void onPreExdcute()
        {

        }

        @Override
        protected Void doInBackground(String... arg0)
        {
            // TODO Auto-generated method stub

            final SharedPreferences.Editor prefsEdit = prefs.edit();

            Log.e("Song is playing", "in  Mediya Player ");

            mp.setLooping(false);
            mp.start();
            int millisecond=mp.getDuration();
            Log.e("Song is playing", "in  Mediya Player " + millisecond);

            prefsEdit.putBoolean("mediaplaying", true);
            prefsEdit.commit();
            //btnChapter.setEnabled(false);

            return null;

        }

        protected void onPostExecute(Void result)
        {
            super.onPostExecute(result);
            btnChapter.setEnabled(false);
        }

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        Configuration config=getResources().getConfiguration();
        if(config.orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            setContentView(R.layout.audio);
        }
        else if(config.orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            setContentView(R.layout.audio);
        }
    }

    @Override
    public void onPause() {
        super.onPause();


        SharedPreferences.Editor prefsEdit = prefs.edit();
        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying)
        {
            mp.pause();
            int position = mp.getCurrentPosition();
            Log.e("Current ", "Position -> " + position);
            prefsEdit.putInt("mediaPosition", position);
            prefsEdit.commit();
        }
    }

    @Override
    protected void onResume() {

        super.onResume();

        mp.start();

        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying) {
            int position = prefs.getInt("mediaPosition", 0);
            mp.seekTo(position);
            // mp.start();


        }
    } 

}

そして、Manifest.xml ファイルにいくつかの変更を加えました。

< android:configChanges="orientation|screenSize|keyboard" >

そして、layout-land フォルダを作成します。

音楽が 2 回再生されるのはなぜですか?

4

11 に答える 11

9

この質問に対する最も簡単な回答。

@Override
protected void onSaveInstanceState(Bundle outState) 
{
    outState.putInt("possition", mpbg.getCurrentPosition());
    mpbg.pause();
    super.onSaveInstanceState(outState);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) 
{
    int pos = savedInstanceState.getInt("possition");
    mpbg.seekTo(pos);
    super.onRestoreInstanceState(savedInstanceState);
}
于 2014-05-24T06:04:21.440 に答える
4

mediaplayer を静的変数として宣言すると、mp のインスタンスは 1 つだけ存在します。アクティビティの方向が変更されたとします。方向の変更時にすべてが再作成されますが、静的プロパティのために Mp 変数は再作成されません。このように条件を作るだけです。

if(mp!=null && !mp.isPlaying()){ 
    mp = MediaPlayer.create(getApplicationContext(), R.raw.subhanallah);
    playMusic(); 
} 

onCreate() メソッドでは、音楽が既に再生されているかどうかを確認します。再生中の場合は、アプリケーションが音楽プレーヤーを再度起動できない場合の条件です。また、音楽が再生されていない場合は、アプリケーションが音楽を再開できるかどうかを確認します。


更新コードは次のとおりです。

public class Audio_Activity extends Activity {


static MediaPlayer mp = null;


    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        if(isLaunched)
        {
            setContentView(R.layout.audio);
        }

        SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
        length = settings.getInt("TheOffset", 0);
        init();
        prefs = PreferenceManager.getDefaultSharedPreferences(this);
        if(mp == null) 
        {
            initializeMP();
        }
        if(!mp.isPlaying())
        {
             playMusic();
        }

        mp.setOnCompletionListener(new OnCompletionListener() 
        {

            @Override
            public void onCompletion(MediaPlayer arg0) 
            {
                // TODO Auto-generated method stub

            }
        });


    }

    private void playMusic() 
    {
        httpGetAsynchTask httpGetAsyncTask = new httpGetAsynchTask();
        httpGetAsyncTask.execute();
    }

    public void initializeMP()
    {
          mp = MediaPlayer.create(getApplicationContext(), R.raw.subhanallah);

    }

    class httpGetAsynchTask extends AsyncTask<String,Integer, Void>
    {

        protected void onPreExdcute()
        {

        }

        @Override
        protected Void doInBackground(String... arg0)
        {
            // TODO Auto-generated method stub

            final SharedPreferences.Editor prefsEdit = prefs.edit();

            Log.e("Song is playing", "in  Mediya Player ");

            if(mp == null)
            {
                initializeMP()
            }
            mp.setLooping(false);
            mp.start();
            int millisecond=mp.getDuration();
            Log.e("Song is playing", "in  Mediya Player " + millisecond);

            prefsEdit.putBoolean("mediaplaying", true);
            prefsEdit.commit();
            //btnChapter.setEnabled(false);

            return null;

        }

        protected void onPostExecute(Void result)
        {
            super.onPostExecute(result);
            btnChapter.setEnabled(false);
        }

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        Configuration config=getResources().getConfiguration();
        if(config.orientation == Configuration.ORIENTATION_PORTRAIT)
        {
            setContentView(R.layout.audio);
        }
        else if(config.orientation == Configuration.ORIENTATION_LANDSCAPE)
        {
            setContentView(R.layout.audio);
        }
    }

    @Override
    public void onPause() {
        super.onPause();


        SharedPreferences.Editor prefsEdit = prefs.edit();
        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying)
        {
            if(mp!=null)
            {
                 mp.pause();
            }
            int position = mp.getCurrentPosition();
            Log.e("Current ", "Position -> " + position);
            prefsEdit.putInt("mediaPosition", position);
            prefsEdit.commit();
        }
    }

    @Override
    protected void onResume() {

        super.onResume();
        if(mp == null)
        {
            initializeMP();
        }
        mp.start();

        boolean isPlaying = prefs.getBoolean("mediaplaying", false);
        if (isPlaying) {
            int position = prefs.getInt("mediaPosition", 0);
            mp.seekTo(position);
            // mp.start();


        }
    } 

}
于 2013-07-29T10:42:15.730 に答える
3

このようなタスクでは、向きが変わってもサービスが再初期化されないため、サービスを使用する必要があります。

于 2013-07-29T07:20:56.410 に答える
2

というわけで、ずっと悩んでいましたが、やっと解決しました。あなたがしたいことは、あなたの Mediaplayer をクラスの静的メンバー変数にすることです。ここでの一番の答えと同様です。ただし、回避したい落とし穴は、「便利な」 create() メソッドを使用することです。これにより、静的であっても、呼び出されるたびにメディアプレーヤーの新しいインスタンスが実際に作成されます。代わりにやりたいことは次のようなものです:

static MediaPlayer m = new MediaPlayer();

プレーヤを作成したいコードのどこにでも、次のようにします。

m.reset();

try{
        m.setDataSource(getApplicationContext(),Uri.parse("android.resource://com.example.app/" + R.raw.soundId));
        m.prepare();

}catch(java.io.IOException e){ }

m.seekTo(pos);
m.start();

これのポイントは、 create() は便利ですが、新しいインスタンスを作成し続けてすぐにメモリを使い果たすため、方向を変更しない場合にのみ本当に役立つということです。1 つの静的メンバーを作成し、onCreate() が呼び出されるたびにそれを再利用する方が、はるかにクリーンでシンプルです。Reset() は、プレーヤーを再利用できる正しい状態にします。

于 2017-01-06T21:24:20.347 に答える
1

入れてよろしいですか

< android:configChanges="orientation|screenSize|keyboard" >

適切な場所で?他のアクティビティやアクティビティの外ではなく、プレーヤーのアクティビティに配置する必要があります。例として、マニフェストで次のように使用しました。

<activity android:name=".PlayerActivity" android:label="@string/title_activity_player" android:noHistory="true" android:configChanges="orientation|screenSize"> </activity>

そしてそれは動作します..それが役立つことを願っています..

于 2015-08-18T08:49:24.837 に答える
0

私もこの問題に何度も悩まされてきたので、参照用に POC を作成することにしました。この例ではconfigChangesフラグを使用し、サイズ変更を手動で処理します。それは非常にうまく機能します

https://github.com/caspercba/POCMediaPlayerRotation

于 2015-07-17T00:15:36.357 に答える
0

向きを変更すると、アクティビティが破棄されて再作成されます。

ビデオの実際の進行状況を onSaveInstanceState() に保存し、バンドルから onRestoreInstanceState() に保存されたデータを取得できます。その後、進行状況データを使用して再生を開始するか、データが保存されていない場合は最初から再生を開始できます。

于 2013-07-29T07:20:17.017 に答える