当媒体播放器准备时显示进度条

6

我正在尝试找出如何在媒体播放器准备流媒体文件时显示一个进度条,上面写着“正在加载,请稍等...”。目前的情况是它在歌曲准备好后才显示。我该如何解决这个问题?

        mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true);         
                    /*dubstep stream*/
                    try {
                        dubstepMediaPlayer.setDataSource(dubstepPlaylistString[0]);
                        dubstepMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                        dubstepMediaPlayer.prepare();

                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalStateException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }


                    dubstepMediaPlayer.start();
                    if(dubstepMediaPlayer.isPlaying()){
                        mediaPlayerLoadingBar.dismiss();
                    }`

编辑: 这是我现在的代码:

`switch(pSelection){ case 1:

选择(pSelection)的情况如下:

                    new AsyncTask<Void, Void, Void>(){

                    @Override
                    protected void onPreExecute(){
                        mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true);
                        try {
                            dubstepMediaPlayer.setDataSource(dubstepPlaylistString[0]);
                        } catch (IllegalArgumentException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IllegalStateException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        dubstepMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    }

                    @Override
                    protected Void doInBackground(Void... params) {
                        // TODO Auto-generated method stub
                        //mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true);
                        return null;
                    }

                    protected void onPostExecute(Void result){
                        //mediaPlayerLoadingBar =ProgressDialog.show(PlaylistActivity.this, "", "Loading. Please wait...", true)
                            dubstepMediaPlayer.prepareAsync();
                        dubstepMediaPlayer.start();
                        mediaPlayerLoadingBar.dismiss();

                }

                }.execute();`
6个回答

5
如果有人仍然遇到这个问题,以下是代码:
      AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {

            @Override
            protected void onPreExecute() {
                if(translation.equals("NIV"))
                {
                    if(AudioPlaying==false)
                    {
                        mediaPlayer = new MediaPlayer();
                        mediaPlayer.setOnPreparedListener(Main.this);
                        mediaController = new MediaController(Main.this);
                    }
                    else
                        mediaController.show();
                }
                else
                    Toast.makeText(getBaseContext(), "عفوا, جاري تحميل ملفات الصوت الخاصة بترجمة الفانديك ", Toast.LENGTH_LONG).show();
                pd = new ProgressDialog(Main.this);
                pd.setTitle("Processing...");
                pd.setMessage("Please wait.");
                pd.setCancelable(false);
                pd.setIndeterminate(true);
                pd.show();

            }

            @Override
            protected Void doInBackground(Void... arg0) {
                try {
                    //Do something...
                    //Thread.sleep(5000);
                    try 
                    {
                        mediaPlayer.setDataSource(AudioUrlPath);
                        mediaPlayer.prepare();
                        mediaPlayer.start();
                        AudioPlaying=true;
                    } 
                    catch (IOException e) {
                        Log.e("AudioFileError", "Could not open file " + AudioUrlPath + " for playback.", e);
                    }

                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                if (pd!=null) {
                    pd.dismiss();
                    //b.setEnabled(true);
                }
            }

        };
        task.execute((Void[])null);

你让我赢得了尊重,兄弟(对于我来说是自由职业任务):p - Jigar

4

问题在于你在这里没有进行任何异步操作,而你应该这样做。你应该使用AsyncTask来完成你的工作。

看一下这里详细介绍的“4个步骤”:

四个步骤:
当执行异步任务时,该任务会经历以下4个步骤:
  1. onPreExecute(),在任务执行后立即在UI线程上调用。此步骤通常用于设置任务,例如在用户界面中显示进度条。
  2. doInBackground(Params ...),在onPreExecute()完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的后台计算。异步任务的参数传递给此步骤。计算的结果必须在此步骤中返回,并将传递回最后一步。此步骤还可以使用publishProgress(Progress ...)发布一个或多个进度单元。这些值在onProgressUpdate(Progress ...)步骤中在UI线程上发布。
  3. onProgressUpdate(Progress ...),在调用publishProgress(Progress ...)后在UI线程上调用。执行时间的确定性未定义。执行此方法可在后台计算仍在执行的同时在用户界面中显示任何形式的进度。例如,它可以用于动画化进度条或在文本字段中显示日志。
  4. onPostExecute(Result),在后台计算完成后在UI线程上调用。将后台计算的结果作为参数传递给此步骤。

编辑:

您可以创建一个匿名内部类来完成您的任务,这可能类似于您创建onClick处理程序的方式。在您的onClick中执行以下操作:

//pseudo-code...
onClick(View v, ...) {
    new AsyncTask<Generic1, Generic2, Generic3>() {
        protected void onPreExecute() {
            // do pre execute stuff...
        }

        protected Generic3 doInBackground(Generic1... params) {
            // do background stuff...
        }

        protected void onPostExecute(Generic3 result) {
            // do post execute stuff...
        }
    }.execute();
}

别忘了在这里注意你的泛型!


好的,我似乎理解了,或者至少我认为我理解了你的意思。那么我应该在哪里创建这个类呢?因为这段代码是在 onCLick 中的。它是扩展 AsyncTask 还是我的主类? - Splitusa
平均而言,歌曲开始播放前需要大约3-5秒钟的时间。但用户应该知道歌曲正在加载。 - Splitusa
嗯,从一万英尺高的角度来诊断问题可能会很困难。也许你应该更新你的问题,因为你已经进行了更新... - nicholas.hauschild
我已经更新了代码。它会在歌曲开始播放前显示进度条,并在歌曲正在播放时取消(这正是应该发生的)。现在,当我按下暂停按钮时,应用程序会强制关闭。你有什么想法吗?顺便说一句,谢谢你的帮助。这是我学习安卓编程的第六周,所以我还在学习中。 - Splitusa
看起来 .execute 正在破坏我的其他代码。有没有办法在它运行一次后取消异步任务? - Splitusa
显示剩余5条评论

1

这是活动类。这里我只是展示一下方法。

package com.android.mediaactivity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

    public class MediaActivity extends Activity 
    {
        public LinearLayout mainLayout;
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            mainLayout=(LinearLayout)findViewById(R.id.mainlinear);
            MediaPlayer media=new MediaPlayer(this);
            media.startPlayer();
        }
    }

这里是MediaPlayer类。

package com.android.mediaactivity;

import java.io.IOException;

import android.media.MediaPlayer.OnPreparedListener;

public class MediaPlayer implements OnPreparedListener {
    MediaActivity mediaActivity;
    android.media.MediaPlayer mediaPlayer;
    public MediaPlayer(MediaActivity mediaActivity) {
        this.mediaActivity = mediaActivity;
    }
    public void startPlayer() {
        mediaPlayer = new android.media.MediaPlayer();
        mediaPlayer.setOnPreparedListener(this);
        mediaPlayer.reset();
        try {
            mediaPlayer.setDataSource("");
            mediaPlayer.prepareAsync();
            toggleProgress(true);
        } catch (IllegalArgumentException e) { // TODO Auto-generated catch block          e.printStackTrace();        } catch (IllegalStateException e) {             // TODO Auto-generated catch block          e.printStackTrace();        } catch (IOException e) {           // TODO Auto-generated catch block          e.printStackTrace();        }   }   public void onPrepared(android.media.MediaPlayer mp)    {       toggleProgress(false);      mediaPlayer.start();    }
            public void toggleProgress(final boolean show) {
                mediaActivity.runOnUiThread(new Runnable() {
                    public void run() {
                        if (show) mediaActivity.mainLayout.setVisibility(mediaActivity.mainLayout.VISIBLE);
                        else mediaActivity.mainLayout.setVisibility(mediaActivity.mainLayout.INVISIBLE);
                    }
                });
            }

        }
    }
}

这是主要的main.xml文件。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:id="@+id/mainlinear"
    android:visibility="invisible">

    <ProgressBar android:id="@+id/ProgressBar01"
        android:layout_width="wrap_content" android:layout_height="wrap_content"></ProgressBar>
</LinearLayout>

好的。我会再试一次,然后告诉你。 - Splitusa
好的,你提供给我的代码确实有效。现在我能把它放到我的原始代码上并且仍然正常工作吗? - Splitusa

0
当您在底层的mediaplayer对象上调用prepare时,内部实际上会进行一些准备工作,例如设置文件提取器、设置音频解码器以解码编码的音频文件并设置音频接收器以播放从解码器解码的原始音频数据。现在所有这些都需要时间,不是瞬间完成的。
因此,在您的原始代码中,您检查mediaplayer是否正在播放,然后将其关闭,但问题是在那个时候mediaplayer还没有开始播放音频,因此您的dismiss从未被调用,因此它总是可见的。
您需要做的是实现MediaPlayer.OnPreparedListener监听器,并在应用程序中调用onPrepared方法时,在该方法中调用dismiss mediaPlayerLoadingBar.dismiss();。

0

终于找到了: 各位,非常重要的一点: 在设置URL之后

  try {
            mediaPlayer.setDataSource(url);
        } catch (IOException e) {
            e.printStackTrace();
        }

我已经添加了 prepare_sync() 并且添加了处理程序,因为对于大文件它会崩溃

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        mediaPlayer.prepareAsync();
        ProgressDialog progressDialog = ProgressDialog.show(Player.this,
                "Loading Title", "Loading Message");
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                if (progressDialog != null && progressDialog.isShowing()){
                    progressDialog.dismiss();

                }
            }
        });
        // might take long! (for buffering, etc)
        mediaPlayer.start();

    }
},500);

这段代码将添加进度条。

要点:

  1. 设置URL
  2. 准备异步操作
  3. OnPreparedListener 进度条

mp.start-done

这是我的做法,顺便说一下,我听说还有另一种选择,可以看看Exoplayer!


0
这是我的解决方案: prepareAsync函数用于准备音频,它是一个非阻塞操作(不会阻塞应用程序的主线程)。
然后我使用回调setOnPreparedListener,在prepareAsync返回并且音频准备好时得到通知。
public void playAudio(String audioFile){


//init the progress dialog
  final ProgressDialog progressDialog = new ProgressDialog(SubjectActivity.this);

    try {

         progressDialog.setCancelable(false);
         progressDialog.setMessage(" Waiting to Prepare ...");
         progressDialog.show();

// pass the url file to the media player
        mediaplayer.setDataSource(audioFile);
        mediaplayer.prepareAsync();


    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
//the callback gets called when prepareAsync audio file become ready, 
    mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mediaplayer.start();
// cancel the dialog
            progressDialog.cancel();
        }
    });


}

1
欢迎来到SO,这个答案质量较低,您必须提供代码解释,说明您是如何解决这个问题的。 - Basel Issmail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接