第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

Android 入門教程

菜單類控件
菜單:Menu
并發(fā)編程
多線程

媒體播放器:MediaPlayer

Android 系統(tǒng)提供了幾種播放音頻和視頻的方式,其中最常用的就是 MediaPlayer,和其他功能組件一樣都有很多第三方框架提供更加豐富完備的功能,但是基本用法和時(shí)序基本都是參照 MediaPlayer 來設(shè)計(jì)的,本節(jié)就來看看 MediaPlayer 的使用方法。

1. MediaPlayer 的狀態(tài)

MediaPlayer 有一套完善的狀態(tài)機(jī),通常出現(xiàn)一些奇怪的報(bào)錯(cuò)或者 Crash 大概率就是狀態(tài)流轉(zhuǎn)出了問題,而市面上大多數(shù)的播放器也會(huì)遵循 Android 官方設(shè)計(jì)的這套狀態(tài)機(jī)來實(shí)現(xiàn)。首先看看所有的狀態(tài):

  • Idle:
    空閑態(tài),剛創(chuàng)建或者調(diào)用了reset()之后的狀態(tài),此時(shí)不能進(jìn)行播放
  • Initailized:
    初始化態(tài),僅僅設(shè)置了媒體源,但還未進(jìn)行任何網(wǎng)絡(luò)資源的拉取或者媒體流的解析,此時(shí)仍然不能播放
  • Preparing:
    準(zhǔn)備中,觸發(fā)了媒體流的下載以及媒體流的解析,但均未完成,處于準(zhǔn)備中,尚不能進(jìn)行播放
  • Prepared:
    準(zhǔn)備好,已經(jīng)將媒體資源拉取并解析完成,隨時(shí)可以開始播放
  • Started:
    播放態(tài),在媒體資源準(zhǔn)備好之后,調(diào)用了start()觸發(fā)了媒體的播放,則進(jìn)入視頻 / 音頻播放
  • Paused:
    暫停態(tài),這個(gè)很好理解,視頻 / 音頻播放暫停,此時(shí)可以隨時(shí)調(diào)用start()繼續(xù)播放回到Started狀態(tài)
  • PlaybackCompleted:
    播放結(jié)束態(tài),視頻 / 音頻播放到結(jié)尾,自然結(jié)束
  • Stoped:
    停止態(tài),在播放或者暫停過程中主動(dòng)調(diào)用stop()停止播放,注意它和暫停態(tài)不同,“Stoped”態(tài)不能直接回到播放態(tài);它和
    播放結(jié)束態(tài)也不同,“Stoped”一定是由開發(fā)者主動(dòng)觸發(fā)的
  • End:
    釋放態(tài),播放器調(diào)用release()觸發(fā)播放器資源的釋放,此時(shí)播放器資源被回收將不能使用
  • Error:
    錯(cuò)誤態(tài),如果由于某種原因 MediaPlayer 出現(xiàn)了錯(cuò)誤,會(huì)觸發(fā) OnErrorListener.onError()事件,此時(shí) MediaPlayer 即進(jìn)入 Error 狀態(tài),及時(shí)捕捉并妥善處理這些錯(cuò)誤是很重要的,可以幫助我們及時(shí)釋放相關(guān)的軟硬件資源,也可以改善用戶體驗(yàn)。通過setOnErrorListener可以設(shè)置該監(jiān)聽器。如果MediaPlayer進(jìn)入了Error狀態(tài),可以通過調(diào)用reset()來恢復(fù),使得MediaPlayer重新返回到 Idle 狀態(tài)。

下面可以對(duì)照著狀態(tài)看看官方給的狀態(tài)機(jī)流轉(zhuǎn)圖:

Mediaplayer

這個(gè)圖非常經(jīng)典,建議大家收藏此文章,今后使用 MediaPlayer 過程中出現(xiàn)任何問題都可以看看狀態(tài)機(jī)是否出現(xiàn)異常。

2. MediaPlayer 常用 API

