学习Android MediaPlayer

Android Media Playback

原文

The Android multimedia framework includes support for playing variety of common media types, so that you can easily integrate audio, video and images into your applications. You can play audio or video from media files stored in your application's resources (raw resources), from standalone files in the filesystem, or from a data stream arriving over a network connection, all using MediaPlayer APIs.

Android多媒体框架包含对多种常见媒体类型的支持,所以你可以容易的在自己的应用中集成音频,视频和图片。你可以播放应用内的资源文件,或文件系统中独立的文件,也可以通过网络数据流来播放,这些功能都使用MediaPlayer APIs实现。

Note: You can play back the audio data only to the standard output device. Currently, that is the mobile device speaker or a Bluetooth headset. You cannot play sound files in the conversation audio during a call.

注意:你只能通过标准输出设备播放音频。当前,这包括移动设备的扬声器或者蓝牙耳机。你不能在用户打电话时播放音频。


The Basics

在Android Framework中,下面两个类用来播放声音和视频:

MediaPlayer  此类是播放声音和视频的主要API。

AudioManager 此类管理音频资源和音频在设备上的输出。


Manifest Declarations

Before starting development on your application using MediaPlayer, make sure your manifest has the appropriate declarations to allow use of related features.

在开始使用MediaPlayer之前,确保你的清单文件中声明了与相关特性有关的权限:

  • Internet Permission - 如果你使用MediaPlayer播放网络内容,应用需要网络访问权限。

  • Wake Lock Permission - 如果你的应用需要保持屏幕不变暗或者处理器不休眠,或者使用MediaPlayer.setScreenOnWhilePlaying()MediaPlayer.setWakeMode()方法,你需要请求以下权限:


Using MediaPlayer

One of the most important components of the media framework is the MediaPlayer class. An object of this class can fetch, decode, and play both audio and video with minimal setup. It supports several different media sources such as:

媒体框架中最重要的组件之一是MediaPlayer类。该类的对象可以用最少的步骤获取,解码和播放音频和视频。它支持多种媒体源,例如:

  • 本地资源

  • 内部URI,例如用于Content Resolver的URI

  • 外部URL(流)

Android支持的媒体类型,见此文档:Android Supported Media Formats。

下面的例子显示了如何播放本地raw资源(应用res/raw目录下)

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you

本例中,一个“raw”资源是一个系统不会尝试用特殊方式去解析的文件。然而,此资源的内容不能是原始音频。它应该是根据支持的格式恰当编码和格式化的文件。

下面的例子显示如何通过本地URI播放:

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();

下面的例子显示如何通过HTTP访问URL来播放:

String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

注意:如果你通过URL播放在线媒体文件,该文件必须可以渐近下载(Progressive download)。

警告:在使用setDataSource()时,必须捕获或者传递IllegalArgumentException和IOException,因为你引用的文件可能不存在。


Asynchronous Preparation

Using MediaPlayer can be straightforward in principle. However, it's important to keep in mind that a few more things are necessary to integrate it correctly with a typical Android application. For example, the call to prepare() can take a long time to execute, because it might involve fetching and decoding media data. So, as is the case with any method that may take long to execute, you should never call it from your application's UI thread.

原则上,使用MediaPlayer是简单直接的。然而集成在Android应用中时,有几点需要注意。例如,调用prepare()可能会花费很长时间,因为此方法涉及到媒体数据的获取和解码,因此不应该在UI线程调用。

To avoid hanging your UI thread, spawn another thread to prepare the MediaPlayer and notify the main thread when done. However, while you could write the threading logic yourself, this pattern is so common when using MediaPlayer that the framework supplies a convenient way to accomplish this task by using the prepareAsync() method. This method starts preparing the media in the background and returns immediately. When the media is done preparing, the onPrepared() method of the MediaPlayer.OnPreparedListener, configured through setOnPreparedListener() is called.

要避免挂起UI线程,使用另一个线程来准备MediaPlaer,在完成时通知主线程。然而,虽然你可以自己写线程逻辑,此框架提供了prepareAsync方法来简化这一工作。此方法立刻返回,在后台执行准备工作,完成后通过回调通知调用者。


Managing State

