【android-音視頻】listview中播放音頻,實現音頻時長的倒計時,暫停,切換。


音頻播放會出現很多情況,比如當我點擊的是同一個音頻按鈕的時候,肯定就是控制音頻的播放與暫停,顯示時長的textview的暫停與繼續。

當點擊的音頻按鈕不是同一個的時候,

首先要重置上個點擊的音頻按鈕相對應的音頻時長的textview顯示。

比如,第一次點擊的是《萍聚》這首歌,時長4:01,應該立即播放此歌曲,並且時長進行倒計時4:01,4:00,3:59.....這樣。

當第二次點擊這首歌時,則需要暫停歌曲的播放,並暫停倒計時。

當在暫停狀態點擊其他的音頻播放按鈕的時候,

重置上次點擊的音頻,並重置與此對應的時間。根據前后兩次點擊的音頻的url,判斷是否需要重新獲得mediaplayer實例。

比如,第一次點擊的是《萍聚》,已經播放到2:21。第二次點擊的是《五環之歌》,則需要把第一個的Mediaplayer釋放掉,再重新得到一個五環之歌的mediaplayer。

並重置與《萍聚》相對應的textview的時長為4:01(即初始時長).

當activity切換的時候,轉入后台不可見的時候,要釋放掉mediaplayer。

下面請看代碼。(時間比較緊,沒有整理代碼。肯定還有更好的解決辦法。還請高手指正!)

  1.MediaPlayerUtils.java

import java.io.File;

import android.app.ProgressDialog;
import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.SeekBar;
import android.widget.TextView;

import com.ab.download.AbDownloadThread;
import com.ab.download.AbFileDownloader;
import com.ab.download.DownFile;
import com.ab.download.DownFileDao;
import com.ab.http.AbFileHttpResponseListener;
import com.ab.task.AbTaskItem;
import com.ab.task.AbTaskListener;
import com.ab.task.AbThread;
import com.ab.util.AbFileUtil;
/**
 * 2014-3-24下午4:19:16
 * 
 * @author:hlloworld.Mr-zz
 * 
 * @todo:MediaPlayer工具類,可以得到一個裝載好的MediaPlayer,並且裝載完畢后會自動播放一次 
 *                                                           1.首先會檢查本地是否有指定路徑(該路徑有項目根目錄
 *                                                           +voice+網絡路徑的文件名組成)
 *                                                           的音頻文件 2.如果存在,直接裝載播放
 *                                                           3.如果不存在,則異步播放網絡音頻
 */
public class MediaPlayerUtils {

    private ProgressDialog pd;
    private MediaPlayer player = null;
    private Handler handler = null;
    private static Context context;
    private static MediaPlayerUtils instance = null;
    private UpdateSeekBarThread updateSeekBarThread;
    private int playPosition;
    private DownFile d;//斷點續傳的文件
    private AbFileDownloader loader;

    private MediaPlayerUtils() {
    }

    public static MediaPlayerUtils getInstance(Context context) {
        if (instance == null) {
            MediaPlayerUtils.context = context;
            instance = new MediaPlayerUtils();
            TelephonyManager telephonyManager = (TelephonyManager) context
                    .getSystemService(Context.TELEPHONY_SERVICE);
            telephonyManager.listen(new MyPhoneListener(),
                    PhoneStateListener.LISTEN_CALL_STATE);
        }
        return instance;
    }