使用 MediaPlayer 的 API 之前一定要先熟悉熟悉再熟悉上一小節(jié)的狀態(tài)機(jī)時(shí)序圖,否則盲目使用 API 會(huì)出現(xiàn)很多狀態(tài)錯(cuò)誤的異常發(fā)生。
setDataSource(FileDescriptor fd):
設(shè)置音頻 / 視頻資源地址

  • isPlaying():
    判斷當(dāng)前視頻 / 音頻是否正在播放
  • seekTo(position):
    直接跳轉(zhuǎn)到視頻 / 音頻的某個(gè)時(shí)間點(diǎn)
  • getCurrentPosition():
    獲取當(dāng)前的播放進(jìn)度
  • getDuration():
    獲取媒體文件的總時(shí)長
  • reset():
    重置 MediaPlayer,此后會(huì)進(jìn)入 Idle 態(tài)
  • release():
    釋放播放器,在不使用的時(shí)候調(diào)用,節(jié)省系統(tǒng)資源
  • setVolume(float leftVolume, float rightVolume):
    設(shè)置媒體音量
  • selectTrack(int index):
    設(shè)置媒體軌道
  • getTrackInfo():
    返回一個(gè)數(shù)組,包含所有的軌道信息

3. MediaPlayer 使用步驟

Android 系統(tǒng)為 MediaPlayer 適配了多種場景,也為不同的場景提供了不同的使用方式,但大體上有幾個(gè)步驟:

  1. 創(chuàng)建播放器
    創(chuàng)建通常有兩種方法:
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.song);
MediaPlayer mediaPlayer = new MediaPlayer();

第一種方式直接在創(chuàng)建的時(shí)候傳入媒體流地址,而第二種僅僅是創(chuàng)建一個(gè)“Idle”態(tài)的閑置播放器

  1. 設(shè)置媒體源
    Android 提供下面的方法設(shè)置媒體數(shù)據(jù)源
mediaPlayer.setDataSource(www.mc.com/mc.mp3);

如果在創(chuàng)建 MediaPlayer 的時(shí)候就設(shè)置了媒體文件,那么可以跳過這一步

  1. 開始播放
    在設(shè)置好媒體源地址之后,就可以開始播放了:
mediaPlayer.start();
  1. 播放控制
    在播放過程中可以調(diào)用一些控制 API 進(jìn)行播放狀態(tài)的控制

  2. 結(jié)束播放
    調(diào)用stop()可以結(jié)束播放,并且記得在不用的時(shí)候還要調(diào)用release()

4. 播放器使用示例

本節(jié)來用 MediaPlayer 實(shí)現(xiàn)一個(gè)簡單的播放器,并通過幾個(gè) API 來實(shí)現(xiàn)基本的播放控制。

4.1 MediaPlayer 的使用

首先看看 MainActivity:


package com.emercy.myapplication;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.concurrent.TimeUnit;

public class MainActivity extends Activity {
    private Button b1, b2, b3, b4;
    private MediaPlayer mediaPlayer;

    private double startTime = 0;
    private double finalTime = 0;

    private Handler myHandler = new Handler();
    private int forwardTime = 5000;
    private int backwardTime = 5000;
    private SeekBar seekbar;
    private TextView tx1, tx2, tx3;

    public static int oneTimeOnly = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        b1 = (Button) findViewById(R.id.button);
        b2 = (Button) findViewById(R.id.button2);
        b3 = (Button) findViewById(R.id.button3);
        b4 = (Button) findViewById(R.id.button4);

        tx1 = (TextView) findViewById(R.id.textView2);
        tx2 = (TextView) findViewById(R.id.textView3);
        tx3 = (TextView) findViewById(R.id.textView4);

        mediaPlayer = MediaPlayer.create(this, R.raw.video);
        seekbar = (SeekBar) findViewById(R.id.seekBar);
        seekbar.setClickable(false);
        b2.setEnabled(false);

        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int temp = (int) startTime;

                if ((temp + forwardTime) <= finalTime) {
                    startTime = startTime + forwardTime;
                    mediaPlayer.seekTo((int) startTime);
                    Toast.makeText(getApplicationContext(), "前進(jìn)5秒", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getApplicationContext(), "前方還剩不到5秒", Toast.LENGTH_SHORT).show();
                }
            }
        });

        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "Pausing sound", Toast.LENGTH_SHORT).show();
                mediaPlayer.pause();
                b2.setEnabled(false);
                b3.setEnabled(true);
            }
        });

        b3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getApplicationContext(), "音頻播放", Toast.LENGTH_SHORT).show();
                mediaPlayer.start();

                finalTime = mediaPlayer.getDuration();
                startTime = mediaPlayer.getCurrentPosition();

                if (oneTimeOnly == 0) {
                    seekbar.setMax((int) finalTime);
                    oneTimeOnly = 1;
                }

                tx2.setText(String.format("%d min, %d sec",
                        TimeUnit.MILLISECONDS.toMinutes((long) finalTime),
                        TimeUnit.MILLISECONDS.toSeconds((long) finalTime) -
                                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
                                        finalTime)))
                );

                tx1.setText(String.format("%d min, %d sec",
                        TimeUnit.MILLISECONDS.toMinutes((long) startTime),
                        TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
                                TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes((long)
                                        startTime)))
                );

                seekbar.setProgress((int) startTime);
                myHandler.postDelayed(UpdateSongTime, 100);
                b2.setEnabled(true);
                b3.setEnabled(false);
            }
        });

        b4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int temp = (int) startTime;

                if ((temp - backwardTime) > 0) {
                    startTime = startTime - backwardTime;
                    mediaPlayer.seekTo((int) startTime);
                    Toast.makeText(getApplicationContext(), "后退5秒", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(getApplicationContext(), "后方還剩不到5秒", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private Runnable UpdateSongTime = new Runnable() {
        public void run() {
            startTime = mediaPlayer.getCurrentPosition();
            tx1.setText(String.format("%d min, %d sec",
                    TimeUnit.MILLISECONDS.toMinutes((long) startTime),
                    TimeUnit.MILLISECONDS.toSeconds((long) startTime) -
                            TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.
                                    toMinutes((long) startTime)))
            );
            seekbar.setProgress((int) startTime);
            myHandler.postDelayed(this, 100);
        }
    };
}

通過MediaPlayer.create(this, R.raw.video)創(chuàng)建一個(gè) MediaPlayer 對(duì)象并初始化媒體流地址,然后分別設(shè)置幾個(gè)控制 Button 的監(jiān)聽事件,實(shí)現(xiàn)播放器的前進(jìn)、后退、播放、暫停操作,當(dāng)中還有一個(gè)UpdateSongTime的 Runnable 變量,用來每隔 100 毫秒更新一次播放進(jìn)度,實(shí)現(xiàn)播放進(jìn)度的同步刷新。

4.2 布局文件

布局文件就按照片一般播放器的擺放方式就可以,上面通常是頁面的主題和描述,下方就是進(jìn)度條、歌曲名稱時(shí)長等等。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="30dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="音樂播放器"
        android:textSize="35dp" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textview"
        android:layout_centerHorizontal="true"
        android:text="慕課Android教程"
        android:textColor="#ff7aff24"
        android:textSize="35dp" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:text="前進(jìn)" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_toRightOf="@id/button"
        android:text="暫停" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/button2"
        android:layout_toEndOf="@+id/button2"
        android:text="播放" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/button3"
        android:layout_toEndOf="@+id/button3"
        android:layout_toRightOf="@+id/button3"
        android:text="后退" />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button"
        android:layout_alignStart="@+id/textview"
        android:layout_alignEnd="@+id/textview" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/seekBar"
        android:text="超哥音樂選集"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/seekBar"
        android:layout_alignEnd="@+id/button4"
        android:text="02:23"
        android:textAppearance="?android:attr/textAppearanceSmall" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/textView2"
        android:layout_alignBottom="@+id/textView2"
        android:layout_centerHorizontal="true"
        android:text="超哥吉他"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

當(dāng)然也可以按照你自己的設(shè)計(jì)去擺放播放器的布局樣式,編譯之后如下:

demo

5. 小結(jié)

本節(jié)學(xué)習(xí)了 Android 內(nèi)置的最常用的播放器,最關(guān)鍵的是要熟悉它的狀態(tài)機(jī)時(shí)序圖,因?yàn)榭赡茉趯?shí)際開發(fā)中你會(huì)使用更強(qiáng)大的第三方播放器,但是基本時(shí)序仍然是參照 Android 官方設(shè)計(jì)的,在了解時(shí)序之后就可以按照本節(jié)的步驟使用各種 API 來播放音視頻了。在掌握了本節(jié)內(nèi)容之后,如果感興趣也可以研究研究市面上常用的開源播放器,可以讓你對(duì)播放器有更深的理解。