Another aspect of a MediaPlayer that you should keep in mind is that it's state-based. That is, the MediaPlayer has an internal state that you must always be aware of when writing your code, because certain operations are only valid when then player is in specific states. If you perform an operation while in the wrong state, the system may throw an exception or cause other undesireable behaviors.

关于MediaPlayer的另一个关注点是它是基于状态的。也就是说,你写代码时必须始终意识到MediaPlayer有内部状态,因为某些操作只在player处于特定状态时才有效。如果你在错误的状态下执行操作,系统可能会抛出异常或者引发其他不需要的行为。

MediaPlayer类文档中展示了MediaPlayer的完整状态图。

Releasing the MediaPlayer

A MediaPlayer can consume valuable system resources. Therefore, you should always take extra precautions to make sure you are not hanging on to a MediaPlayer instance longer than necessary. When you are done with it, you should always call release() to make sure any system resources allocated to it are properly released. For example, if you are using a MediaPlayer and your activity receives a call to onStop(), you must release the MediaPlayer, because it makes little sense to hold on to it while your activity is not interacting with the user (unless you are playing media in the background, which is discussed in the next section). When your activity is resumed or restarted, of course, you need to create a new MediaPlayer and prepare it again before resuming playback.

MediaPlayer会消费宝贵的系统资源,所以必须注意不要保持MediaPlayer实例超过需要的时间。当你用完时,应该调用release()方法来确保分配给它的系统资源被合适的释放了。例如,如果你正在使用MediaPlayer,而Activity收到了onStop()回调,则必须释放MediaPlayer(除非你在后台播放)。当Activity 重新获得焦点或者重新开始时,你需要创建一个新的MediaPlayer实例,并在恢复播放前准备它。

将MediaPlayer释放并制空:

mediaPlayer.release();
mediaPlayer = null;

As an example, consider the problems that could happen if you forgot to release the MediaPlayer when your activity is stopped, but create a new one when the activity starts again. As you may know, when the user changes the screen orientation (or changes the device configuration in another way), the system handles that by restarting the activity (by default), so you might quickly consume all of the system resources as the user rotates the device back and forth between portrait and landscape, because at each orientation change, you create a new MediaPlayer that you never release.

例如,如果你在Activity stop时忘了释放MediaPlayer,但在Activity create时创建了新的实例,那在用户反复旋转屏幕时,可能会很快就耗尽所有的系统资源,因为每次方向改变,你都创建了新的MediaPlayer对象,但从来没有释放。

Using a Service with MediaPlayer

If you want your media to play in the background even when your application is not onscreen—that is, you want it to continue playing while the user is interacting with other applications—then you must start a Service and control the MediaPlayer instance from there. You should be careful about this setup, because the user and the system have expectations about how an application running a background service should interact with the rest of the system. If your application does not fulfil those expectations, the user may have a bad experience. This section describes the main issues that you should be aware of and offers suggestions about how to approach them.

如果想让媒体文件在后台播放,需要启动一个Service,让后再Service中控制MediaPlayer实例。用户和系统对运行后台服务的应用如何同系统其它部分交互有一些期望,如果你的应用无法满足这些期望,用户可能会有糟糕的体验。本节描述了你需要注意的主要事项以及如何解决的建议。

Running asynchronously

First of all, like an Activity, all work in a Service is done in a single thread by default—in fact, if you're running an activity and a service from the same application, they use the same thread (the "main thread") by default. Therefore, services need to process incoming intents quickly and never perform lengthy computations when responding to them. If any heavy work or blocking calls are expected, you must do those tasks asynchronously: either from another thread you implement yourself, or using the framework's many facilities for asynchronous processing.

首先,同Activity一样,默认情况下Service中的所有工作也是在主线程中完成的。因此,服务需要快速的处理传入的intent,在响应意图是不能执行长时间操作。如果有大量的工作或者阻塞式的调用,就需要异步的完成。

For instance, when using a MediaPlayer from your main thread, you should call prepareAsync() rather than prepare(), and implement a MediaPlayer.OnPreparedListener in order to be notified when the preparation is complete and you can start playing. For example:

例如,在主线程中使用MediaPlayer时,你应该调用prepareAsync()而不是prepare(),实现MediaPlayer.OnPreparedListener接口来通知准备已经完成。代码如下:

public class MyService extends Service implements MediaPlayer.OnPreparedListener {private static final String ACTION_PLAY = "com.example.action.PLAY";MediaPlayer mMediaPlayer = null;public int onStartCommand(Intent intent, int flags, int startId) {...if (intent.getAction().equals(ACTION_PLAY)) {mMediaPlayer = ... // initialize it heremMediaPlayer.setOnPreparedListener(this);mMediaPlayer.prepareAsync(); // prepare async to not block main thread}}/** Called when MediaPlayer is ready */public void onPrepared(MediaPlayer player) {player.start();}
}

Handling asynchronous errors

On synchronous operations, errors would normally be signaled with an exception or an error code, but whenever you use asynchronous resources, you should make sure your application is notified of errors appropriately. In the case of a MediaPlayer, you can accomplish this by implementing a MediaPlayer.OnErrorListener and setting it in your MediaPlayer instance:

在同步的调用中,错误通常是通过异常或者错误码表示,但在异步调用时,你应该确保正确的接收到错误。对于MediaPlayer来说,你可以实现MediaPlayer.OnErrorListener接口,设置给MediaPlayer实例:

public class MyService extends Service implements MediaPlayer.OnErrorListener {MediaPlayer mMediaPlayer;public void initMediaPlayer() {// ...initialize the MediaPlayer here...mMediaPlayer.setOnErrorListener(this);}@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {// ... react appropriately ...// The MediaPlayer has moved to the Error state, must be reset!}
}

It's important to remember that when an error occurs, the MediaPlayer moves to the Error state (see the documentation for the MediaPlayer class for the full state diagram) and you must reset it before you can use it again.

要记住当错误发生时,MediaPlayer转变为Error状态,在你使用它之前需要重置(reset)它。

转载于:https://www.cnblogs.com/yuanchongjie/p/5089476.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spark2.0.1 安装配置

1. 官网下载 wget http://d3kbcqa49mib13.cloudfront.net/spark-2.0.1-bin-hadoop2.7.tgz 2. 解压 tar -zxvf spark-2.0.1-bin-hadoop2.7.tgz ln -s spark-2.0.1-bin-hadoop2.7 spark2 3. 环境变量 vi /etc/profile #Spark 2.0.1export SPARK_HOME/usr/local/spark2export PATH…

Spring Cloud各组件超时

Ribbon的超时 全局设置: ribbon:ReadTimeout: 60000ConnectTimeout: 60000局部设置: service-id:ribbon:ReadTimeout: 1000ConnectTimeout: 1000其中,service-id 是Ribbon所使用的虚拟主机名,一般和Eureka Server上注册的服务名称…

【图像处理】——遍历图像所有像素的方法(for 循环和np.where遍历)应用在模板制作

目录 具体np.where的用法可以参见: 其他遍历图像的所有像素的方法: 模板制作流程 Python代码

C++总结笔记(五)——构造函数和析构函数

文章目录前言一、基本概念1 构造函数2 析构函数二、示例1. 构造函数和析构函数的简单使用2. 拷贝构造函数的调用3. 浅拷贝和深拷贝前言 本文讲述了构造函数和析构函数的概念以及对应的示例,以便加深理解。 一、基本概念 1 构造函数 构造函数用于初始化类的对象&a…

LINUX 更新

sudo apt-get dist-upgrade,更新所有的软件转载于:https://www.cnblogs.com/jackieron/p/5997805.html

python实战===如何优雅的打飞机

这是一个打飞机的游戏,结构如下: 其中images中包含的素材为 命名为alien.png 命名为ship.png 游戏效果运行是这样的: 敌军,也就是体型稍微大点的,在上方左右移动,并且有规律向下移动。我军目标,…

【图像处理】——上采样、下采样、在模板匹配中的金字塔加速策略

目录 1、下采样 Python自带函数 自定义函数 Python实现下采样 2、上采样 Python自带函数 自定义函数<

C++总结笔记(六)——友元

文章目录前言一、基本概念二、程序示例1.全局函数调用私有成员2. 外部类调用私有成员3. 外部类的成员函数调用私有成员总结前言 一、基本概念 友元是C中为了方便类外的类或者函数访问类内私有成员而定义的一种特殊语法&#xff0c;用friend关键字进行修饰。 二、程序示例 友…

Java默认类型,类型转换,常量与变量笔记

默认类型&#xff1a; 在java里整数默认是int类型&#xff0c;小数默认是double类型&#xff0c;单个字符默认是char类型&#xff0c;true、false自然默认的是boolean类型&#xff0c;字符串默认的是String类型。 变量和常量类型转换&#xff1a; 因为有默认类型&#xff0c;在…

【图像处理】——Python实现灰度特征提取

目录 1、灰度特征 2、Python代码 1、灰度特征 2、Python代码 import cv2 import numpy as npdef gray_features(img):hist = cv2.calcHist([img],[0],None,[256],[0,255])#得到全局直方图统计数据

C++总结笔记(七)—— 运算符重载

文章目录一、概念二、程序示例1. 加减乘除重载2. 赋值运算符重载3. 递增递减运算符重载4. 关系运算符重载5. 左移运算符重载6. 函数调用运算符重载一、概念 C中运算符重载是为了实现对象之间进行各种运算的特定语法&#xff0c;在某些特定的场合起到重要的作用&#xff0c;新建…

asp.net 加载xml到menu

XML File <?xml version"1.0" encoding"utf-8" ?> <Area iAreaID "0" cAreaName"城市"><Province iAreaID "1" cAreaName"北京市"/><Province iAreaID "2" cAreaName"上海…

前端lvs访问多台nginx代理服务时出现404错误的处理

前端lvs访问多台nginx代理服务时出现404错误的处理 环境描述&#xff1a;app --> lvs --> nginx --> server app访问页面购买流量页面(nginx服务器)代理到后端和服务器交互(多台server)刚开始访问没有问题&#xff0c;流量变大为了避免出现问题&#xff0c;nginx配置了…

使用numpy出现DeprecationWarning: The normed argument is ignored when density is provided. 解决方法忽略警告的方法

目录 1、从根本上进行解决 2、直接利用warning模块忽略警告 1、从根本上进行解决 “DeprecationWarning: The normed argument is ignored when density is provided. In future passing both will result in an error.” 这种一般是因为函数库或者是一些包package版本更新而…

iptables四个表与五个链间的处理关系

转载自&#xff1a;http://www.linuxidc.com/Linux/2012-08/67505.htm netfilter/iptables IP 信息包过滤系统是一种功能强大的工具&#xff0c;可用于添加、编辑和除去规则&#xff0c;这些规则是在做信息包过滤决定时&#xff0c;防火墙所遵循和组成的规则。 这些规则存储在专…

C++总结笔记(八)—— 菱形继承

文章目录一、基本概念二、程序举例1. 虚继承2. 内在逻辑一、基本概念 菱形继承是指存在两个子类继承自同一个基类&#xff0c;同时有子类继承这两个子类。 二、程序举例 1. 虚继承 使用虚继承可以解决菱形继承资源浪费的问题&#xff0c;因为有两个子类继承基类&#xff0c…

Linux命令:mkdir

全称&#xff1a;make directories 用途&#xff1a;创建新目录 格式&#xff1a;mkdir [OPTION]... DIRECTORY... 类型&#xff1a;mkdir is hashed (/bin/mkdir) 说明&#xff1a; 创建文件目录&#xff0c;较常用的选项参数有两个&#xff1a; -m, --modeMODE&#xff1a;直…

InnoDB引擎与MyIASM的一点总结

InnoDB引擎&#xff1a; 提供了对数据库ACID事务的支持&#xff0c;并且实现了SQL标准的四种隔离级别 提供了行级锁和外键约束。 它的设计的目标是处理大容量数据库系统&#xff0c;用于缓冲数据和索引。 不支持FULLTEXT类型的数据&#xff0c;没有保存表的行数&#xff0c;当s…

C++总结笔记(九)—— 多态

文章目录一、多态是什么&#xff1f;二、使用步骤2.1. 静态多态2.1.1 函数重载2.1.2 模板2.2.动态多态2.2.1 示例2.2.2 原理分析总结一、多态是什么&#xff1f; 多态是面向对象的语言中都必须掌握的特性&#xff0c;其概念简单讲就是对同一种特性的方法有不同的实现功能&…

[转]c++类的构造函数详解

c构造函数的知识在各种c教材上已有介绍&#xff0c;不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法&#xff0c;故在此我根据自己的c编程经验总结了一下c中各种构造函数的特点&#xff0c;并附上例子&#xff0c;希望对初学者有所帮助。 c类的构造函数详解 …