    public void initCountDownPlayer(final String voiceUrl,final Handler handler, final String time,final TextView tv) {
        // 如果sd卡能用,播放sd卡上的文件
        final File voice = new File(XingyunApplication.voiceDir
                + FileUtil.getFileNameFromUrl(voiceUrl));
        if (CommonUtils.isSDCardExits()) {
            
            if (!voice.exists()) {
                // 播放網絡文件
                playNetVoiceWithCountDown(voiceUrl, time,tv);
                // 如果sd卡中沒有,先下載
                downUrl(voiceUrl, voice);
//                downUrl1(voiceUrl, voice, context);
            } else {
                try {
                    player = player == null ? new MediaPlayer() : player;
                    player.setOnCompletionListener(new OnCompletionListener() {
                        
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            // TODO Auto-generated method stub
                            UpdateVoiceTimeThread.getInstance( time,tv).stop();
                        }
                    });
                    player.setDataSource(voice.toString());
                    player.prepare();
                    player.start();
                    UpdateVoiceTimeThread.getInstance( time,tv).start();
                    Message msg = handler.obtainMessage();
                    msg.obj = player;
                    msg.what = Gloable.VOICE_DOWN_OK;
                    handler.sendMessage(msg);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
        } else {
            playNetVoiceWithCountDown(voiceUrl, time,tv);
        }
    }
    
    private void playNetVoiceWithCountDown(final String voiceUrl,final String time,final TextView tv){
        // 如果sd卡不能用,直接播放網絡文件
                    showProgress();
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            // TODO Auto-generated method stub
                            Uri uri = Uri.parse(voiceUrl);
                            player = player == null ? MediaPlayer.create(context, uri)
                                    : player;
                            player.setOnCompletionListener(new OnCompletionListener() {
                                
                                @Override
                                public void onCompletion(MediaPlayer mp) {
                                    // TODO Auto-generated method stub
                                    UpdateVoiceTimeThread.getInstance( time,tv).stop();
                                }
                            });
                            player.setOnPreparedListener(new OnPreparedListener() {

                                @Override
                                public void onPrepared(MediaPlayer mp) {
                                    // TODO Auto-generated method stub
                                    dissmissProgress();
                                    player.start();
                                    
                                    UpdateVoiceTimeThread.getInstance( time,tv).start();
                                    Message msg = handler.obtainMessage();
                                    msg.obj = player;
                                    msg.what = Gloable.VOICE_DOWN_OK;
                                    handler.sendMessage(msg);
                                }
                            });
                        }
                    }).start();

    }
    
  /**
     * 顯示無邊框透明的progressdialog
     */
    private void showProgress() {
        pd = new CustomProgressDialog(context);
        pd.setCanceledOnTouchOutside(false);
        pd.show();
    }

    /**
     * 隱藏無邊框透明的progressdialog
     */
    private void dissmissProgress() {
        if (pd == null) {
            return;
        }
        pd.dismiss();
    }

    public void releasePlayer() {
        if (player != null) {
            if (player.isPlaying()) {
                player.stop();
            }
            player.release();
            player = null;
        }
        if (pd != null) {
            pd.dismiss();
            pd = null;
        }
        context = null;
        instance = null;
        if (updateSeekBarThread != null) {
            handler.removeCallbacks(updateSeekBarThread);
        }
    }

    /**
     * 只有電話來了之后才暫停音樂的播放
     */
    static class MyPhoneListener extends android.telephony.PhoneStateListener {
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:// 電話來了
                if (instance!=null) {
                    instance.callIsComing();
                }
                break;
            case TelephonyManager.CALL_STATE_IDLE: // 通話結束
                if (instance!=null) {
                    instance.callIsDown();
                }
                break;
            }
        }
    }

    /**
     * 來電話了
     */
    public void callIsComing() {
        if (player.isPlaying()) {
            playPosition = player.getCurrentPosition();// 獲得當前播放位置
            player.stop();
        }
    }

    /**
     * 通話結束
     */
    public void callIsDown() {
        if (playPosition > 0) {
            player.seekTo(playPosition);
            playPosition = 0;
        }
    }
    
    
    
    
    
    
    
    
    
   
    }

}

 

控制textview倒計時的countdownTimer

import java.text.SimpleDateFormat;
import android.media.MediaPlayer;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.sax.StartElementListener;
import android.widget.SeekBar;
import android.widget.TextView;

/**
 * 2014-3-26下午12:28:44
 * 
 * @author:crazyhelloworld.Mr-zz
 * @todo:
 */
public class UpdateVoiceTimeThread {

    private static CountDownTimer cdt;
    private final static int TIME_CHANGE_DELAY = 1000;
    private final static SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
    private static String time;
    private static TextView tvv;
    private static UpdateVoiceTimeThread instance = null;
    public static long l;
    public static UpdateVoiceTimeThread getInstance( final String stime,final TextView tv){
        if (instance==null) {
            synchronized (UpdateVoiceTimeThread.class) {
                if (instance == null) {
                    instance = new UpdateVoiceTimeThread();
                    time = stime;
                    tvv = tv;
                    String smin = stime.substring(0, stime.indexOf(":"));
                    String ssec = stime.substring(stime.indexOf(":") + 1, stime.length());
                    int min = Integer.parseInt(smin);
                    int sec = Integer.parseInt(ssec);
                    l = (min * 60 + sec) * 1000;
                    getTimer();
//                    cdt.start();
                }
            }
        }
        return instance;
    }
    
    private UpdateVoiceTimeThread(){};
    
    private static CountDownTimer getTimer(){
        if (cdt!=null) {
            cdt.cancel();
            cdt = null;
        }
        cdt = new CountDownTimer(l, TIME_CHANGE_DELAY) {

            @Override
            public void onTick(long millisUntilFinished) {
                // TODO Auto-generated method stub
                tvv.setText(sdf.format(millisUntilFinished));
                l = l - TIME_CHANGE_DELAY;
            }

            @Override
            public void onFinish() {
  
                tvv.setText(time);

            }
            
        };
        return cdt;
    }
    
