当然,不仅限定于使用Android内置的应用程序,还可以自己编写提供播放及更多功能的应用程序。

    为此,Android包括了一个MediaPlayer类。这个类可以用于播放以及控制音频和视频。目前,我们仅仅使用其音频播放示例。

    最简单的MediaPlayer示例是播放与应用程序本身一起打包的音频文件。为此,音频文件应放置在应用程序的原始资源中。为了使用Eclipse中的Android Developer Tools(Android开发人员工具)实现该操作,需要在项目的res文件夹中创建一个新的文件夹,称为raw。Android Developer Tools将在R.java文件中为此文件生成资源ID,在此过程中采用R.raw.file_name_without.extension语法。

    1.启动媒体播放器

    为音频文件创建MediaPlayer非常简单。可以使用静态方法create实例化一个MediaPlayer对象,传入作为上下文的this以及为音频文件生成的资源ID。

1   MediaPlayer mediaPlayer=MediaPlayer.create(this, R.raw.music);

   随后,只须调用MediaPlayer对象上的start方法来播放音频文件。

1   mediaPlayer.start();

    2.控制播放

    MediaPlayer类有几个嵌套的类,他们是监听MediaPlayer所发送事件的接口。这些事件与状态变化相关。

    例如,MediaPlayer将对实现OnCompletionListener并通过setOnCompletionListener方法注册的类调用onCompletion方法。该操作将在音频文件正在播放时执行。

    下面是一个活动的完整示例,该活动无限次的重复,通过使用OnCompletionListener播放相同的音频文件。在onStart方法中初始化MediaPlayer对象和开始播放;在onStop方法中停止播放盒释放MediaPlayer对象。这可以防止当活动不再活跃时继续播放音频,而是当该活动重新活跃时重新启动音频的播放。

1 package com.nthm.androidtest;
 2 
 3 import android.app.Activity;
 4 import android.media.MediaPlayer;
 5 import android.media.MediaPlayer.OnCompletionListener;
 6 import android.os.Bundle;
 7 
 8 public class CustomAudioPlayer extends Activity implements OnCompletionListener {
 9     private MediaPlayer mediaPlayer;
10     
11     @Override
12     protected void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14         setContentView(R.layout.customaudioplayer);
15     }
16     
17     @Override
18     protected void onStart() {
19         super.onStart();
20         mediaPlayer=MediaPlayer.create(this, R.raw.music);
21         mediaPlayer.setOnCompletionListener(this);
22         mediaPlayer.start();
23     }
24 
25     @Override
26     protected void onStop() {
27         super.onStop();
28         mediaPlayer.stop();
29         mediaPlayer.release();
30     }
31 
32     @Override
33     public void onCompletion(MediaPlayer mp) {
34         mediaPlayer.start();
35     }
36 
37 }

    当然,这可以在没有OnCompletionListener的情况下完成,只须简单的通过使用setLooping(true)方法将MediaPlayer设置为循环播放。

    让我们更深入一步,通过触摸事件控制播放。下面这段代码可以作为开发一个DJ音频应用程序的良好起点。

1 package com.nthm.androidtest;
 2 
 3 import android.app.Activity;
 4 import android.media.MediaPlayer;
 5 import android.media.MediaPlayer.OnCompletionListener;
 6 import android.os.Bundle;
 7 import android.view.MotionEvent;
 8 import android.view.View;
 9 import android.view.View.OnClickListener;
10 import android.view.View.OnTouchListener;
11 import android.widget.Button;

    正如之前的示例所做的那样,活动将实现OnCompletionListener,但是他也会实现OnTouchListener,从而可以响应触摸事件;同时它实现了OnClickListener,从而可以响应用户单击按钮事件。

