使用MediaPlayer播放音频文件

MediaPlayer是一个支持音频及视频文件播放的Android类,可播放不同来源(本地或网络流媒体)、多种格式(如WAV、MP3、Ogg Vorbis、MPEG-4以及3GPP)的多媒体文件。

新建音视频播放、暂停和停止封装类

package com.huangfei.hellomoon;

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;

/** * * @author huangfeihong 音视频播放、暂停和停止封装类 */
public class AudioPlayer {

    private MediaPlayer mPlayer;

    /** * 暂停 */
    public void pause() {
        if (mPlayer != null) {
            mPlayer.pause();
        }
    }

    /** * 停止 */
    public void stop() {
        if (mPlayer != null) {
            /** * MediaPlayer.release()方法可销毁MediaPlayer的实例。销毁是“停止”的一种具有攻击意味的说法, * 但我们有充足的理由使用销毁一词。 * 除非调用MediaPlayer.release()方法,否则MediaPlayer将一直占用着音频解码硬件及其它系统资源 * 。而这些资源是由所有应用共享的。 * MediaPlayer有一个stop()方法。该方法可使MediaPlayer实例进入停止状态,等需要时再重新启动 * 。不过,对于简单的音频播放应用,建议 使用release()方法销毁实例,并在需要时进行重见。基于以上原因,有一个简单可循的规则: * 只保留一个MediaPlayer实例,保留时长即音频文件 播放的时长。 */
            mPlayer.release();
            mPlayer = null;
        }
    }

    /** * 播放 */
    public void paly(Context c) {
        /** * 开头就调用stop()方法,可避免用户多次单机Play按钮创建多个MediaPlayer实例的情况发生。 */
        stop();

        /** * 音频文件放在res/raw目录下。目录raw负责存放那些不需要Android编译系统特别处理的各类文件。 */
        mPlayer = MediaPlayer.create(c, R.raw.one_small_step);
        mPlayer.setOnCompletionListener(new OnCompletionListener() {

            @Override
            public void onCompletion(MediaPlayer mp) {
                stop();
            }
        });

        mPlayer.start();
    }
}

创建播放音频的Fragment

package com.huangfei.hellomoon;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;

public class HelloMoonFragment extends Fragment {
    private AudioPlayer mPlayer = new AudioPlayer();
    private Button mPlayButton;
    private Button mStopButton;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /** * 当旋转设备后,音频播放会停止,该如何保证音频一直播放? * 调用Fragment.setRetainInstance(true)方法可保留fragment。 * * 当设备旋转时,FragmentManager会检查每个fragment的retainInstance属性值。如果属性值为false(初始默认值), * FragmentManager会立即销毁该fragment实例。随后,为适应新的设备配置,新的activity的新FragmentManager会创建 * 一个新的fragment及其视图。如属性值为true,则该fragment的视图立即被销毁,但fragment本身不会被销毁。为适应新的设备配置, * 当新的activity创建后,新的FragmentManager会找到被保留的fragment,并重新创建它的视图。 * * 只有当activity因设备配置发生改变被销毁时,fragment才会短暂的处于被保留状态。如果activity是因操作系统需要回收内存而被销毁, * 则所有被保留的fragment也会被随之销毁。 * * 如果activity或fragment中有需要长久保存的东西,则应覆盖onSaveInstanceState(Bundle)方法,将其保存下来。这样,由于同activity记录的生命周期保持了同步,后续可在需要时对其进行回复。 */
        setRetainInstance(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_hello_moon, container,
                false);
        mPlayButton = (Button) view.findViewById(R.id.hellomoon_palyButton);
        mPlayButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mPlayer.paly(getActivity());
            }
        });
        mStopButton = (Button) view.findViewById(R.id.hellomoon_stopButton);
        mStopButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mPlayer.stop();
            }
        });

        return view;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        /** * 调用AudioPlayer.stop()方法,以避免MediaPlayer的不停播放。该Fragment被销毁后,MediaPlayer仍可不停地播放, * 这是因为MediaPlayer运行在一个不同的线程上。 */
        mPlayer.stop();
    }
}
<?xml version="1.0" encoding="utf-8"?>
<!-- TableLayout使用起来和LinearLayout差不多。联合使用TableLayout和TableRow,可更容易地布置形成排列整齐的视图。 -->
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >

    <ImageView  android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:contentDescription="@string/hellomoon_image_description" android:scaleType="centerInside" android:src="@drawable/armstrong_on_moon" />

    <!-- TableRow组件无需声明高度和宽度的属性定义。实际上,它使用的是TableLayout的高度和宽度属性定义及其所有其他属性定义。 TableRow子组件的行为方式类似于表里的单元格。 -->

    <TableRow  android:layout_weight="0" android:gravity="center|bottom" >

        <Button  android:id="@+id/hellomoon_palyButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hellomoon_play" />

        <Button  android:id="@+id/hellomoon_stopButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hellomoon_stop" />
    </TableRow>

</TableLayout>

创建托管Fragment的Activity

package com.huangfei.hellomoon;

import android.os.Bundle;
import android.app.Activity;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;

public class HelloMoonActivity extends FragmentActivity {

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

}
<fragment xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/helloMoonFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:name="com.huangfei.hellomoon.HelloMoonFragment" />

<!-- 使用布局fragment,即在fragment元素节点中指定fragment的类。在Activity调用setContentView(...)方法,并实例化布局时,发现了fragment元素。 于是FragmentManager接着就创建了指定Fragment的一个实例,并将其添加到fragment对列中。 使用如此简单的方式托管fragment,同时也失去了只有显示地使用FragmentManager才能获得的灵活性与掌控能力。 1、可覆盖fragment的生命周期方法,以响应各种事件。但无法控制调用这些方法的时机。 2、无法提交移除、替换、分离布局fragment的事务。activity被创建后,即无法做出任何改变。 3、无法附加argument给布局fragment。附加argument必须在fragment创建后并被添加给FragmentManager之前完成。如果使用布局fragment,这些事件何时发生,我们无从得知。-->

代码地址

你可能感兴趣的:(mediaplayer)