1

私のアプリには、音楽アイテムの ListView があり、アイテムをクリックすると、それに対応する mp3 URL をフェッチして、MediaPlayer でストリーミングします。ユーザーが [再生] ボタンをクリックするたびに、MediaPlayer のデータソースなどを設定します。問題は、[再生] ボタンをクリックして ListView をスクロールすると、画面がフリーズしてダイアログが開くことです。

AppName is not responding.
Would you like to close it?
      Wait       OK

しかし、スタックトレースを取得できませんでしたが、次のように言いました:

ANR my.package.name.AppName ...
Reason: keyDispatchingTimedOut

UIスレッドを待機させないように、プロセスをバックグラウンドスレッド内に配置することを読みました。これは私の現在の実装ですが、問題はまだ解決していません:

Thread t = new Thread() {
            public void run() {
                SampleActivity.this.runOnUiThread(new Runnable() {
                    public void run() {
                        try {
                            mp.reset();
                            mp.setDataSource(musicURI);
                            mp.prepare();
                            mp.start();

                            songSeekBar.setEnabled(true);

                            // Changing Button Image to stop image
                            btnPlay.setImageResource(R.drawable.btn_stop);

                            // set Progress bar values
                            songSeekBar.setProgress(0);
                            songSeekBar.setMax(100);

                            // Updating progress bar
                            updateProgressBar();
                        } catch (IllegalArgumentException e) {
                            e.printStackTrace();
                        } catch (IllegalStateException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            songSeekBar.setEnabled(false);
                            songTotalDurationLabel.setText("0:00");
                            songCurrentDurationLabel.setText("0:00");
                            Log.d(Constant.TAG_SAMPLE, musicTitle
                                    + " mp3 file not found.");
                            e.printStackTrace();
                        }
                    }
                });
            }
        };
        t.start();

私がしたことは、runOnUiThread内部に配置しThread(機能していません)、試したThreadだけで(機能していません)、Asynctaskその内部にも試しましdoInBackgroundたが、プレーヤーはバックグラウンドで再生されており、停止できませんが、内部に配置しようとはしていませんonPostExecute

何かが足りない気がします。1つ確かなことは、実際にはバックグラウンドスレッド内に配置する必要があるということですが、どのスレッドですか? どんなアイデアでも受け入れられます、ありがとう!

編集: だから、私は実装を変更しましたが、それはまだ持続しています:

Thread thread = new Thread() {
        public void run() {
            Handler refresh = new Handler(Looper.getMainLooper());
            refresh.post(new Runnable() {
                public void run() {
                    // Play song
                    try {
                        mp.reset();
                        mp.setDataSource(globalSongIndex);
                        mp.prepare();
                        mp.start();

                        songSeekBar.setEnabled(true);

                        // Changing Button Image to pause image
                        btnPlay.setImageResource(R.drawable.btn_stop);

                        // set Progress bar values
                        songSeekBar.setProgress(0);
                        songSeekBar.setMax(100);

                        // Updating progress bar
                        updateProgressBar();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalStateException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        songSeekBar.setEnabled(false);
                        songTotalDurationLabel.setText("0:00");
                        songCurrentDurationLabel.setText("0:00");
                        Log.d(Constant.TAG_MYPAGE, musicTitle + " mp3 file not found.");
                        e.printStackTrace();
                    }
                }
            });
        }
    };
    thread.start();

ちなみに、私はそれをアンドロイドのウェブサイトhereに基づいていました。

4

2 に答える 2

0

OK、あなたのコードはメインスレッドで実行されます。プレーヤーを初期化するのは得策ではありません。完全に、最初のコードから 2 番目のコードまで何も変更していません。

ANR は文字列 player.prepare() に表示されます。代わりに playerAsync を使用してみてください。非同期のプレーヤーを準備するか、これを削除します。

Handler refresh = new Handler(Looper.getMainLooper());
        refresh.post(new Runnable() {
            public void run() {

バックグラウンドスレッドですべてのジョブを作成します。

そして、AsyncTask について読んでください。これは、バックグラウンドで何らかの作業を行うのに適したクラスです。通常のスレッドを使用するよりもはるかに便利です。

正しい方法は次のようになります。

MediaPlayer mp = new MediaPlayer();
mp.setDataSource(YourURI);
mp.setOnPreparedListener(new OnPreparedListener() {
  public void onPrepared(MediaPlayer mp)
  {
   long duration = mp.getDuration();
   mp.start();
  }
});
mp.prepareAsync();
于 2013-08-16T06:58:31.243 に答える