• MediaPlayer播放音频的基本使用
  • 音乐播放器的完善
  • 视频播放SurfaceView
  • 视频播放VideoView
  • vitamio框架
  • 如何调用照相机和录像机

MediaPlayer播放音频的基本使用

MediaPlayer播放音频的基本使用步骤:
①创建一个MediaPlayer实例
②设置播放的数据格式
③设置数据源
④准备播放
⑤开始播放

整体的示例代码很简单:

// 1. 创建一个音频播放器实例
final MediaPlayer player = new MediaPlayer();
// 2. 设置数据格式
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource("/mnt/sdcard/zxxpg.mp3");// 此处也可以是网络路径
// player.prepare(); // 此处会阻塞主线程,建议prepareAsync
player.prepareAsync();
// 4. 当准备成功后回调
player.setOnPreparedListener(new OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {// 5. 开始播放player.start();}
});

音乐播放器的完善

下面是音乐播放器案例教完善的实现,当然这也只是个玩具程序,还缺少很多很多功能。

该案例的实现分为以下几步:
①点击播放、暂停、继续按钮达到播放、暂停、继续的目的
②增加进度条,让进度随着播放进度而调整
③手指拖动进度条时,可以修改播放的位置。
④使用文字显示当前播放进度

本来想把代码直接贴出来完事的,但是感觉这样不太好,了解代码的演化过程可能是对自己最好的锻炼。

由于这个小案例是在之前案例的基础之上修改过来了,所以先把骨架代码贴出来,然后再一步一步增加功能。

IService接口如下

public interface IService {public void callPlay();public void callPause();public void callReplay();
}

MainActivity类如下:

public class MainActivity extends Activity implements OnSeekBarChangeListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);// 启动和绑定服务Intent service = new Intent(this, MusicService.class);startService(service);conn = new MyServiceConnection();bindService(service, conn, Context.BIND_AUTO_CREATE);}// 播放public void play(View v) {iService.callPlay();}// 暂停public void pause(View v) { iService.callPause();}// 重新播放public void replay(View v) {    iService.callReplay();}private class MyServiceConnection implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {iService = (IService) service; }@Overridepublic void onServiceDisconnected(ComponentName name) {}}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(conn);}
}

MusicService类文件如下:

public class MusicService extends Service {@Overridepublic void onCreate() {super.onCreate();}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}// 播放音乐public void play() {}// 暂停public void pause() {}// 继续播放public void replay() {}// 中间人private class MyBinder extends Binder implements IService {@Overridepublic void callPlay() {    play(); }@Overridepublic void callPause() {pause();}@Overridepublic void callReplay() {replay();}}
}

activity_main.xml文件如下:

<LinearLayout 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:orientation="vertical"tools:context=".MainActivity" ><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="play"android:text="播放音乐" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="pause"android:text="暂停播放" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="replay"android:text="继续播放音乐" />
</LinearLayout>

整体来说骨架代码还是很简单的,当应用启动时会启动并绑定服务,这样就可以通过中间人来调用服务中的方法了。

接下来就一步一步添加功能。

第一步,点击播放、暂停、继续按钮达到播放、暂停、继续的目的

首先回想一下如何播放音乐文件:初始化MediaPlay实例,配置数据源、类型,准备一下,然后就可以start播放了。

那么在这一步中,可以在服务的onCreate()方法中,实例化MediaPlay对象;当调用播放时,初始化资源并播放;暂停和继续播放就很简单了,只需要调用相应的方法就OK了。

增加的代码如下:

// 播放器实例
private MediaPlayer mediaPlayer;
@Override
public void onCreate() {super.onCreate();// 初始化实例对象mediaPlayer = new MediaPlayer();
}// 播放
public void play() {
try {// 重置资源mediaPlayer.reset();// 初始化配置mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDataSource("/mnt/sdcard/zuoqujia.mp3");// 准备mediaPlayer.prepareAsync();// 准备完成的回调mediaPlayer.setOnPreparedListener(new OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {mediaPlayer.start();}});} catch (Exception e) {e.printStackTrace();}
}// 暂停播放
public void pause() {mediaPlayer.pause();}// 继续播放
public void replay() {mediaPlayer.start();}

第二步,增加进度条,让进度随着播放进度而调整

其实增加一个进度条是很简单的,直接拖一个SeekBar就可以达到目的。但是怎么样在服务中达到修改UI的目的却是这一步的难点,此外,SeekBar的进度条是要实时更新的,这些都是这一步的关键。

仔细回想一下之前的知识点,我们可以使用Handler在子线程中修改UI线程的数据,但是服务中怎么获取到Handler?可以这样,把MainActivity中的Handler改变为静态变量,这样就可以在服务类中使用了。

音乐播放要求每秒更新一次进度条的位置,我们可以使用SE中的Timer和TimerTask达到此目的。

有了以上这些解决问题的技术,赶快来看看代码是怎么写的。

首先在布局文件中加入SeekBar控件,并在MainActivity的找到该控件。

<SeekBar
    android:id="@+id/sb_progress"android:layout_width="match_parent"android:layout_height="wrap_content" />
private static SeekBar sbProgress; // 进度条protected void onCreate(Bundle savedInstanceState) {... ...sbProgress = (SeekBar) findViewById(R.id.sb_progress);... ...
}

然后在MainActivity中增加静态的Handler,在MusicService类增加发送消息的逻辑。

MainActivity类增加如下内容:

private static int duration; // 歌曲总时长,毫秒单位 private static int currentPosition; // 歌曲当前进度,毫秒单位public static Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case MusicService.CURRENTPOSITION: // 设置进度// 获取消息、更新进度条、更新当前播放位置currentPosition = msg.arg1;sbProgress.setProgress(currentPosition);break;case MusicService.DURATION: // 设置总时长duration = msg.arg1;sbProgress.setMax(duration);break;default:break;}};
};

MusicService增加如下代码

public static final int DURATION = 0; // 音乐总时长
public static final int CURRENTPOSITION = 1;//音乐当前播放位置public void play() {try {// 重置mediaPlayer.reset();// 初始化mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDataSource("/mnt/sdcard/zuoqujia.mp3");// 准备mediaPlayer.prepareAsync();// 准备完成的回调mediaPlayer.setOnPreparedListener(new OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {// 开始播放mediaPlayer.start();// 获取音乐总进度,并发送消息int duration = mediaPlayer.getDuration();Message msg = Message.obtain();msg.what = DURATION;msg.arg1 = duration;MainActivity.handler.sendMessage(msg);// 每隔一秒更新进度Timer timer = new Timer();TimerTask task = new TimerTask() {@Overridepublic void run() {//  获取当前进度,并发送消息更新UIint currentPosition = mediaPlayer.getCurrentPosition();Message msg = Message.obtain();msg.what = CURRENTPOSITION;msg.arg1 = currentPosition;MainActivity.handler.sendMessage(msg);}};// 每隔一秒钟调用一次timer.schedule(task, 0, 1000);}});} catch (Exception e) {e.printStackTrace();}
}

做完这些,音乐播放时,进度到就会“动”了。

第三步,手指拖动进度条时,可以修改播放的位置。

达到这个目的,可以利用MediaPlayer中的seekTo()方法,定位播放位置。

那么我们需要做的很简单了,在IService中增加一个callSeekToProgress()方法,并在MainActivity和MusicService调用和编写。

IService增加如下内容:

public void callSeekToProgress(int currentPosition);

MainActivity增加如下内容:

// 把播放进度移动到指定位置
public void seekToProgress(int currentPosition) {iService.callSeekToProgress(currentPosition);
}

在MusicService增加如下内容:

// 中间人
private class MyBinder extends Binder implements IService {... ...@Overridepublic void callSeekToProgress(int currentPosition) {seekToProgress(currentPosition);}
}// 修改播放位置
public void seekToProgress(int currentPosition) {mediaPlayer.seekTo(currentPosition);
}

第四步,使用文字显示当前播放进度

写完上面这些,增加这个功能就略显容易了。在布局文件中增加一个TextView,然后再Handler消息处理时,设置其内容就可以了。

tvCurrentProgress.setText("音乐共" + (int)(duration / 1000.0f) + "秒/当前" + (int)(currentPosition / 1000.0f) + "秒");

视频播放(SurfaceView)

Android中的视频播放使用的还是MediaPlayer类,同时还借助了SurfaceView控件,而且遗憾的是它只支持3GP和MP4格式的文件。

代码也很简单,简单的看看一下吧

// 获取到控件
SurfaceView sfv = (SurfaceView) findViewById(R.id.sfv);// 播放器
final MediaPlayer mediaPlayer = new MediaPlayer();SurfaceHolder holder = sfv.getHolder();// 添加回调,当SurfaceView准备好时才播放
holder.addCallback(new Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}@Overridepublic void surfaceCreated(SurfaceHolder holder) {try {// 设置HoldermediaPlayer.setDisplay(holder);mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mediaPlayer.setDataSource("/mnt/sdcard/proto.3gp");mediaPlayer.prepare(); // might take long! (for buffering, etc)mediaPlayer.start();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
});

视频播放(VideoView)

上面的SurfaceView略显麻烦,Google为我们提供了另外一个封装的控件VideoView,只需要几行代码就可以轻松展示一个3GP或者MP4文件。

VideoView vv = (VideoView) findViewById(R.id.vv);
vv.setVideoPath("/mnt/sdcard/proto.3gp");
vv.start();

vitamio框架

Android原生的SurfaceView和VideoView,在播放视频格式上都有限制,只能播放3GP和MP4。

Vitamio是一款开源框架,由一大堆C大神开发的,其中提供了Andoird版本的类库支持。

其中有一个VideoView类,和Andoird中原生的VideoView方法差不多,但是完美支持市面上的各种视频格式。

<io.vov.vitamio.widget.VideoView
      android:id="@+id/vv"android:layout_width="wrap_content"android:layout_height="wrap_content" />
io.vov.vitamio.widget.VideoView vv = (VideoView) findViewById(R.id.vv);vv.setVideoPath("/mnt/sdcard/test.3gp");

使用方法也是超级简单。

如何调用照相机和录像机

//就是利用隐式意图 去开启手机的自带的相机应用
//如果是照相
//创建意图对象
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory().getPath(),"paizhao.png"))); // set the image file name
//开启意图   获取结果
startActivityForResult(intent, 0);//如果是录像
//创建意图对象
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory().getPath(),"luxiang.3gp"))); // set the image file name//开启意图   获取结果
startActivityForResult(intent, 0);

Android基础笔记(十七)- 多媒体编程相关推荐

  1. Bootstrap基础二十七 多媒体对象(Media Object)

    Bootstrap<基础二十七> 多媒体对象(Media Object) 原文:Bootstrap<基础二十七> 多媒体对象(Media Object) Bootstrap 中 ...

  2. android基础笔记

    1       拨打电话 Intent意图 //系统统一调用程序的一个类 Stringnumber="13138794688"; Intent intent=new Intent( ...

  3. 【Android基础笔记01】Android开发环境搭建和HelloWorld

    最近手头项目3.0版本要上线了, 没有那么多工作压力了, 抽空看了看之前在云笔记上做的笔记 都是一些基础知识 给大家分享出来吧 一.什么是Android?[了解 ] Android(中文俗称安卓)是一 ...

  4. Android学习笔记十七.使用ContentProvider实现数据共享(四).操作系统(联系人)的ContentProvider

        Android系统本身提供了大量的ContentProvider,例如联系人信息.系统的多媒体信息等,我们开发的应用程序主要是通过ContentResolver来调用系统的ContentPro ...

  5. android基础笔记1

    1.       在模拟器中安装apk文件: G:\work\android-sdk-windows\platform-tools里有个adb.exe工具 Adb install G:\work\Cr ...

  6. 【Android基础】应用界面编程

    介绍 本章会介绍Android程序界面和很多组件的知识,是界面需要的知识. 通过学习本章的知识,可以开发出漂亮的图形用户界面,这些图形用户界面是Android应用开发的基础,也是非常重要的组成部分. ...

  7. android开发笔记之多媒体—图形图像处理

    --图像的两种分类: 位图 例子:单色位图(只有两种颜色(黑白),每一个像素点占一位)256位图(每一个像素点有256个颜色,每一个像素点需要占一个字节)24位位图(每个像素点占3个字节)位图图像(b ...

  8. Android学习笔记——手机多媒体运用

    参考书籍:Android第一行代码(第二版).郭霖著 1.通知 Notification是Android中较有特色的功能,当应用程序希望向用户发出提示信息但不在前台运行时可使用(手机顶部显示通知图标, ...

  9. android开发笔记之网络编程—简易新闻客户端

    今天我们来对前面讲过的知识综合运用一下,包括xml的PULL解析,listView的万能适配器等知识.... 那先来看一个组件-->智能图片加载器(smart-image-view),它可以很方 ...

最新文章

  1. HAAR、LBP分类器训练
  2. JVM 史上最最最完整知识总结!
  3. 跟着 Github 学习 Restful HTTP API 的优雅设计
  4. android activity启动模式_从0系统学Android--2.5Activity启动模式
  5. 矩池云上编译安装dlib库
  6. 档案盒正面标签制作_如何制作差异化的短视频内容?
  7. AtCoder Grand Contest 018 A
  8. 一张图搞懂美国大数据产业(上)
  9. IDEA java 中文乱码解决方法
  10. JavaScript逻辑训练题(二)
  11. diskgenius扩容c盘重启电脑卡住_DiskGenius怎么给C盘扩容?DiskGenius无损调整C盘容量方法 (全文)...
  12. 个人博客详细文章目录索引(持续更新)
  13. QNX 7.1 交叉编译 cron
  14. 如何将图片变成GIF图?一键完成gif制作
  15. 复习——哈夫曼树及哈夫曼编码
  16. CSS首字母下沉怎么设置?
  17. 重识JavaScript(一)
  18. 利用硬件机器人实现网络试衣
  19. Selenium WebDrive学习(一)
  20. 盲打软件测试自学,GS Typing Tutor(打字练习测试软件) V3.1 官方版

热门文章

  1. 北理Todo::待办管理系统
  2. 前端利用numeral处理数字和时间格式化
  3. 下拉选框样式html,超酷select选择下拉框美化jQuery插件
  4. 常见胸肌问题解答(一):厚度不够
  5. 嫌自己的签名不好看?那就用Python给自己设计一个专属签名
  6. flutter开发工具,2020年最全Android面试攻略
  7. R语言 cannot take a sample larger than the population when ‘replace = FALSE‘
  8. Python-docx
  9. java调用hp打印机驱动_Java Equip.getHp方法代码示例
  10. mc一进服务器就未响应,大佬们这得怎么办啊,一进服务器游戏就崩溃,