    public void start() {
        getTimer();
        cdt.start();
    }
    public void pause(){
        cdt.cancel();
        tvv.setText(sdf.format(l));
    }
    public void stop(){
        instance = null;
        if (cdt!=null) {
            cdt.cancel();
            cdt = null;
        }
        tvv.setText(time);
    }

}

 

 

adapter中聲明的判斷屬性及handler

    /**
     * 根據前后兩次點擊的地址判斷是否需要重新加載mediaplayer的標識
     */
    private static int flag = 0;
    /**
     * 音頻播放的實例
     */
    public static MediaPlayer player = null;
    /**
     * 為了比對前后兩次點擊請求的音頻地址是否相同。與issame結合使用,
     * 如果issame=true,則點擊的是同一個按鈕。直接播放或者暫停
     * 如果issame=false,再判斷當前點擊的與按鈕的音頻地址與tempvoiceurl是否一致
     * 如果一致,stop上一個的播放,恢復tvlength的值為初始值。
     * 如果不一致,直接播放
     */
    private String tempVoiceUrl = "";
    /**
     * 當前點擊的iv后面的時間textview
     */
    private static TextView tv;
    /**
     * 當前點擊的音頻的長度
     */
    private static String time;
    /**
     * 當前點擊的容器(ImageView)
     */
    private View tempView;
    /**
     * 上個音頻的時長
     */
    private String tempTime;
    /**
     * 上個音頻時長的容器
     */
    private TextView tempTv;
    /**
     * 前后兩次點擊的是否是一個imageview的標識
     */
    private boolean isSame = false;

    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case Gloable.VOICE_DOWN_OK:
                player = (MediaPlayer) msg.obj;
                break;

            default:
                break;
            }

        };
    };

 

 

adapter中音頻的點擊事件

holder.voice.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if (!tempVoiceUrl.equals(p.getVoiceUrl())) {
                    MediaPlayerUtils.getInstance(context).releasePlayer();
                    flag = 0;
                }
                tv = (TextView) ((LinearLayout) v.getParent()).getChildAt(2);
                if (v == tempView) {
                    isSame = true;
                } else {
                    tempView = v;
                    isSame = false;
                }

                UpdateVoiceTimeThread.getInstance(p.getVoiceTime(), tv).stop();
                time = p.getVoiceTime();
                playVoice(p.getVoiceUrl(), time);
            }
        });

 

 

adapter中按鈕的點擊事件調用的播放方法

private void playVoice(String url, String time) {
        if (flag == 0) {
            if (NetUtils.isNetworkAvailable(context)) {
                MediaPlayerUtils.getInstance(context).initCountDownPlayer(url,
                        handler, time, tv);
                tempVoiceUrl = url;
                flag = -1;
            } else {
                Toast.makeText(context,
                        context.getString(R.string.network_not_avaliable), 1)
                        .show();
            }
        } else if (player != null) {
            if (isSame) {
                if (!player.isPlaying()) {
                    player.start();
                    if (UpdateVoiceTimeThread.l == 0) {
                        UpdateVoiceTimeThread.getInstance(time, tv).start();
                    } else {
                        UpdateVoiceTimeThread
                                .getInstance(
                                        CommonUtils
                                                .getStringDate(UpdateVoiceTimeThread.l),
                                        tv).start();
                    }
                } else {
                    player.pause();
                    UpdateVoiceTimeThread.getInstance(
                            CommonUtils.getStringDate(UpdateVoiceTimeThread.l),
                            tv).pause();
                }
                tempTv = tv;
                tempTime = time;
            } else {
                player.seekTo(0);
                player.start();
                UpdateVoiceTimeThread.getInstance(tempTime, tempTv).stop();
                UpdateVoiceTimeThread.getInstance(time, tv).start();

            }
        }
    }

    public static void releasePlayer() {
        MediaPlayerUtils.getInstance(context).releasePlayer();
        if (player != null) {
            player.release();
            player = null;
        }
        flag = 0;
        if (time != null && tv != null) {
            UpdateVoiceTimeThread.getInstance(time, tv).stop();
        }
    }

adapter中釋放player的方法

public static void releasePlayer() {
        MediaPlayerUtils.getInstance(context).releasePlayer();
        if (player != null) {
            player.release();
            player = null;
        }
        flag = 0;
        if (time != null && tv != null) {
            UpdateVoiceTimeThread.getInstance(time, tv).stop();
        }
    }

在activity的onPause()回調方法里調用adapter的releasePlayer()方法。

記錄一下,希望可以幫到一些人,更希望大神給予指點。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM