播放音频及视频我们会用到MediaPlayer和JetPlayer类,录制音频及视频我们会用到MediaRecorder类。文件的来源可以是本地文件系统文件、存储在Android中的资源文件,还可以是通过网络的文件流。
Android对常用媒体格式提供了支持,支持的图片格式有JPEG、GIF、PNG、BMP,支持的音频格式有3GP、MP3、WAV,支持的视频格式有3GP、MP4等。
一、音频及视频播放
1、从源文件中播放
1)、在项目的res/raw文件夹下放置一个Android支持的媒体文件,例如一个MP3文件
2)、创建一个MediaPlayer实例,可以使用MediaPlayer的静态方法create来完成
3)、调用start()方法开始播放,调用pause()方法暂停播放,调用stop()方法停止播放。如果希望重复播放,在调用start()方法之前,必须调用reset()和prepare()方法
//实例化MediaPlayer
MediaPlayer player = MediaPlayer.create(this, R.raw.music1);
//开始播放
player.start();
2、从文件系统中播放
例如在我们的SDCard中有一些音频及视频文件
1)、实例化一个MediaPlayer
2)、调用setDataSource()方法来设置想要播放文件的路径
3)、首先调用prepare(),然后调用start()来进行播放
//实例化MediaPlayer
MediaPlayer mp = new MediaPlayer();
//播放路径
String path = "/sdcard/music1.mp3";
//为MediaPlayer设置数据源
mp.setDataSource(path);
//准备
mp.prepare();
//播放
mp.start();
3、从网络中播放
方法一:1)、创建网络URI实例
2)、创建一个MediaPlayer实例,可以使用MediaPlayer的静态方法create,通过传递URI参数来完成
3)、调用start()方法开始播放
String path = "http://msl.m.mop.com/2008/08/27/012/music1.mp3";
Uri uri = Uri.parse(path);
MediaPlayer player = MediaPlayer.create(this,uri);
player.start();
方法二:1)、实例化一个MediaPlayer
2)、调用setDataSource()方法来设置想要播放文件的路径,改路径是网络上可用的路径
3)、首先调用prepare(),然后调用start()来进行播放
MediaPlayer mp = new MediaPlayer();
String path = "http://msl.m.mop.com/2008/08/27/012/music1.mp3";
mp.setDataSource(path);
mp.prepare();
mp.start();
二、迷你音乐播放器
具有控制界面的音乐播放器
public class MainActivity extends Activity implements OnCompletionListener {
//声明图片按钮ImageButton
private ImageButton playBtn,pauseBtn,stopBtn;
//声明MediaPlayer实例
private MediaPlayer mp;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
playBtn = (ImageButton) findViewById(R.id.play);
pauseBtn = (ImageButton) findViewById(R.id.pause);
stopBtn = (ImageButton) findViewById(R.id.stop);
playBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
play();
}
});
pauseBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
pause();
}
});
stopBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stop();
}
});
//准备
setup();
}
@Override
protected void onDestroy() {
super.onDestroy();
if(stopBtn.isEnabled()){
stop();
}
}
@Override
public void onCompletion(MediaPlayer mp) {
stop();
}
private void play(){
mp.start();
//使播放按钮失效
playBtn.setEnabled(false);
//使暂停按钮生效
pauseBtn.setEnabled(true);
//使停止按钮生效
stopBtn.setEnabled(true);
}
private void pause(){
mp.pause();
playBtn.setEnabled(true);
pauseBtn.setEnabled(false);
stopBtn.setEnabled(true);
}
private void stop(){
mp.stop();
pauseBtn.setEnabled(false);
stopBtn.setEnabled(false);
try {
//准备
mp.prepare();
//定位到开始
mp.seekTo(0);
playBtn.setEnabled(true);
} catch (Throwable t) {
error(t);
}
}
//加载播放文件
private void loadClip(){
try {
mp = MediaPlayer.create(this, R.raw.music1);
mp.setOnCompletionListener(this);
} catch (Throwable t) {
error(t);
}
}
//准备
private void setup(){
loadClip();
playBtn.setEnabled(true);
pauseBtn.setEnabled(false);
stopBtn.setEnabled(false);
}
//出错提示
private void error(Throwable t){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("报错啦!")
.setMessage(t.toString())
.setPositiveButton("确定",null)
.show();
}
}
<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="迷你音乐播放器" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageButton
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/play" />
<ImageButton
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/pause" />
<ImageButton
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stop" />
</LinearLayout>
</LinearLayout>
三、迷你视频播放器
借助VideoView和MediaController组件可以很方便的实现一个视频播放器
public class VideoActivity extends Activity {
private VideoView video;
//声明媒体控制组件
private MediaController ctlr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置窗口特征
getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.video);
//实例化file
File clip = new File("/sdcard/test.mp4");
//判断文件是否存在
if(clip.exists()){
video = (VideoView) findViewById(R.id.video);
video.setVideoPath(clip.getAbsolutePath());
ctlr = new MediaController(this);
//MediaController和MediaPlayer相互关联
ctlr.setMediaPlayer(video);
video.setMediaController(ctlr);
//使VideoView获得焦点
video.requestFocus();
}
}
}
vedio.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<VideoView
android:id="@+id/video"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
四、音视频的录制
通过MediaRecorder完成,常用的方法有:start()开始录制、pause()暂停录制、stop()停止录制、prepare()准备录制、reset()重新开始、release()释放资源等。
public class MainActivity extends Activity {
private ImageButton recordBtn,stopBtn;
private MediaRecorder mr;
private String path;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
recordBtn = (ImageButton) findViewById(R.id.l_record);
stopBtn = (ImageButton) findViewById(R.id.l_stop);
recordBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
record();//录制
}
});
stopBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
stop();
}
});
setup();//准备
}
//设置路径
private void setPath() throws IOException{
//路径为sd扩展卡
path = "/sdcard/test1.map3";
//获得sd扩展卡状态
String state = android.os.Environment.getExternalStorageState();
//判断是否安装扩展卡
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)){
throw new IOException("SD没有安装。它的状态是" + state);
}
//获得文件父目录
File directory = new File(path).getParentFile();
if(!directory.exists() && !directory.mkdirs()){
throw new IOException("文件不能被创建");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(stopBtn.isEnabled()){
stop();
}
}
//录制方法
private void record(){
try {
mr.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
mr.start();
recordBtn.setEnabled(false);
stopBtn.setEnabled(true);
}
//停止
private void stop(){
mr.stop();
stopBtn.setEnabled(false);
recordBtn.setEnabled(true);
mr.release();//释放资源
}
//设置属性
private void setProperty(){
try {
mr = new MediaRecorder();
//设置音频源
mr.setAudioSource(MediaRecorder.AudioSource.MIC);
//设置输出格式
mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//设置音频编码器
mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
//设置路径
setPath();
} catch (Throwable t) {
error(t);
}
//设置输出文件
mr.setOutputFile(path);
} catch (Throwable t) {
error(t);
}
}
//准备
private void setup(){
setProperty();
recordBtn.setEnabled(true);
stopBtn.setEnabled(false);
}
//错误提示
private void error(Throwable t){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("报错啦!")
.setMessage(t.toString())
.setPositiveButton("确定", null)
.show();
}
}
main.xml
<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="迷你录音器" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageButton
android:id="@+id/l_record"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/s" />
<ImageButton
android:id="@+id/l_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/stop" />
</LinearLayout>
</LinearLayout>
五、Camera照相
使用到了很多类,如下介绍:
- SurfaceView:该类是一个视图组件,实现了照片的预览功能
- SurfaceHolder:一个抽象接口,是SurfaceView的支持类,一般通过SurfaceView的getHolder()方法获得。允许你控制界面的尺寸和格式、编辑界面的像素,以及监控界面尺寸的改变
- SurfaceHolder.Callback:SurfaceHolder的一个内部接口,可以实现该接口获得界面改变的信息。该接口中有三个方法,surfaceCreated()方法在界面创建时被调用,一般在该方法中打开照相机并设置预览。surfaceChanged()方法在界面尺寸改变时被调用,一般在该方法中设置相机的参数(大小、格式等)。surfaceDestroyed()方法在界面被销毁时调用,在该方法中清除相机实例,释放资源
- Camera:相机类,实现拍照功能
- Camera.PictureCallback:Camera的一个内部接口,处理照片准备好后的回调
通过上面类的介绍,我们可以实现一个拍照程序。
public class CameraActivity extends Activity {
//声明拍照界面组件
private SurfaceView surfaceView;
//声明界面控制组件
private SurfaceHolder surfaceHolder;
//声明照相机
private Camera camera;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
surfaceView = (SurfaceView) findViewById(R.id.preview);
surfaceHolder = surfaceView.getHolder();
//实现SurfaceHolder.Callback回调接口,实现该接口中的三个方法
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
//打开照相机
camera = Camera.open();
try {
//设置预览
camera.setPreviewDisplay(holder);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//获取相机参数
Camera.Parameters parameters = camera.getParameters();
//设置照片大小
parameters.setPreviewSize(width, height);
//设置照片格式
parameters.setPreviewFormat(PixelFormat.JPEG);
//设置相机参数
camera.setParameters(parameters);
//开始预览
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
};
//为SurfaceHolder添加回调,并设置其类型
surfaceHolder.addCallback(surfaceCallback);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
//创建一个保存照片任务类,该类的主要功能是从硬件获得的字节流保存到设备文件中
class SavePictureTask extends AsyncTask<byte[], String, String>{
@Override
protected String doInBackground(byte[]... params) {
//创建文件
File picture = new File(Environment.getExternalStorageDirectory(),"picture.jpg");
//如果文件存在删除掉
if(picture.exists())
picture.delete();
try {
//获得文件输出流
FileOutputStream fos = new FileOutputStream(picture.getPath());
//写到该文件
fos.write(params[0]);
//关闭文件流
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
//实现Camera.PictureCallback回调方法,执行保存照片任务
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
new SavePictureTask().execute(data);
camera.startPreview();
}
};
//拍照方法
private void takePic(){
//停止预览
camera.stopPreview();
//拍照
camera.takePicture(null, null, pictureCallback);
}
//响应按键事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_CAMERA || keyCode == KeyEvent.KEYCODE_SEARCH){
takePic();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
camera.xml
<?xml version="1.0" encoding="utf-8"?>
<android.view.SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</android.view.SurfaceView>