1 public class CustomAudioPlayer extends Activity implements OnCompletionListener,OnClickListener,OnTouchListener{

     当然,我们将需要一个指向MediaPlayer对象的引用。需要访问一个View对象,从而可以注册希望捕获的事件;同时需要访问任何在布局XML文件中定义的按钮——在当前情况下是一个用于停止播放的按钮和一个用于启动的播放的按钮。

1     private MediaPlayer mediaPlayer;
2     private View theview;
3     private Button stopButton;
4     private Button startButton;

    需要声明一个变量,其包含音频文件中的保存位置。后面将使用这个位置确定从哪里开始播放音频文件。

1     private int position=0;
2     @Override
3     protected void onCreate(Bundle savedInstanceState) {
4         super.onCreate(savedInstanceState);
5         setContentView(R.layout.customaudioplayer);

    使用标准的findViewById函数,可以访问在布局XML中定义的按钮以及View对象。

1         stopButton=(Button) findViewById(R.id.StopButton);
2         startButton=(Button) findViewById(R.id.StartButton);

    由于活动可以响应单击事件,因此我们将它注册为两个按钮上的监听器。

1         stopButton.setOnClickListener(this);
2         startButton.setOnClickListener(this);

    然后将使活动能够响应触摸事件。

1         theview=findViewById(R.id.theview);
2         theview.setOnTouchListener(this);

    在这个应用中,音频文件的名称是music.mp3,而且已经将它放置在项目的res/raw文件夹中。我们将使用该文件创建MediaPlayer对象。同时,与前面的示例一样,将活动设置为MediaPlayer对象的OnCompletionListener。

1 mediaPlayer=MediaPlayer.create(this, R.raw.music);
2         mediaPlayer.setOnCompletionListener(this);
3         mediaPlayer.start();
4     }

   下面定义onCompletion方法,每当MediaPlayer完成播放音乐文件时调用它。在当前情况下,将调用start方法来播放音频,然后调用seekTo方法定位到保存的位置。需要在能够定位之前播放音频。

1     @Override
2     public void onCompletion(MediaPlayer mp) {
3         mediaPlayer.start();
4         mediaPlayer.seekTo(position);
5     }

    当用户触发一个触摸事件时,将会调用onTouch方法。在该方法中只关注ACTION_MOVE触摸事件,当用户在View对象表面上移动手指时触发该事件。在这种情况下,需要确保MediaPlayer正在播放,然后根据触摸事件在屏幕上发生的位置计算出应该定位到的位置。如果触摸事件发生在屏幕的右边界,那么将定位到文件的末尾。如果发生在屏幕的左边界,那么将定位到靠近文件的其实位置。我们将这个值保存到position变量中,因此当音频文件完成播放时,若重新开始播放(在onCompletion方法中),则它将定位回该位置。

1     @Override
 2     public boolean onTouch(View v, MotionEvent event) {
 3         if(event.getAction()==MotionEvent.ACTION_MOVE){
 4             if(mediaPlayer.isPlaying()){
 5                 position=(int)(event.getX()*mediaPlayer.getDuration()/theview.getWidth());
 6                 mediaPlayer.seekTo(position);
 7             }
 8         }
 9         return true;
10     }

   最后有一个响应按钮单击事件的onClick方法。这些单击事件暂停和启动音频播放。

1     @Override
2     public void onClick(View v) {
3         if(v==stopButton){
4             mediaPlayer.pause();
5         }else if(v==stopButton){
6             mediaPlayer.start();
7         }
8     }
9 }

    下面试上述代码示例中引用的布局XML文件

1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent"
 4     android:orientation="vertical"
 5     >
 6     <Button 
 7         android:layout_width="wrap_content"
 8         android:layout_height="wrap_content"
 9         android:text="Start"
10         android:id="@+id/StartButton" />
11     <Button 
12         android:layout_width="wrap_content"
13         android:layout_height="wrap_content"
14         android:text="Stop"
15         android:id="@+id/StopButton" />
16     <View 
17         android:layout_width="fill_parent"
18         android:layout_height="fill_parent"
19         android:id="@+id/theview"
20         />
21 </LinearLayout>

    在Android上构建一个自定义的音频播放器会导致一些有趣的可能性。我们可以构建不仅仅是直接播放音频的应用程序。将这个应用程序转换成完整的二手机DJ应用程序可能会很有兴趣。