音乐播放
MediaPlayer mediaPlayer = new MediaPlayer();
if (mediaPlayer.isPlaying()) {mediaPlayer.reset();//重置为初始状态
}
mediaPlayer.setDataSource("/mnt/sdcard/god.mp3");
mediaPlayer.prepare();
mediaPlayer.start();//开始或恢复播放
mediaPlayer.pause();//暂停播放
mediaPlayer.start();//恢复播放
mediaPlayer.stop();//停止播放
mediaPlayer.release();//释放资源
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {//播出完毕事件
@Override public void onCompletion(MediaPlayer arg0) {
mediaPlayer.release();
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {// 错误处理事件
@Override public boolean onError(MediaPlayer player, int arg1, int arg2) {
mediaPlayer.release();
return false;
}
});
音乐播放代码示例:
DemoActivity.java:
package cn.itcast.mp3;
import java.io.File;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.Chronometer.OnChronometerTickListener;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Toast;
public class DemoActivity extends Activity implements OnClickListener,
OnChronometerTickListener, OnSeekBarChangeListener {
private EditText et_path;
private Chronometer et_time;
private SeekBar sb;
private Button bt_play, bt_pause, bt_replay, bt_stop;
private MediaPlayer mediaPlayer;
private TelephonyManager manager;
/**
* subtime:点击“续播”到暂停时的间隔的和 beginTime:重新回到播放时的bash值 falgTime:点击“播放”时的值
* pauseTime:“暂停”时的值
*/
private long subtime = 0, beginTime = 0, falgTime = 0, pauseTime = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
manager = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
manager.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
sb = (SeekBar) this.findViewById(R.id.sb);
et_path = (EditText) this.findViewById(R.id.et_path);
et_time = (Chronometer) this.findViewById(R.id.et_time);
bt_play = (Button) this.findViewById(R.id.play);
bt_pause = (Button) this.findViewById(R.id.pause);
bt_replay = (Button) this.findViewById(R.id.replay);
bt_stop = (Button) this.findViewById(R.id.stop);
sb.setEnabled(false);
sb.setOnSeekBarChangeListener(this);
bt_play.setOnClickListener(this);
bt_pause.setOnClickListener(this);
bt_replay.setOnClickListener(this);
bt_stop.setOnClickListener(this);
et_time.setOnChronometerTickListener(this);
}
Handler handler = new Handler();
Runnable updateThread = new Runnable() {
public void run() {
// 获得歌曲现在播放位置并设置成播放进度条的值
if (mediaPlayer != null) {
sb.setProgress(mediaPlayer.getCurrentPosition());
// 每次延迟100毫秒再启动线程
handler.postDelayed(updateThread, 100);
}
}
};
public void onClick(View v) {
String path;
try {
switch (v.getId()) {
case R.id.play:
falgTime = SystemClock.elapsedRealtime();
path = et_path.getText().toString().trim();
play(path);
pauseTime = 0;
et_time.setBase(falgTime);
et_time.start();
break;
case R.id.pause:
pause();
break;
case R.id.replay:
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(0);
et_time.setBase(SystemClock.elapsedRealtime());
et_time.start();
} else {
path = et_path.getText().toString().trim();
play(path);
et_time.setBase(SystemClock.elapsedRealtime());
et_time.start();
}
if ("续播".equals(bt_pause.getText().toString().trim())) {
bt_pause.setText("暂停");
}
falgTime = SystemClock.elapsedRealtime();
subtime = 0;
break;
case R.id.stop:
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer = null;
et_time.setBase(SystemClock.elapsedRealtime());
et_time.start();
et_time.stop();
bt_play.setEnabled(true);
bt_play.setClickable(true);
sb.setProgress(0);
sb.setEnabled(false);
falgTime = 0;
subtime = 0;
}
break;
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "文件播放出现异常", 0).show();
}
}
private void pause() {
// 判断音乐是否在播放
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
// 暂停音乐播放器
mediaPlayer.pause();
bt_pause.setText("续播");
sb.setEnabled(false);
et_time.stop();
pauseTime = SystemClock.elapsedRealtime();
// System.out.println("1 pauseTime" + pauseTime);
} else if (mediaPlayer != null
&& "续播".equals(bt_pause.getText().toString())) {
subtime += SystemClock.elapsedRealtime() - pauseTime;
// System.out.println("2 subtime:" + subtime);
mediaPlayer.start();
bt_pause.setText("暂停");
sb.setEnabled(true);
beginTime = falgTime + subtime;
// System.out.println("3 beginTime" + beginTime);
et_time.setBase(beginTime);
et_time.start();
}
}
/**
* 播放指定地址的音乐文件 .mp3 .wav .amr
*
* @param path
*/
private void play(String path) throws Exception {
if ("".equals(path)) {
Toast.makeText(getApplicationContext(), "路径不能为空", 0).show();
return;
}
File file = new File(path);
if (file.exists()) {
mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(path);
// mediaPlayer.prepare(); // c/c++ 播放器引擎的初始化
// 同步方法
// 采用异步的方式
mediaPlayer.prepareAsync();
// 为播放器注册
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
mediaPlayer.start();
bt_play.setEnabled(false);
bt_play.setClickable(false);
sb.setMax(mediaPlayer.getDuration());
handler.post(updateThread);
sb.setEnabled(true);
}
});
// 注册播放完毕后的监听事件
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mediaPlayer.release();
mediaPlayer = null;
bt_play.setEnabled(true);
bt_play.setClickable(true);
et_time.setBase(SystemClock.elapsedRealtime());
et_time.start();
et_time.stop();
sb.setProgress(0);
sb.setEnabled(false);
}
});
} else {
Toast.makeText(getApplicationContext(), "文件不存在", 0).show();
return;
}
}
private class MyListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
// 音乐播放器暂停
pause();
break;
case TelephonyManager.CALL_STATE_IDLE:
// 重新播放音乐
pause();
break;
}
}
}
public void onChronometerTick(Chronometer chronometer) {
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO 自动生成的方法存根
if (fromUser == true && mediaPlayer != null) {
mediaPlayer.seekTo(progress);
falgTime = SystemClock.elapsedRealtime() - sb.getProgress();
et_time.setBase(falgTime);
subtime = 0;
et_time.start();
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO 自动生成的方法存根
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="请输入音乐的路径" />
<Chronometer
android:id="@+id/et_time"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/et_path"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="/sdcard/e.mp3" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal" >
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放" />
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="暂停" />
<Button
android:id="@+id/replay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重播" />
<Button
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止" />
</LinearLayout>
</LinearLayout>
使用SoundPool播放音效:
在Android开发中我们经常使用MediaPlayer来播放音频文件,但是MediaPlayer存在一些不足,例如:资源占用量较高、延迟时间较长、不支持多个音频同时播放等。这些缺点决定了MediaPlayer在某些场合的使用情况不会很理想,例如在对时间精准度要求相对较高的游戏开发中。
在游戏开发中我们经常需要播放一些游戏音效(比如:子弹爆炸,物体撞击等),这些音效的共同特点是短促、密集、延迟程度小。在这样的场景下,我们可以使用SoundPool代替MediaPlayer来播放这些音效。
SoundPool(android.media.SoundPool),顾名思义是声音池的意思,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU资源占用量低和反应延迟小。另外,SoundPool还支持自行设置声音的品质、音量、播放比率等参数,支持通过ID对多个音频流进行管理。
就现在已知的资料来说,SoundPool有一些设计上的BUG,从固件版本1.0开始有些还没有修复,我们在使用中应该小心再小心。相信将来Google会修复这些问题,但我们最好还是列出来:
1. SoundPool最大只能申请1M的内存空间,这就意味着我们只能用一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
2. SoundPool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。建议使用这两个方法的时候尽可能多做测试工作,还有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
3. SoundPool的效率问题。其实SoundPool的效率在这些播放类中算是很好的了,但是有的朋友在G1中测试它还是有100ms左右的延迟,这可能会影响用户体验。也许这不能管SoundPool本身,因为到了性能比较好的Droid中这个延迟就可以让人接受了。
在现阶段SoundPool有这些缺陷,但也有着它不可替代的优点,基于这些我们建议大在如下情况中多使用SoundPool:
在游戏开发中我们经常需要播放一些游戏音效(比如:子弹爆炸,物体撞击等),这些音效的共同特点是短促、密集、延迟程度小。在这样的场景下,我们可以使用SoundPool代替MediaPlayer来播放这些音效。
SoundPool(android.media.SoundPool),顾名思义是声音池的意思,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU资源占用量低和反应延迟小。另外,SoundPool还支持自行设置声音的品质、音量、播放比率等参数,支持通过ID对多个音频流进行管理。
就现在已知的资料来说,SoundPool有一些设计上的BUG,从固件版本1.0开始有些还没有修复,我们在使用中应该小心再小心。相信将来Google会修复这些问题,但我们最好还是列出来:
1. SoundPool最大只能申请1M的内存空间,这就意味着我们只能用一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
2. SoundPool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。建议使用这两个方法的时候尽可能多做测试工作,还有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
3. SoundPool的效率问题。其实SoundPool的效率在这些播放类中算是很好的了,但是有的朋友在G1中测试它还是有100ms左右的延迟,这可能会影响用户体验。也许这不能管SoundPool本身,因为到了性能比较好的Droid中这个延迟就可以让人接受了。
在现阶段SoundPool有这些缺陷,但也有着它不可替代的优点,基于这些我们建议大在如下情况中多使用SoundPool:
1.应用程序中的声效(按键提示音,消息等)2.游戏中密集而短暂的声音(如多个飞船同时爆炸)
开发步骤:
1> 往项目的res/raw目录中放入音效文件。
2> 新建SoundPool对象,然后调用SoundPool.load()加载音效,调用SoundPool.play()方法播放指定音效文件。
public class AudioActivity extends Activity {
private SoundPool pool;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//指定声音池的最大音频流数目为10,声音品质为5
pool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
final int sourceid = pool.load(this, R.raw.pj, 0);//载入音频流,返回在池中的id
Button button = (Button)this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//播放音频,第二个参数为左声道音量;第三个参数为右声道音量;第四个参数为优先级;第五个参数为循环次数,0不循环,-1循环;第六个参数为速率,速率最低0.5最高为2,1代表正常速度
pool.play(sourceid, 1, 1, 0, -1, 1);
}
});
}
}
1> 往项目的res/raw目录中放入音效文件。
2> 新建SoundPool对象,然后调用SoundPool.load()加载音效,调用SoundPool.play()方法播放指定音效文件。
public class AudioActivity extends Activity {
private SoundPool pool;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//指定声音池的最大音频流数目为10,声音品质为5
pool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
final int sourceid = pool.load(this, R.raw.pj, 0);//载入音频流,返回在池中的id
Button button = (Button)this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//播放音频,第二个参数为左声道音量;第三个参数为右声道音量;第四个参数为优先级;第五个参数为循环次数,0不循环,-1循环;第六个参数为速率,速率最低0.5最高为2,1代表正常速度
pool.play(sourceid, 1, 1, 0, -1, 1);
}
});
}
}
使用SoundPool播放音效代码示例:
DemoActivity.java:
package cn.itcast.soundpool;
import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.View;
public class DemoActivity extends Activity {
int soundid;
SoundPool pool;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pool = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
// 这语句代码 是一个异步的操作
soundid = pool.load(this, R.raw.ring, 1); // 需要花费一定的时间
}
public void shoot(View view) {
// 不会播放 因为上面异步的加载声音的操作 还没完成
pool.play(soundid, 1.0f, 1.0f, 0, 0, 1.0f);
// taking tom
}
}